How do I remove 'goto' here - c#

I've read that using "goto" in C# is not recommended
However, my code uses goto and so far, errors appeared when trying to avoid "goto"
anum1r:
Console.Write ("What is the first number? ");
try {
num1 = Convert.ToDouble (Console.ReadLine ());
} catch (System.FormatException) {
Console.Beep ();
Console.WriteLine ("");
Console.WriteLine ("You have entered an invalid number!");
Console.WriteLine ("");
goto anum1r;
}
anum2r:
Console.Write ("What is the second number? ");
try {
num2 = Convert.ToDouble (Console.ReadLine ());
} catch (System.FormatException) {
Console.Beep ();
Console.WriteLine ("");
Console.WriteLine ("You have entered an invalid number!");
Console.WriteLine ("");
goto anum2r;
}
answer = num1 + num2;
How do I transform this code without using GOTO. ty

Use a while loop:
double num1;
while (true) {
Console.Write ("What is the first number? ");
try {
num1 = Convert.ToDouble (Console.ReadLine ());
break;
} catch (System.FormatException) {
Console.Beep ();
Console.WriteLine ("");
Console.WriteLine ("You have entered an invalid number!");
Console.WriteLine ("");
}
}
As you need this code twice, it is also a good idea to refactor it in a separate method like #James' answer. (Though it needs an extra parameter to modify the user prompt.)

You could use a while loop
private double? GetNumber()
{
double? result = null;
try {
result = Convert.ToDouble (Console.ReadLine ());
} catch (System.FormatException) {
Console.Beep ();
Console.WriteLine ("");
Console.WriteLine ("You have entered an invalid number!");
Console.WriteLine ("");
}
return result;
}
...
// prompt for first number
double? num1 = null;
while (!num1.HasValue)
{
Console.Write ("What is the first number? ");
num1 = GetNumber();
}
// prompt for second number
double? num2 = null;
while (!num2.HasValue)
{
Console.Write ("What is the second number? ");
num2 = GetNumber();
}
// calculate result
answer = num1.Value + num2.Value;

There are two good ways to improve your code:
Extract into a separate method the logic for repeatedly asking the user for a number until they enter a valid one. (Use a loop construct to handle looping rather than a goto.)
Use double.TryParse() to avoid having to catch a format exception.
If you put both of those together, you get code that looks something like this:
using System;
namespace Demo
{
public static class Program
{
private static void Main()
{
double first = askForNumber("What is the first number? ");
Console.WriteLine();
double second = askForNumber("What is the second number? ");
Console.WriteLine("\nYou entered {0} and {1}", first, second);
}
private static double askForNumber(string prompt)
{
while (true)
{
Console.Write(prompt);
double result;
if (double.TryParse(Console.ReadLine(), out result))
return result;
Console.Beep();
Console.WriteLine("\nYou have entered an invalid number!\n");
}
}
}
}

You can use a for-loop and a collection like a double[], also use double.TryParse:
int numbers = 10;
double[] allNumbers = new double[numbers];
for (int i = 0; i < numbers; i++)
{
Console.Write("What is the {0}. number? ", i + 1);
double num;
if (double.TryParse(Console.ReadLine().Trim(), out num))
{
allNumbers[i] = num;
}
else
{
i--; // ask the user until we have the numbers
Console.Beep();
Console.WriteLine("");
Console.WriteLine("You have entered an invalid number!");
Console.WriteLine("");
}
}
double answer = allNumbers.Sum(); // LINQ so add using System.Linq;
Another way is to extract a method for this purpose:
private static double? ReadNumberFromConsole()
{
double num;
if (double.TryParse(Console.ReadLine().Trim(), out num))
return num;
else
return null;
}
That makes the code more readable:
for (int i = 0; i < numbers; i++)
{
Console.Write("What is the {0}. number? ", i + 1);
double? num = ReadNumberFromConsole();
if (num.HasValue)
{
allNumbers[i] = num.Value;
}
else
{
i--; // ask the user until we have the numbers
Console.Beep();
Console.WriteLine("");
Console.WriteLine("You have entered an invalid number!");
Console.WriteLine("");
}
}

