Console.WriteLine("Mortgage Loan Calculator");
Console.WriteLine("------------------------------------");
C1 c1 = new C1();
while (true)
{
bool continueLoop = true;
do
{
try
{
Console.WriteLine("Enter loan amount: ");
loanAmount = Convert.ToDouble(Console.ReadLine());
checkLoanAmount(loanAmount);
continueLoop = false;
}
catch (FormatException formatException)
{
Console.WriteLine("\n" + formatException.Message);
Console.WriteLine("Please enter a double value. \n");
continueLoop = true;
}
catch (MyRangeException negativeNumberException)
{
Console.WriteLine("\n" + negativeNumberException.test);
}
catch (Exception exception)
{
Console.WriteLine("\n" + exception.Message);
Console.WriteLine("Input string was not in a correct format");
continueLoop = true;
}
} while (continueLoop);
do
{
try
{
Console.WriteLine("Enter loan amount: ");
years = Convert.ToDouble(Console.ReadLine());
checkLoanYears(years);
}
catch (FormatException formatException)
{
Console.WriteLine("\n" + formatException.Message);
Console.WriteLine("Please enter a double value. \n");
}
catch (MyRangeException negativeNumberException)
{
Console.WriteLine("\n" + negativeNumberException.Message);
}
catch (Exception exception)
{
Console.WriteLine("\n" + exception.Message);
Console.WriteLine("Input string was not in a correct format");
}
} while (continueLoop);
do
{
try
{
Console.WriteLine("Enter loan amount: ");
interest = Convert.ToDouble(Console.ReadLine());
checkLoanInterest(interest);
}
catch (FormatException formatException)
{
Console.WriteLine("\n" + formatException.Message);
Console.WriteLine("Please enter a double value. \n");
}
catch (MyRangeException negativeNumberException)
{
Console.WriteLine("\n" + negativeNumberException.Message);
}
catch (Exception exception)
{
Console.WriteLine("\n" + exception.Message);
Console.WriteLine("Input string was not in a correct format");
}
} while (continueLoop);
}
So I'm trying to create a Loan Program with exception handling. I have the code working to where it takes the exceptions when I input in the wrong format. The problem that I'm having though is that it keeps it in an infinite loop asking for the loan amount instead of going to the next question. If anyone could give me some advice of what I'm doing wrong that would be greatly appreciated!
Here is a partial list of things I see with your code:
Class C1 does nothing and it is not used
Outer while loop has no exit condition while(true) { } and no break; statement inside.
Repeating (copy/paste) code for similar functionality to receive user inputs. Major clue when you see this pull the code in a function, and use a loop if necessary to call the function. Here I think you use need to manualy call the function three times.
Using try{} catch{} as part of regular code instead of only for something actually un-expected. This is the reason C# has the int.TryParse(), float.TryParse() and decimal.TryParse() method, in order to branch your code depending if the input is valid or not
if(float.TryParse(input, out var value))
{
// use float `value`
} else {
// invalid input
}
Exceptions are for, well, exceptional events. Nothing in a user input program like this should be exceptional.
Your code for the loanAmount seems to be right though. It's setting continueLoop = false; and that should allow the loop to exit. You haven't shown us checkLoanAmount (which should be named CheckLoanAmount) so I can't tell you if that's causing your problem.
In any case, here's how I would do this kind of app:
Console.WriteLine("Mortgage Loan Calculator");
Console.WriteLine("------------------------------------");
decimal ReadDecimal(string message, Func<decimal, bool> validator, string validation)
{
while (true)
{
Console.WriteLine(message);
if (decimal.TryParse(Console.ReadLine(), out decimal result) && validator(result))
{
return result;
}
Console.WriteLine();
Console.WriteLine(validation);
Console.WriteLine();
}
}
decimal loanAmount = ReadDecimal("Enter loan amount: ", d => d > 0m, "Amount must be greater than zero.");
decimal years = ReadDecimal("Enter number of years: ", d => d > 0m, "Amount must be greater than zero.");
decimal interest = ReadDecimal("Enter interest rate: ", d => d >= 0m && d <= 100, "Amount must be between zero and 100.");
Related
WriteLine("Before parsing");
Write("What is your age? ");
string? input = ReadLine(); // or use "49" in a notebook
try
{
int age = int.Parse(input!);
WriteLine($"You are {age} years old.");
}
catch (OverflowException)
{
WriteLine("Your age is a valid number format but it is either too big or small.");
}
catch (FormatException)
{
WriteLine("The age you entered is not a valid number format.");
}
catch (Exception ex)
{
WriteLine($"{ex.GetType()} says {ex.Message}");
}
WriteLine("After parsing");
Write("Enter an amount: ");
string amount = ReadLine()!;
if (string.IsNullOrEmpty(amount)) return;
try
{
decimal amountValue = decimal.Parse(amount);
WriteLine($"Amount formatted as currency: {amountValue:C}");
}
catch (FormatException) when (amount.Contains("$"))
{
WriteLine("Amounts cannot use the dollar sign!");
}
catch (FormatException)
{
WriteLine("Amounts must only contain digits!");
}
I'm supposed to update or replace the try catch clauses with the TryParse() method but there's multiple catch statements within the try catch statements. The result of the c# code is not supposed to have any try catch clauses but still performs handling exceptions.
The try-catch block in the code is used to handle exceptions that may occur when parsing a string to an integer or decimal.
To run the code without using try-catch, you can use the built-in method int.TryParse or decimal.TryParse, which returns a boolean indicating if the parsing was successful or not, rather than throwing an exception.
Here's an example:
WriteLine("Before parsing");
Write("What is your age? ");
string? input = ReadLine(); // or use "49" in a notebook
if (int.TryParse(input!, out int age))
{
WriteLine($"You are {age} years old.");
}
else
{
WriteLine("The age you entered is not a valid number format.");
}
WriteLine("After parsing");
Write("Enter an amount: ");
string amount = ReadLine()!;
if (string.IsNullOrEmpty(amount)) return;
if (decimal.TryParse(amount, out decimal amountValue))
{
WriteLine($"Amount formatted as currency: {amountValue:C}");
}
else if (amount.Contains("$"))
{
WriteLine("Amounts cannot use the dollar sign!");
}
else
{
WriteLine("Amounts must only contain digits!");
}
I'm trying to restart my program after I catch an error using the catch() function, but I also want it to display the error, stop the rest of the program from running, and restart the program.
This is just a shortened version of my code which I have used as an example.
using System;
namespace Calculator
{
internal class Program
{
private static void Main(string[] args)
{
float input = 0;
while (input != 5)
{
Console.Clear();
Console.WriteLine("What would you like to do? Type: 1 for Addition. Write 5 to end program.");
try
{
input = float.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Please enter a number");
}
//Addition
if (input == 1)
{
Console.WriteLine("Enter First Value: ");
string FirstValue = Console.ReadLine();
float firstval = 0;
try
{
firstval = float.Parse(FirstValue);
}
catch (FormatException)
{
Console.WriteLine("Please enter a number");
break;
}
Console.WriteLine("Enter Second Value: ");
string SecondValue = Console.ReadLine();
float secval = 0;
try
{
secval = float.Parse(SecondValue);
}
catch (FormatException)
{
Console.WriteLine("Please enter a number");
break;
}
float sum = Add(firstval, secval);
Console.WriteLine("The sum is: {0}", sum);
}
}
}
public static float Add(float num1, float num2)
{
return num1 + num2;
}
}
}
When it says
catch (FormatException)
{
Console.WriteLine("Please enter a number");
break;
}
The break; makes it so the rest of the code stops, and it displays the error. That is good, but the program also ends after that, what I want, is that the program repeats after error. Is there any way that this could happen, but it allows 1) the Console.WriteLine("Please enter a number");, 2) the program to not run the rest of the code (The part where we are asked for a second value), and 3) the program to restart for the beginning. Please let me know if that didn't make sense, as it was a hard to explain. :)
It is very simple you do not need the "break" keyword because "break" terminates the loop execution to continue execution on exception use "continue" keyword without quotes the working fiddle is here
and your code after replacing "break" with "continue" is following
using System;
namespace Calculator
{
public class Program
{
public static void Main(string[] args)
{
float input = 0;
while (input != 5)
{
Console.Clear();
Console.WriteLine("What would you like to do? Type: 1 for Addition. Write 5 to end program.");
try
{
input = float.Parse(Console.ReadLine());
}
catch (FormatException)
{
Console.WriteLine("Please enter a number");
}
//Addition
if (input == 1)
{
Console.WriteLine("Enter First Value: ");
string FirstValue = Console.ReadLine();
float firstval = 0;
try
{
firstval = float.Parse(FirstValue);
}
catch (FormatException)
{
Console.WriteLine("Please enter a number");
continue;
}
Console.WriteLine("Enter Second Value: ");
string SecondValue = Console.ReadLine();
float secval = 0;
try
{
secval = float.Parse(SecondValue);
}
catch (FormatException)
{
Console.WriteLine("Please enter a number");
continue;
}
float sum = Add(firstval, secval);
Console.WriteLine("The sum is: {0}", sum);
}
}
}
public static float Add(float num1, float num2)
{
return num1 + num2;
}
}
}
Fixed, but now it automatically presses enter when it gets to the Main(); thing and I can't actually input anything in time. Anyone know what's wrong?
using System;
using System.Linq;
namespace Bruh
{
class Program
{
static void Main()
{
int pog = 0;
int pog2 = 0;
Random r = new Random();
Console.WriteLine("Input a whole number");
string poggers = Console.ReadLine();
if (int.TryParse(poggers, out pog))
{
pog = int.Parse(poggers);
}
else
{
Console.WriteLine("ERROR: Not a number. Please input a number and not letters.");
Console.Read();
System.Environment.Exit(1);
}
Console.WriteLine("Input a number higher than the previous");
string poggers2 = Console.ReadLine();
if (int.TryParse(poggers2, out pog2))
{
pog2 = int.Parse(poggers2);
}
else
{
Console.WriteLine("ERROR: Not a number. Please input a number and not letters.");
Console.Read();
System.Environment.Exit(1);
}
int genRand = r.Next(pog, pog2);
Console.WriteLine("This number was randomly generated between " + pog + " and " + pog2 + " and we got: " + genRand);
Console.Read();
Console.WriteLine("Would you like to try again? Y/N");
ConsoleKeyInfo answer = Console.ReadKey();
if (answer.KeyChar == 'y' || answer.KeyChar == 'Y')
{
Console.WriteLine("\n");
Main();
}
else if (answer.KeyChar == 'n' || answer.KeyChar == 'N')
{
System.Environment.Exit(1);
}
else
{
Console.WriteLine("ERROR: Y/N not any other character");
Console.Read();
System.Environment.Exit(1);
}
}
}
}
I've reworked your code into something that is more C#-like :-) - find this below.
Highlights:
You use int.TryParse() correctly, but do the conversion again
inside the true code block, using int.Parse().
No need to call System.Environment.Exit(1); to terminate the program, just let it end.
The call main() is actually a recursive call - where a method (function) calls it self. Usable sometimes, but i often leads to a StackOverflow exception. In this case, you get some strange behaviour...
using System;
namespace Bruh2
{
class Program
{
static void Main()
{
bool tryAgain = true;
while (tryAgain)
{
int pog = 0;
int pog2 = 0;
Random r = new Random();
Console.Write("Input a whole number: ");
string poggers = Console.ReadLine();
while (!int.TryParse(poggers, out pog))
{
Console.WriteLine("ERROR: Not a number. Please input a number and not letters.");
poggers = Console.ReadLine();
}
Console.Write("Input a number higher than the previous: ");
string poggers2 = Console.ReadLine();
while (!int.TryParse(poggers2, out pog2))
{
Console.WriteLine("ERROR: Not a number. Please input a number and not letters.");
poggers2 = Console.ReadLine();
}
int genRand = r.Next(pog, pog2);
Console.WriteLine("This number was randomly generated between " + pog + " and " + pog2 + " and we got: " + genRand);
Console.WriteLine();
Console.WriteLine("Would you like to try again? Y/N");
//ConsoleKeyInfo answer = Console.ReadKey();
string answer = Console.ReadKey().KeyChar.ToString().ToLower();
while (answer!="y" && answer!="n")
{
Console.WriteLine("ERROR: Y/N not any other character");
answer = Console.ReadKey().ToString().ToLower();
}
if (answer == "n")
{
tryAgain = false; // terminate the loop (and thereby the program)
}
}
}
}
}
I am trying to include an exception handling in to this small sample of code. When I am prompted to input the conversionType, I tried to input strings which are supposed to trigger the catch code and print out the error message, but instead the code just shuts down like any other errors, suggesting that the error was not caught by the try catch blocks. I am still learning how exception handling works in C#. So is there anyway to correctly catch the exception and prevent the code from crashing?
static void Main(string[] args)
{
int conversionType;
double number;
Console.WriteLine("Choose the type of conversion:\n" +
"1.Celsius to Fahrenheit\n" +
"2.Fahrenheit to Celsius");
try
{
conversionType = Convert.ToInt32(Console.ReadLine());
if (conversionType == 1)
{
Console.WriteLine("Enter the Temperature in Celsius: ");
number = Convert.ToDouble(Console.ReadLine());
number = number * 9 / 5 + 32;
Console.WriteLine("Temperature in Fahrenheit: {0:00.0}°F", number);
}
else if (conversionType == 2)
{
Console.WriteLine("Enter the Temperature in Fahrenheit: ");
number = Convert.ToDouble(Console.ReadLine());
number = (number - 32) * 5 / 9;
Console.WriteLine("Temperature in Celsius: {0:00.0}°C", number);
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
You shouldn't use exceptions for this, you have functions like int.TryParse and double.TryParse that return a boolean signifying whether or not they succeeded.
You should put a Console.ReadLine(); on the end of the code for you to see the exception.
And Also, you can add the code below inside your try statement just to make sure the program will catch every exception.
int conversionType;
double number;
Console.WriteLine("Choose the type of conversion:\n" +
"1.Celsius to Fahrenheit\n" +
"2.Fahrenheit to Celsius");
I think what you wanna do is multiple usage of the function within a loop.
You can catch different exception types like this and add a finally block.
static void Main(string[] args)
{
int conversionType;
double number;
do
{
try
{
Console.WriteLine("Choose the type of conversion:\n" +
"1.Celsius to Fahrenheit\n" +
"2.Fahrenheit to Celsius");
conversionType = Convert.ToInt32(Console.ReadLine());
if (conversionType == 1)
{
Console.WriteLine("Enter the Temperature in Celsius: ");
number = Convert.ToDouble(Console.ReadLine());
number = number * 9 / 5 + 32;
Console.WriteLine("Temperature in Fahrenheit: {0:00.0}°F", number);
}
else if (conversionType == 2)
{
Console.WriteLine("Enter the Temperature in Fahrenheit: ");
number = Convert.ToDouble(Console.ReadLine());
number = (number - 32) * 5 / 9;
Console.WriteLine("Temperature in Celsius: {0:00.0}°C", number);
}
}
catch (FormatException fe)
{
Console.WriteLine("Format exception:" + fe.Message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
// do something additional for all cases
Console.WriteLine("Try again? (Y/N): ");
}
}
while (Console.ReadLine().ToUpper() == "Y");
}
This code aks for input from the user.
I wish to have the user try again after he sends wrong input and triggers any of the exceptions below.
After getInputNumber() is triggered after the exception and the user enters the right input as numbers, the return is then triggered which returns the correct number.
After this return, it returns to the FormatException thus deleting the correct number value and returning only 0.
How can I fix it to get the correct value, but also keep allowing the user to try again if he misses the correct input?
private static int getInputNumber()
{
int number = 0;
try
{
number = Convert.ToInt32(Console.ReadLine());
}
catch (Exception ex)
{
if (ex is FormatException)
{
Console.Clear();
Console.WriteLine("Wrong format! \nTry numbers instead.");
getInputNumber();
}
else if (ex is OverflowException)
{
Console.Clear();
Console.WriteLine("The number you entered is too large.\nTry a number between 1 and 2,147,483,647");
getInputNumber();
}
}
return number;
}
On your catch block try this:
...
if (ex is FormatException)
{
Console.Clear();
Console.WriteLine("Wrong format! \nTry numbers instead.");
return getInputNumber();
}
....
Instead of just calling it. This is because when you call the getInputNumber() method after first catch and it passes successfull, it gets back to your catch block(at this point number is still 0 since a exception occurs)
As stybl said, it's better to use a boolean check and while loop to keep asking for a valid input user.
First of all, I recommend using Int32.Parse instead. It won't make much of a difference in this particular case, but it is considered best practice. For your code to work you need to include return statements for every recursive call of getInputNumber:
private static int getInputNumber()
{
int number = 0;
try
{
number = int.Parse(Console.ReadLine());
}
catch (Exception ex)
{
if (ex is FormatException)
{
Console.Clear();
Console.WriteLine("Wrong format! \nTry numbers instead.");
return getInputNumber();
}
else if (ex is OverflowException)
{
Console.Clear();
Console.WriteLine("The number you entered is too large.\nTry a number between 1 and 2,147,483,647");
return getInputNumber();
}
}
return number;
}
However, making getInputNumber recurse like that is a bad idea. Instead, you should use an infinite loop. The final result will look something like this:
private static int getInputNumber()
{
int number = 0;
while (true)
{
try
{
number = int.Parse(Console.ReadLine());
break;
}
catch (Exception ex)
{
if (ex is FormatException)
{
Console.Clear();
Console.WriteLine("Wrong format! \nTry numbers instead.");
}
else if (ex is OverflowException)
{
Console.Clear();
Console.WriteLine("The number you entered is too large.\nTry a number between 1 and 2,147,483,647");
}
else
{
Console.Clear();
Console.WriteLine("Unexpected error!");
}
}
}
return number;
}