When I run this console app, everything works fine but except for my UserAnswer() result. It keeps returning a value of '0' for both num1 & num2. This doesn't make sense to me because I don't receive any errors for declaring a new value for num1 & num2 in Input1() & Input2() methods. It compiles and runs fine but why is it not picking up the new values of these variables?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CalculatorApp
{
public class Program
{
float Number;
float num2;
float num1;
public static void Main(string[] args)
{
// Display title as the C# console calculator app.
Console.WriteLine("Console Calculator in C#\r");
Console.WriteLine("------------------------\n");
//Console.ReadKey();
// execute program functions
new Program().Input1();
new Program().Input2();
new Program().UserOption();
new Program().UserAnswer();
new Program().PromptUserExit();
}
// Ask the user to type the first number.
//Console.WriteLine("Type a number, and then press Enter");
public float Input1() {
Console.WriteLine("Type a number, and then press Enter");
bool Valid = false;
while (Valid == false)
{
string Input = Console.ReadLine();
if (!float.TryParse(Input, out Number))
{
Console.WriteLine("Not an integer, please try again.");
}
else
{
Valid = true;
num1 = (float)Convert.ToDecimal(Input);
}
} return num1;
}
public float Input2() {
// Ask the user to type the second number.
Console.WriteLine("Type another number, and then press Enter");
bool Valid2 = false;
while (Valid2 == false)
{
string Input2 = Console.ReadLine();
if (!float.TryParse(Input2, out Number))
{
Console.WriteLine("Not an integer, please try again.");
}
else
{
Valid2 = true;
num2 = (float)Convert.ToDecimal(Input2);
}
} return num2;
}
public void UserOption() {
// Ask the user to choose an option.
Console.WriteLine("Choose an option from the following list:");
Console.WriteLine("\ta - Add");
Console.WriteLine("\ts - Subtract");
Console.WriteLine("\tm - Multiply");
Console.WriteLine("\td - Divide");
Console.Write("Your option? ");
}
public void UserAnswer() {
bool isOperatorValid;
do
{
isOperatorValid = true;
switch (Console.ReadLine())
{
case "a":
Console.WriteLine($"Your result: {num1} + {num2} = " + (num1 + num2));
break;
case "s":
Console.WriteLine($"Your result: {num1} - {num2} = " + (num1 - num2));
break;
case "m":
Console.WriteLine($"Your result: {num1} * {num2} = " + (num1 * num2));
break;
case "d":
Console.WriteLine($"Your result: {num1} / {num2} = " + (num1 / num2));
break;
default:
Console.WriteLine("Invalid input please try again");
isOperatorValid = false;
break;
}
} while (!isOperatorValid);
}
public void PromptUserExit() {
// Wait for the user to respond before closing.
Console.Write("Press any key to close the Calculator console app...");
Console.ReadKey();
}
}
}
This is your problem:
new Program()
You are creating a new instance of the Program class every time you call a method. Each time, the variables are initialized with the default value of 0.
You need to initialize the class once, then use the same class:
var program = new Program();
program.Input1();
program.Input2();
program.UserOption();
program.UserAnswer();
program.PromptUserExit();
Or you could just make all of your methods and variables static so that you can call them directly without initializing a new object. In bigger programs, you would want to be careful with declaring things static (there is a time and place, but it's not "always"). But in a small program like this, it's fine.
Related
I'm a beginner c# programmer trying to program a simple app that shows a menu to the user. When option 1 is selected by the user at run-time, the program lists values from 0 to 100 Celsius degrees converted to Fahrenheit degrees. When option 2 is chosen, the program calculates and displays a list of values between 0 and 212 degrees in Fahrenheit converted to Celsius degrees. Use a constant for the values 100 and 212 in the related method.
The problem is that I'm only getting the option entered not a converted result. This is what I have done so far:
{
class TemperatureConverter
{
private const int columns = 1;
/// <summary>
///
///
///
/// </summary>
public TemperatureConverter()
{
Start();
}
/// <summary>
///
/// </summary>
public void Start()
{
while (true)
{
int choice = ShowMenu();
switch (choice)
{
case 0:
return;
case 1:
Console.WriteLine();
while (true)
{
Console.Write("Enter Celsius:");
Console.WriteLine();
if (double.TryParse(Console.ReadLine(), out double celsius))
{
Console.WriteLine(ShowTableCelsiusToFahrenheit(celsius));
Console.WriteLine();
break;
}
}
break;
case 2:
Console.WriteLine();
while (true)
{
Console.Write("Enter Fahrenheit:");
if (double.TryParse(Console.ReadLine(), out double fahrenheit))
{
Console.WriteLine(ShowTableFahrenheitToCelsius(fahrenheit));
Console.WriteLine();
break;
}
}
break;
default:
Console.WriteLine("You must enter 1 to convert to Celsius or 2 to convert to Fahrenheit or 0 to exit!");
break;
}
}
}
private double CelsiusToFarenheit(double celsius) => celsius * 9.0 / 5.0 + 32.0;
private double FahrenheitToCelsius(double fahrenheit) => (fahrenheit - 32.0) * 5.0 / 9.0;
private string ShowTableCelsiusToFahrenheit(double celsius) => $"{celsius}°C is {CelsiusToFarenheit(celsius)}°F";
private string ShowTableFahrenheitToCelsius(double fahrenheit) => $"{fahrenheit}°F is {FahrenheitToCelsius(fahrenheit)}°C";
public int ShowMenu()
{
int width = 28;
while (true)
{
Console.WriteLine("MAIN MENU");
Console.WriteLine("".PadLeft(width, '-'));
Console.WriteLine("Celsius to Fahrenheit".PadRight(width - 3) + ": 1");
Console.WriteLine("Fahrenheit to Celsius".PadRight(width - 3) + ": 2 ");
Console.WriteLine("Exit the program".PadRight(width - 3) + ": 0 ");
Console.WriteLine("".PadLeft(width, '-'));
Console.WriteLine();
Console.WriteLine("Your choice: ");
string line = Console.ReadLine();
if (int.TryParse(line, out int choice))
{
return choice;
}
}
}
}
}
I've done some refactoring for you so that you can see how this kind of code can be written. I've tried to logically extract the parts so there is a clear responsibility and flow for each part of the program.
I've also removed the automatic running of the code from the constructor. It's a bad idea to run code in the constructor other than code to set the initial conditions of the class.
Here's the refactored code:
void Main()
{
var tc = new TemperatureConverter();
tc.Start();
}
class TemperatureConverter
{
public void Start()
{
while (true)
{
int choice = ShowMenu();
switch (choice)
{
case 0:
return;
case 1:
Console.WriteLine();
while (true)
{
Console.Write("Enter Celsius:");
if (double.TryParse(Console.ReadLine(), out double celsius))
{
Console.WriteLine(GetCelsiusToFahrenheitLine(celsius));
Console.WriteLine();
break;
}
}
break;
case 2:
Console.WriteLine();
while (true)
{
Console.Write("Enter Fahrenheit:");
if (double.TryParse(Console.ReadLine(), out double fahrenheit))
{
Console.WriteLine(GetFahrenheitToCelsiusLine(fahrenheit));
Console.WriteLine();
break;
}
}
break;
default:
Console.WriteLine("You must enter 1 to convert to Celsius or 2 to convert to Fahrenheit or 0 to exit!");
break;
}
}
}
private double CelsiusToFarenheit(double celsius) => celsius * 9.0 / 5.0 + 32.0;
private double FahrenheitToCelsius(double fahrenheit) => (fahrenheit - 32.0) * 5.0 / 9.0;
private string GetCelsiusToFahrenheitLine(double celsius) => $"{celsius}°C is {CelsiusToFarenheit(celsius)}°F";
private string GetFahrenheitToCelsiusLine(double fahrenheit) => $"{fahrenheit}°F is {FahrenheitToCelsius(fahrenheit)}°F";
public int ShowMenu()
{
int width = 28;
while (true)
{
Console.WriteLine("MAIN MENU");
Console.WriteLine("".PadLeft(width, '-'));
Console.WriteLine("Celsius to Fahrenheit".PadRight(width - 3) + ": 1");
Console.WriteLine("Fahrenheit to Celsius".PadRight(width - 3) + ": 2 ");
Console.WriteLine("Exit the program".PadRight(width - 3) + ": 0 ");
Console.WriteLine("".PadLeft(width, '-'));
Console.WriteLine();
Console.WriteLine("Your choice: ");
string line = Console.ReadLine();
if (int.TryParse(line, out int choice))
{
return choice;
}
}
}
}
Now, this doesn't do what has been asked of you in the text in your question. I'll leave that to you. One hint on that - there is no need to read in any temperature as input from the user.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I made this Basic C# Calculator to reflect on what I've learned these past few days. I'm an absolute beginner and I wanted to get suggestions on improving and shortening it.
I've tried to add switch statements and multiple methods, but it has been really hard grasping them.
using System;
namespace lol
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hi! What is your name?");
string name = Console.ReadLine();
Console.WriteLine(name + " What do you wanna do?");
Console.WriteLine("Type \"+\" for addition");
Console.WriteLine("Type \"-\" for Subraction");
Console.WriteLine("Type \"*\" for Multiplication");
Console.WriteLine("Type \"/\" for division");
string operation = Console.ReadLine();
Console.Write("Now, Give me number one: ");
double num1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Now give me number two: ");
double num2 = Convert.ToDouble(Console.ReadLine());
if (operation == "+")
{
Console.WriteLine(num1 + num2);
}
else if (operation == "-")
{
Console.WriteLine(num1 - num2);
}
else if (operation == "*")
{
Console.WriteLine(num1 * num2);
}
else
{
Console.WriteLine(num1 / num2);
}
}
}
}
If it better for your eyes, you can write like that:
static class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hi! What is your name?");
string name = Console.ReadLine();
Console.WriteLine(name + " What do you wanna do?");
string[] operations = new string[] { "\"+\" for addition", "\"-\" for subtraction", "\"*\" for multiplication", "\"/\" for divsion" };
foreach (string operation in operations) { Console.WriteLine("Type " + operation); }
string cmd = Console.ReadLine();
Console.Write("Now, Give me number one: ");
double num1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Now give me number two: ");
double num2 = Convert.ToDouble(Console.ReadLine());
switch (cmd)
{
case "+": Console.WriteLine(num1 + num2); break;
case "-": Console.WriteLine(num1 - num2); break;
case "*": Console.WriteLine(num1 * num2); break;
case "/": Console.WriteLine(num1 / num2); break;
}
}
}
Using enums and checking if the user input is valid. I also added a loop that checks if the user wants to input equations.
References:
double.TryParse
Enum
Switch Case
You can try it here: https://dotnetfiddle.net/aIwX5P
using System;
public class Program
{
enum eOperator
{
opAdd = 0,
opSub = 1,
opDiv = 2,
opMul = 3,
opInvalid = int.MinValue + 1,
opQuit = int.MinValue
}
public static void Main()
{
double a = 0.0, b = 0.0;
eOperator op = eOperator.opQuit;
string input = String.Empty;
Console.WriteLine("Calculator");
Console.WriteLine("Enter 'quit' at any time to exit.");
// repeat until the user wants to quit.
do // while(op != eOperator.opQuit)
{
Console.Write("a = ");
input = Console.ReadLine().ToLower().Trim();
if (double.TryParse(input, out a))
{
// input is a valid double and was stored in a
Console.Write("Operator: ");
input = Console.ReadLine().ToLower().Trim();
switch (input)
{
case "+":
op = eOperator.opAdd;
break;
case "-":
op = eOperator.opSub;
break;
case "*":
op = eOperator.opMul;
break;
case "/":
op = eOperator.opDiv;
break;
case "quit":
op = eOperator.opQuit;
break;
default:
op = eOperator.opInvalid; // can't be left as quit
Console.WriteLine("Invalid entry. +, -, *, / or quit for operator.");
break;
}
if (op != eOperator.opQuit && op != eOperator.opInvalid)
{
// user didn't choose to quit or type something invalid
Console.Write("b = ");
input = Console.ReadLine().ToLower().Trim();
if (double.TryParse(input, out b))
{
// input is a valid double and was parsed into b
double result = a; // we use the operator on a, so we might as well just store a into the result right away.
// do the operation on result.
switch (op)
{
case eOperator.opAdd:
result += b;
break;
case eOperator.opSub:
result -= b;
break;
case eOperator.opMul:
result *= b;
break;
case eOperator.opDiv:
// Div by 0 check. without this, this still works since double has +/- inf values.
if (b != 0.0) // comparing double with = and != is usually bad idea, but 0.0 is saved without rounding errors.
{
result /= b;
}
else
{
Console.WriteLine("Div by 0");
op = eOperator.opInvalid;
}
break;
default:
// this if branch checked for the other two operators. since we never chanced op after that check, this exception should never happen.
// it is still a good idea to include it to find errors in your logic, should they have occurred.
throw new Exception("This shouldn't happen.");
}
if (op != eOperator.opInvalid)
{
Console.WriteLine("Result: " + result.ToString());
}
// the only invalid operation is div by 0 for now. the message was sent to the user in that case, so no else is needed at this point.
// alternatively you can store an error message into a string, and when op = opInvalid, then display that error message here centralized.
// this would be a good idea if multiple things can go wrong.
}
else if (input == "quit")
{
// input for b was an invalid number, but input was 'quit'
op = eOperator.opQuit;
}
else
{
// input for b was an invalid number and also not 'quit', display error message
Console.WriteLine("Invalid entry. Type a number or Quit");
}
}
}
else if (input == "quit")
{
// input for a was invalid number, but 'quit'
op = eOperator.opQuit;
}
else
{
// input for a was invalid number and also not 'quit'
Console.WriteLine("Invalid entry. Type a number or Quit");
}
// repeat until the user wants to quit.
}while(op != eOperator.opQuit);
Console.WriteLine("Bye");
}
}
Recently i made a simple calculator to test myself but it was clunky and cluttered because it used a large number of if statements so i used switches to clean it up. recently i learned how to use methods and tried to move each part of the code into a separate and relevant methods. But, some of my code uses loops to return to the start of the code to act as a reset function and now it doesn't work because it doesn't recognize that it is a part of a loop. i tried calling all the methods in a loop inside the main method but it still didn't work. how can i fix this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Calculator
{
class Class1
{
static int num1 = 0;
static int num2 = 0;
static int answer = 0;
static string sumType = " ";
static string consoleContinue = " ";
static void GetUserInput()
{
Console.WriteLine("please enter your first value");
num1 = int.Parse(Console.ReadLine());
Console.WriteLine("please enter your second value");
num2 = int.Parse(Console.ReadLine());
}
static void GetSumType()
{
Console.WriteLine("would you like to add, subtract, multiply or divide?");
Console.WriteLine("alternitavely type quit to exit the program");
sumType = Console.ReadLine();
switch (sumType.ToLower())
{
case "add":
answer = (num1 + num2);
Console.WriteLine("your answer is {0:0.00}", answer);
break;
case "subtract":
answer = (num1 - num2);
Console.WriteLine("your answer is {0:0.00}", answer);
break;
case "multiply":
answer = (num1 * num2);
Console.WriteLine("your answer is {0:0.00}", answer);
break;
case "divide":
answer = (num1 / num2);
Console.WriteLine("your answer is {0:0.00}", answer);
break;
case "quit":
Environment.Exit(-1);
break;
}
}
static void ConsoleContnue()
{
Console.WriteLine("do you wish to continue? type yes to continue and no to exit the program");
consoleContinue = Console.ReadLine();
switch (consoleContinue.ToLower())
{
case "yes":
continue;
break;
case "no":
Environment.Exit(-1);
break;
}
}
static void Main(string[] args)
{
while (true)
{
GetUserInput();
GetSumType();
ConsoleContnue();
}
Console.ReadLine();
}
}
}
In your "ConsoleContnue()" function -> in the switch statement for "yes" you can remove the "continue" so it looks like this:
switch (consoleContinue.ToLower())
{
case "yes":
break;
case "no":
Environment.Exit(-1);
break;
}
Then your code seems to run perfectly.
However, I would change it to a simple one liner since you only care about the "no" clause:
if (consoleContinue.ToLower() == "no") Environment.Exit(-1);
Im trying to write a basic calculator with a main menu and sub menu.
The code is working fine when a valid entry is inputted, but I want an error message to be displayed and then return the user to the main menu when invalid data is entered.
This is what I have done so far. Can someone tell me what am I doing wrong?
static void Main(string[] args)
{
// Main method (only to be used for mainmenu() execution)
MainMenu();
}
// Main Menu method
static void MainMenu()
{
// Declaring variables
// Selection variable, used in user's input to get to the desired operation
int sel;
char letter;
// Main menu styling
Console.WriteLine("Calculator");
Console.WriteLine("********************");
Console.WriteLine("1- Calculator");
Console.WriteLine("2- Exit Calculator");
Console.Write("Please enter your option here: ");
// Converting user's input to sel's type (byte)
sel = int.Parse(Console.ReadLine());
// Processing sel
switch (sel)
{
case 1:
// Execute Addition()
SecondMenu();
break;
case 2:
Console.ReadLine();
break;
default:
Console.WriteLine("Sorry that is not correct format! Please restart!"); //Catch
break;
}
}
static void SecondMenu()
{
char sel2; // Selection variable, used in user's input to get to the desired operation
// Display Menu Options
Console.WriteLine("");
Console.WriteLine("********************");
Console.WriteLine("A. Addition");
Console.WriteLine("S. Substraction");
Console.WriteLine("D. Division");
Console.WriteLine("********************");
Console.Write("Please enter your option here: ");
// Converting user's input to sel's type (byte)
sel2 = Convert.ToChar(Console.ReadLine());
// Processing sel
switch (sel2)
{
case 'a':
// Execute Addition()
Addition();
break;
case 's':
// Execute Substraction()
Substraction();
break;
case 'd':
// Execute Division()
Division();
break;
}
}
// Addition Method
static void Addition()
{
// Declaring variables
double num1, num2, res;
Console.Write("Please enter the first number: ");
// Getting user's input and converting it
num1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Please enter the second number: ");
// Getting user's input and converting it
num2 = Convert.ToDouble(Console.ReadLine());
// Processing numbers into one variable
res = num1 + num2;
// Printing out the result
Console.WriteLine("RESULT: " +res);
Console.WriteLine("");
Console.ReadKey(true);
MainMenu();
}
// Substraction Method
static void Substraction()
{
// Declaring variables
double num1, num2, res;
Console.Write("Please enter the first number: ");
// Getting user's input and converting it
num1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Please enter the second number: ");
// Getting user's input and converting it
num2 = Convert.ToDouble(Console.ReadLine());
// Processing numbers into one variable
res = num1 - num2;
// Printing out the result
Console.WriteLine("RESULT: " + res);
Console.ReadKey(true);
MainMenu();
}
// Division
static void Division()
{
// Declaring variables
double num1, num2, res;
Console.Write("Please enter the first number: ");
// Getting user's input and converting it
num1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Please enter the second number: ");
// Getting user's input and converting it
num2 = Convert.ToDouble(Console.ReadLine());
// Processing numbers into one variable
res = num1 / num2;
// Printing out the result
Console.WriteLine("RESULT: " + res);
Console.WriteLine("");
Console.ReadKey(true);
MainMenu();
}
You can call the MainMenu() method in the default part of the switch in it.
switch (sel)
{
case 1:
// Execute Addition()
SecondMenu();
break;
case 2:
Console.ReadLine();
break;
default:
Console.WriteLine("Sorry that is not correct format!");
MainMenu();
//Catch
break;
}
It is also recommended to have a condition to exit the program (like a maximum number of invalid inputs).
Something like this works, but you'll have to adjust accordingly to fit your requirements:
int sel;
char letter;
bool valid = false;
do
{
Console.WriteLine("Calculator");
Console.WriteLine("********************");
Console.WriteLine("1- Calculator");
Console.WriteLine("2- Exit Calculator");
Console.Write("Please enter your option here: ");
sel = int.Parse(Console.ReadLine());
switch (sel)
{
case 1:
SecondMenu();
break;
case 2:
Environment.Exit(0);
break;
default:
Console.WriteLine("Sorry that is not correct format! Please restart!");
break;
}
}
while (valid != true);
You could just do it like this
static void SecondMenu()
{
char sel2; // Selection variable, used in user's input to get to the desired operation
// Display Menu Options
Console.WriteLine("");
Console.WriteLine("********************");
Console.WriteLine("A. Addition");
Console.WriteLine("S. Substraction");
Console.WriteLine("D. Division");
Console.WriteLine("********************");
Console.Write("Please enter your option here: ");
sel2 = Convert.ToChar(Console.ReadLine());
switch (sel2)
{
case 'a':
Calc(1);
break;
case 's':
Calc(2);
break;
case 'd':
Calc(3);
break;
default:
Console.WriteLine("Wrong entry! Try again");
MainMenu();
return;
}
}
static void Calc(int f)
{
double num1, num2, res;
try
{
Console.Write("Please enter the first number: ");
num1 = Convert.ToDouble(Console.ReadLine());
Console.Write("Please enter the second number: ");
num2 = Convert.ToDouble(Console.ReadLine());
switch (f)
{
case 1:
res = num1 + num2;
break;
case 2:
res = num1 - num2;
break;
case 3:
res = num1 / num2;
break;
default:
Console.WriteLine("Wrong entry! Try again");
MainMenu();
return;
}
Console.WriteLine("RESULT: " + res);
Console.WriteLine("");
Console.ReadKey(true);
MainMenu();
}
catch
{
Console.WriteLine("Wrong entry! Try again");
MainMenu();
}
}
EDIT: To make sure the first menu wont crash, sorround it with a try catch block
try
{
sel = int.Parse(Console.ReadLine());
switch (sel)
{
case 1:
SecondMenu();
break;
case 2:
Console.ReadLine();
break;
default:
Console.WriteLine("Sorry that is not correct format! Please restart!");
MainMenu();
break;
}
}
catch
{
Console.WriteLine("Sorry that is not correct format! Please restart!");
MainMenu();
}
Your problem was, that it tried to parse a char into an int, what is not possible.
You can either write the switch case in another method and call the main method at the default case after printing the error message,
OR
Use a do-while loop,
Inside do, write the switch cases and put a condition at while to exit the calculator.
For example: 'Enter -1 to exit the calculator' and condition in while x!=-1
Try having a play with this:
static void Main(string[] args)
{
MainMenu();
}
static void MainMenu()
{
int sel = -1;
while (sel != 2)
{
Console.WriteLine("Calculator");
Console.WriteLine("********************");
Console.WriteLine("1- Calculator");
Console.WriteLine("2- Exit Calculator");
Console.Write("Please enter your option here: ");
sel = int.Parse(Console.ReadLine());
if (sel == 1)
{
SecondMenu();
}
else if (sel != 2)
{
Console.WriteLine("Sorry that is not correct format! Please restart!"); //Catch
}
}
}
static void SecondMenu()
{
var options = new Dictionary<char, Func<double, double, double>>()
{
{ 'a', (x, y) => x + y },
{ 's', (x, y) => x - y },
{ 'd', (x, y) => x / y },
};
while (true)
{
Console.WriteLine("");
Console.WriteLine("********************");
Console.WriteLine("A. Addition");
Console.WriteLine("S. Substraction");
Console.WriteLine("D. Division");
Console.WriteLine("********************");
Console.Write("Please enter your option here: ");
char sel = Convert.ToChar(Console.ReadLine());
if (options.ContainsKey(sel))
{
Calculate(options[sel]);
break;
}
}
}
static void Calculate(Func<double, double, double> operation)
{
Console.WriteLine("Please enter the first number: ");
double num1 = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Please enter the second number: ");
double num2 = Convert.ToDouble(Console.ReadLine());
double res = operation(num1, num2);
Console.WriteLine("RESULT: " + res);
Console.WriteLine("");
Console.ReadLine();
}
This is literally my first program I've ever written (started learning this past Monday); I am a total newbie.
My question is, how can I prevent exceptions from being thrown when a user enters an invalid character when the program prompts the user for fahreinheit or celsius entry (expecting a number)??? So for example, when a user enters "asfasd", the program throws an exception.
I did a lot of searching on the site before posting this, and I was successfully able to find other input validation questions, however, they were all concerning C and C++ and since I am such a newbie, I have a hard time with understanding those languages and how they relate to C#. Thank you. Please see code:
using System;
namespace Converter
{
class Program
{
static void Main()
{
float? FahrenheitInput = null;
double? CelsiusInput = null;
float? KilogramInput = null;
float? PoundsInput = null;
int UserChoice = 0;
do
{
Console.WriteLine("What would you like to convert? Enter the corresponding number.\n1. Fahrenheit to Celsius");
Console.WriteLine("2. Celsius to Fahrenheit\n3. Pounds to Kilograms\n4. Kilograms to pounds\n5. Exit program");
UserChoice = int.Parse(Console.ReadLine());
switch (UserChoice)
{
case 1:
Console.WriteLine("Enter the temperature in Fahreinheit, number only:");
FahrenheitInput = float.Parse(Console.ReadLine());
Console.Clear();
Console.WriteLine(FahrenheitInput + " degrees fahrenheit in Celsius is " + Program.FahrenheitToCelsius(FahrenheitInput) + "\n\n");
break;
case 2:
Console.WriteLine("Enter the temperature in Celsius, number only:");
CelsiusInput = double.Parse(Console.ReadLine());
Console.Clear();
Console.WriteLine(CelsiusInput + " degrees Celius in fahrenheit is " + Program.CelsiusToFahrenheit(CelsiusInput) + "\n\n");
break;
case 5:
break;
default:
Console.WriteLine("This is not a valid entry. Please enter 1, 2, 3, 4, or 5.");
break;
}
} while (UserChoice != 5);
}
public static float? FahrenheitToCelsius(float? INPUT)
{
return (INPUT - 32) * 5 / 9;
}
public static double? CelsiusToFahrenheit(double? INPUT)
{
return INPUT * 1.8 + 32;
}
}
}
You can either put it in Try-Catch block or use a while loop to validate the user input.
below is your code with a while loop which validates users input.
class Program
{
static void Main(string[] args)
{
double FahrenheitInput = 0;
double CelsiusInput = 0;
double KilogramInput = 0;
double PoundsInput = 0;
int UserChoice = 0;
do
{
Console.WriteLine("What would you like to convert? Enter the corresponding number.\n1. Fahrenheit to Celsius");
Console.WriteLine("2. Celsius to Fahrenheit\n3. Pounds to Kilograms\n4. Kilograms to pounds\n5. Exit program");
UserChoice = int.Parse(Console.ReadLine());
switch (UserChoice)
{
case 1:
Console.WriteLine("Enter the temperature in Fahreinheit, number only:");
while (!double.TryParse(Console.ReadLine(), out FahrenheitInput))
{
Console.WriteLine("Invalid format, please input again!");
};
Console.Clear();
Console.WriteLine(FahrenheitInput + " degrees fahrenheit in Celsius is " + Program.FahrenheitToCelsius(FahrenheitInput) + "\n\n");
break;
case 2:
Console.WriteLine("Enter the temperature in Celsius, number only:");
while (!double.TryParse(Console.ReadLine(), out CelsiusInput))
{
Console.WriteLine("Invalid format, please input again!");
};
Console.Clear();
Console.WriteLine(CelsiusInput + " degrees Celius in fahrenheit is " + Program.CelsiusToFahrenheit(CelsiusInput) + "\n\n");
break;
case 5:
break;
default:
Console.WriteLine("This is not a valid entry. Please enter 1, 2, 3, 4, or 5.");
break;
}
} while (UserChoice != 5);
}
public static double FahrenheitToCelsius(double INPUT)
{
return (INPUT - 32) * 5 / 9;
}
public static double CelsiusToFahrenheit(double INPUT)
{
return INPUT * 1.8 + 32;
}
}
TryParse is your good friend here. In most scenarios, you should favor using TryParse than Parse. In your example, you can do something like:
int validInt;
int.TryParse(Console.ReadLine(), out validInt);
float validFloat;
float.TryParse(Console.ReadLine(), out validFloat);
Parse vs. TryParse
The easiest way, IMHO, to change the routine is to rewrite Parse into corresponding TryParse:
// UserChoice = int.Parse(Console.ReadLine());
UserChoice = int.TryParse(Console.ReadLine(), out UserChoice) ? UserChoice : -1;
...
A bit more complex (you have to convert float into float?)
// FahrenheitInput = float.Parse(Console.ReadLine());
float v;
FahrenheitInput = float.TryParse(Console.ReadLine(), out v) ? (float?) v : null;
The same scheme for CelsiusInput
// CelsiusInput = double.Parse(Console.ReadLine());
double d;
CelsiusInput = double.TryParse(Console.ReadLine(), out v) d (double?) d : null;
The underlying mechanic of the code is
We try to parse user input TryParse(Console.ReadLine()...
If parse succeeds (and thus TryParse returns true) we just return the out (parsed value).
If parse fails (and thus TryParse returns false) we return some special a value (-1 for UserChoice or null in case of FahrenheitInput or CelsiusInput)
P.S. in the first switch you have just case 1, case 2 and case 5; however, you've put "This is not a valid entry. Please enter 1, 2, 3, 4, or 5." in the error message. It seems, that you have to either implement case 3 and case 4 in the switch or edit the error message.
Use int.TryParse instead of int.Parse and float.tryParse instead of float.Parse
While all the answers provided seem to work, the question you asked was
how can I prevent exceptions from being thrown [..]
and I just want to point out that you do this by putting the part which throws the exception in an try-catch-block. What this does is it executes the code within try until an exception is beeing thrown and then passes this exceptions as a parameter to the catch-part where you can handle it:
EXAMPLE
do
{
try
{
// the code you already have
}
catch (Exception ex)
{
Console.WriteLine("This is no valid input (" + ex.Message + ")! Try again...");
}
} while (UserChoice != 5);
Of course preventing exceptions from beeing thrown at all in the first place is the better way (as all the other answers do suggest), but this approach works as well and ist more generic in case you run into a similar problem in the future. Using switch-case-statements for error-handling is quite common practice...