I would also highly recommend avoid using Convert.ToDouble on user input.
Using exceptions as an input validating system is wrong on every level.
Use something like this instead:
double GetNumberFromUser() {
double Num = double.NaN;
while(!double.tryParse(Console.ReadLine(), out Num) && !double.IsNaN(Num))
{
Console.Beep();
Console.WriteLine("");
Console.WriteLine("You have entered an invalid number!");
Console.WriteLine("");
}
return Num;
}
why test for IsNaN also? read this.

You MAY simply use a loop:
double PromptForNumber(string message) {
while (true) {
Console.Write(message + " ");
try {
return Convert.ToDouble(Console.ReadLine());
} catch (FormatException) {
Console.Beep();
Console.WriteLine();
Console.WriteLine("You have entered an invalid number!");
Console.WriteLine();
}
}
}
Used as:
double num1 = PromptForNumber("What is the first number?");
double num2 = PromptForNumber("What is the second number?");
BUT here you're also using exceptions where they're not necessary. Invalid user input is not exceptional and there are better ways to handle that:
double PromptForNumber(string message) {
while (true) {
Console.Write(message + " ");
double number;
if (Double.TryParse(Console.ReadLine(), out number))
return number;
Console.Beep();
Console.WriteLine("\nYou have entered an invalid number!\n");
}
}
Note that this way you'll also handle OverflowException that you left out in your original code.
Do you need 100 inputs? One line of code:
var inputs = Enumerable.Range(1, 100)
.Select(x => PromptForNumber(String.Format("Enter number #{0}:", x)));

private Double InputNum1
{
Console.Write ("What is the first number? ");
try
{
num1 = Convert.ToDouble (Console.ReadLine ());
return num1;
}
catch (System.FormatException)
{
Console.Beep ();
Console.WriteLine ("");
Console.WriteLine ("You have entered an invalid number!");
Console.WriteLine ("");
InputNum1();
}
}

you can use a while to query for numbers until they are valid:
double? num1 = null;
while (num1==null){
Console.Write ("What is the first number? ");
try {
num1 = Convert.ToDouble (Console.ReadLine ());
} catch (System.FormatException) {
Console.Beep ();
Console.WriteLine ("");
Console.WriteLine ("You have entered an invalid number!");
Console.WriteLine ("");
}
}

Related

The name 'a' does not exist in the current context [duplicate]

This question already has answers here:
The name '...' does not exist in the current context
(5 answers)
Closed 4 years ago.
Console.Write("type first number: ");
try
{
Double a = Convert.ToDouble(Console.ReadLine());
}
catch (System.FormatException)
{
Console.WriteLine("that's not a number");
}
Console.Write("operation: ");
string b = Console.ReadLine();
Console.Write("type second number: ");
try
{
Double c = Convert.ToDouble(Console.ReadLine());
}
catch (System.FormatException)
{
Console.WriteLine("that's not a number");
}
if (b == "+")
{
Double sum = a + c;
}
New to c#, why does it say the name "a" does not exist in the current context?
Because the scope of the local a is the first try-catch block. It is created inside the block, and will "disappear" (go out of scope) when the block has finished executing.
You can fix it by declaring the a outside the block, so:
Console.Write("type first number: ");
double a;
try
{
a = Convert.ToDouble(Console.ReadLine());
}
...
Every pair of {} opens a new scope. So since you open a new scope for each of your try-blocks, the variables a and c are only valid within that block.
Try this:
Double a = 0;
try
{
a = Convert.ToDouble(Console.ReadLine());
}
catch (System.FormatException)
{
Console.WriteLine("that's not a number");
}
(and similarily in the other places).
In this particular case, using TryParse() is usually the easier and better solution, because it does not involve exceptions:
Double a;
String input = Console.ReadLine();
if (!Double.TryParse(input, out a))
{
Console.WriteLine("That was not a number...");
}
or even something like this (to prevent continuing anyway):
Double a;
do
{
String input = Console.ReadLine();
if (Double.TryParse(input, out a))
{
break;
}
Console.WriteLine("That was not a number... Try again. ");
}

Small coding project won't catch FormatException

So I recently started my first coding course for C#. I am currently trying to write a short program that prints out Yay! as many times as I indicate. Now to prevent any format exceptions, I've tried to add a try and catch to it. But, for some reason this isn't working and I can't seem to figure out why. The code is below:
Console.Write("Enter the number of times to print \"Yay!\": ");
string entry = Console.ReadLine();
var number = int.Parse (entry);
bool print = true;
while(print)
{
try
{
if(number <= 0)
{
print = false;
}
else
{
Console.WriteLine("Yay!");
number -= 1;
}
}
catch(FormatException)
{
Console.WriteLine("You must enter a whole number.");
}
}
Now to my knowledge, I have everything I need to make this work. Can anyone see where I went wrong with this?
Thanks a lot for reading!
It's
var number = int.Parse (entry);
that should throw the exception, and since it's beyond try {} scope, the
exception has not been caught. Move the fragment into the scope:
Console.Write("Enter the number of times to print \"Yay!\": ");
string entry = Console.ReadLine();
bool print = true;
try {
// int.Parse is within the try {} scope now
var number = int.Parse (entry);
while(print) {
...
}
}
catch(FormatException) {
Console.WriteLine("You must enter a whole number.");
}
Or convert int.Parse into int.TryParse and drop try {...} catch {...} at all (a better solution)
Console.Write("Enter the number of times to print \"Yay!\": ");
int number;
if (!int.TryParse(Console.ReadLine(), out number)) {
Console.WriteLine("You must enter a whole number.");
return;
}
bool print = true;
// There's no need in try {} catch {} now
while(print) {
...
}
You need to place your int.Parse inside your try-catch block.
Here's a revised version of your code.
static void Main(string[] args)
{
bool print = true;
while (print)
{
Console.Write("Enter the number of times to print \"Yay!\": ");
string entry = Console.ReadLine();
try
{
var number = int.Parse(entry);
for (int i = 0; i < number; i++)
{
Console.WriteLine("Yay!");
}
}
catch (FormatException)
{
Console.WriteLine("You must enter a whole number.");
}
}
}

Validate if integer equals string

So im trying to simply check if my variable is entered as a string, I want the if statement to go through and not an unhandled exception...
Here's my code:
Console.Write("Input: ");
int i;
bool success = int.TryParse("", out i);
if (success) {
Console.WriteLine("Enter Integer!");
} else {
i = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Output: ", i);
}
So what am I doing wrong here? Every time I am entering a string, I'm not getting to the if statement, only a crash!
The problem in your code is that the value passed to TryParse has no connection to the value passed to Convert.ToInt32. You should read the value in, then call TryParse with the same value:
Console.WriteLine("Enter an integer:");
var s = Console.ReadLine();
int i;
if (int.TryParse(s, out i)) {
Console.WriteLine("You entered an integer");
} else {
Console.WriteLine("You did not enter an integer");
}
If you would like to continue reading until the end-user enters a valid int, add a loop, like this:
int i;
do {
Console.WriteLine("Enter an integer:");
var s = Console.ReadLine();
} while (!int.TryParse(s, out i));
I think you should do it this way
Console.Write("Input: ");
int i;
bool success = int.TryParse(Console.ReadLine(), out i); //Getting the input and checking it
if (!success)
{
Console.WriteLine("Enter Integer!");
}
else
{
Console.WriteLine("Output: ", i);
}
In your code you were getting the value in the else statement and if your input cannot be parsed to int, then exception throws.

Escaping a function to get back to Main()

I'm making a program that has little programs inside of it, and I've come to a dilemma. On my first mini-program which rearranges digits to find the greatest possible number from those digits, it asks if the user wants to quit. If they respond "Yes" then the function returns 0 which is evaluated in the main(string[] args) method. My problem is that whenever the user says "No", the mini-program still doesn't continue. Here's my source:
namespace ACSL_Competition
{
class Program
{
static int DigitRearranger()
{
string[] mainString = {};
Console.WriteLine("---------Welcome to the Digit Re-arranger!---------");
Console.WriteLine("I take a positive number up to 10000, and find the highest number that can be made out of its digits.");
Console.WriteLine("Instructions: Enter a number up to 10000, and see the results!");
drLabel:
Console.Write("Your Number: ");
string input = Console.ReadLine();
int inputNumber = 0;
try { inputNumber = int.Parse(input); }
catch (Exception ex) { Console.WriteLine("Error: {0}", ex.Message); goto drLabel; }
/*Placeholder code for the moment*/Console.WriteLine(inputNumber.ToString());
evaluate:
Console.Write("Do you want to exit? Yes/No: ");
if (Console.ReadLine().Equals("Yes"))
return 1;
else if (Console.ReadLine().Equals("No"))
{
goto drLabel;
}
else
{
return 1;
}
}
static void Main(string[] args)
{
Console.WriteLine("Welcome to the ACSL Competition Program. Choose a program to begin:");
Console.Write("\n\t");
Console.WriteLine("1\tDigit Re-arranger");
label:
Console.Write("\nProgram: ");
string input = Console.ReadLine();
int number = 0;
try { number = int.Parse(input); }
catch (Exception ex) { Console.WriteLine("Error: {0}", ex.Message); goto label; }
if (number == 1)
{
Console.WriteLine("\n");
if (DigitRearranger() == 1)
{
goto label;
}
else if (DigitRearranger() != 1)
{
DigitRearranger();
}
}
else if (!number.Equals(1))
{
Console.WriteLine("Not a valid program.");
goto label;
}
//----------------
Console.ReadLine();
}
}
}
The underlying problem is that you're calling readline twice. The first time it gets the entered value, i.e. Yes, the second time you call it there is no data to read so it returns "". If you need to reuse the same input store it in a variable, i.e.
string inputVal = Console.ReadLine();
I hate goto statements, maybe you could restructure your code in to a while loop, something like:
bool exit = false;
while(!exit)
{
Console.Write("Your Number: ");
//Your main code
Console.Write("Do you want to exit? Yes/No: ");
if(Console.ReadLine() != "No")
exit = true;
}
In fact, you could get rid of the exit variable, just do while(true) and return if the user enters anything other than no.
I have a few suggestions:
Write your code to be more modular to improve readability. The Main() method should only drive the outer UI loop, each module provides its own UI.
Never use goto statements.
Don't use Console.Readline() inside an if condition (when not "Yes", it was called twice).
Here is my refactored version of your code:
class Program {
static void DigitRearranger()
{
string response = "";
int num;
do
{
Console.Clear();
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("---------Welcome to the Digit Re-arranger!---------");
Console.WriteLine("I take a positive number up to 10000, and find the highest number that can be made out of its digits.");
Console.WriteLine("Instructions: Enter a number up to 10000, and see the results!");
Console.ResetColor();
Console.Write("Your Number: ");
if (!int.TryParse(Console.ReadLine(), out num))
{
Console.WriteLine("Not a number. Press any key to continue");
Console.ReadKey();
continue;
}
//todo: reaarrange the number & print results
/*Placeholder code for the moment*/
Console.WriteLine(num);
Console.Write("Do you want to exit? Yes/No: ");
response = Console.ReadLine();
} while (response.ToLower() != "yes");
}
//UI driver only in Main method:
static void Main(){
string response = "";
do
{
Console.Clear();
Console.WriteLine("Welcome to the ACSL Competition Program. Choose a program to begin:");
Console.WriteLine("\n\t1\tDigit Re-arranger");
Console.WriteLine("\tq\tQuit");
Console.Write("\nProgram: ");
response = Console.ReadLine();
switch(response)
{
case "1":
DigitRearranger();
break;
case "q":
break;
default:
Console.WriteLine("Not a valid program. Press any key to continue");
Console.ReadKey();
break;
}
} while (response.ToLower() != "q");
Console.ReadLine();
}}

Validation of input - Numbers vs. Letters

I am creating a short C# console program that will ask 10 addition questions using random numbers from 0-10. Then it tells the user how many correct or incorrect answers they had. I am trying to find a way to validate that my user input is a number and not a letter. I am posting the code I have created so far, but could use some help.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int i = 0;
int input;
int correct = 0;
int incorrect = 0;
int questions = 10;
int[] solutions = new int[21];
int[] answers = new int[21];
int[] number1 = new int[21];
int[] number2 = new int[21];
Random number = new Random();
Console.WriteLine(" This is a test of your basic addition skills. ");
Console.WriteLine(" Please answer the random addition question below ");
Console.WriteLine(" with a number from 1 - 20 and press enter to get the");
Console.WriteLine(" next of 10 questions. At the end of the questions");
Console.WriteLine(" your results will be calculated and presented to you.");
Console.WriteLine("");
Console.WriteLine("");
while (i < questions)
{
number1[i] = number.Next(0, 10);
number2[i] = number.Next(0,10);
solutions[i] = (number1[i] + number2[i]);
//Console.WriteLine("{0} + {1} = {2}", number1[i], number2[i],solutions[i]);
Console.Write(" {0} + {1} = ", number1[i], number2[i]);
answers[i] = Convert.ToInt32(Console.ReadLine()); // original code
//input = Convert.ToInt32(Console.ReadLine());
//if (input > 0 && input <21)
//{
// Console.WriteLine("YOur answer is: {0}", input);
//}
//else
//Console.WriteLine("YOur answer is not valid");
if (solutions[i] == answers[i])
{
Console.WriteLine(" Correct");
correct++;
}
else
{
Console.WriteLine(" Your answer is incorrect, the correct answer is {0}", solutions[i]);
incorrect++;
}
//Console.WriteLine("{0}", answers[i]);
//int sum = numberone + numbertwo;
//answers[sum]++;
i++;
}
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("The number correct is: {0}, The number incorrect is: {1}", correct, incorrect);
}
}
}
Use int.TryParse() like:
bool isNumber=false;
int number;
while (!isNumber)
{
string txt = Console.ReadLine();
if (!int.TryParse(txt, out number))
{
// not a number, handle it
Console.WriteLine("This is not a number, enter a number. For real now.");
}
else
{
// use number
answers[i] = number;
isNumber = true;
}
}
Instead of:
answers[i] = Convert.ToInt32(Console.ReadLine()); // original code
Use:
int input;
bool validInput = int.TryParse(Console.ReadLine(), out input);
if (!validInput || input < 0 && input > 20)
<throw exception or display some error message here...>
EDIT: If you want to recursively ask for a correct input, this is how you can do it:
int input;
bool validInput = false;
while (!validInput)
{
validInput = int.TryParse(Console.ReadLine(), out input);
if (!validInput || input < 0 && input > 20)
{
validInput = false; // We need to set this again to false if the input is not between 0 & 20!
Console.WriteLine("Please enter a number between 0 and 20");
}
}
int iResult = int.MinValue;
bool bParsed = int.TryParse("xyz", out iResult);
TryParse will not throw an exception.
However, you can use Convert.ToInt32() as well if needed but that will throw an exception on bad data.
Something like:
if (int.TryParse(Console.ReadLine(), out answers[i]) && answers[i] > 0 && ...)
{
...
}
else
{
// invalid answer
}
This allows you to fill all positions of your array:
int result;
bool isInt = Int32.TryParse(Console.ReadLine(), out result);
if (!isInt) {
Console.WriteLine("Your input is not an integer number.");
continue;
}
answers[i] = result;

Categories

Resources