I'm following an old YouTube guide for C# learning and I'm stuck on one of the challenges for error handling.
class Program
{
static Board myBoard = new Board(8);
public static Cell setCurrentCell()
{
int currentRow, currentColumn;
// get x and y coordinates from the user. return a cell location
Console.Write("Enter a current row number: ");
while (true)
{
try
{
currentRow = int.Parse(Console.ReadLine());
break;
}
catch (FormatException)
{
Console.Write("Input has to be a number, try again:");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Input was out of range, try a number between 0 and 8.");
Console.Write("Please try again: ");
}
}
Console.Write("Enter the current column number: ");
while (true)
{
try
{
currentColumn = int.Parse(Console.ReadLine());
break;
}
catch (FormatException)
{
Console.Write("Input has to be a number, try again:");
}
catch (IndexOutOfRangeException)
{
Console.WriteLine("Input was out of range, try a number between 0 and 8.");
Console.Write("Please try again: ");
}
}
}
return myBoard.theGrid[currentRow, currentColumn];
}
}
I'm trying to catch an error if user enters a number out of bounds but the catch just skips over it and then throws the error anyways. what am I doing wrong here?
Following Int32.Parse method documentation – exception type IndexOutOfRangeException is not handled here.
If you want to check that value is less than Int32 min value or greater than Int32 max value, you should catch OverflowException.
IndexOutOfRangeException is throw by an attempt to access an indexable collection (arrays, List<T>, anything that implements IList<T>, etc.) using an invalid index - less than 0 or greater than or equal to the collection size.
Here's the first try block in your code:
try
{
currentRow = int.Parse(Console.ReadLine());
break;
}
Nothing in that block is attempting to index a collection, so we wouldn't expect IndexOutOfRangeException to be thrown. In fact there are only two things in there that can throw an exception at all (int.Parse and Console.ReadLine), neither of which can throw IndexOutOfRangeException under any circumstances.
There's only one line in your code that performs an indexing operation on a collection and that's the final return statement... which is not contained in a try...catch statement.
What you're trying to achieve is to range-check the entered values. There are a couple of ways to do this, but if you insist on using exceptions (which I wouldn't do, but you're learning I guess) then you can check the inputs by attempting to index the board's theGrid array after the parse in each try block like this:
try
{
currentRow = int.Parse(Console.ReadLine());
var test = myBoard.theGrid[currentRow, 0];
break;
}
And for currentColumn:
try
{
currentColumn = int.Parse(Console.ReadLine());
var test = myBoard.theGrid[0, currentColumn];
break;
}
If the entered value (currentRow or currentColumn) is out of bounds then this will throw the IndexOutOfRangeException as expected. (The 0 in the other index is guaranteed to not throw unless the row/column count is 0.)
Related
Quick question how do I use same variable for string input in case and int input in another case. Here is what I mean by that, I have a problem where I need to constantly insert number and then put the addition of those numbers inside another variable. This inserting is inside do while loop, for me to exit the loop and to show the sum of those numbers, I need to type "OK" or "ok". I have a problem where I do not know how to use string variable for int inputs.
Here is my code:
string input= "";
int sum = 0;
do
{
Console.WriteLine("Insert the number or OK (ok) for exit: ");
input = Console.ReadLine();
sum += Convert.ToInt32(input);
// this is where I get the error Input string was not in the correct fromat
} while (input != "OK" && input != "ok");
Console.WriteLine(sum)
If anyone knows how to help me with this, I would gladly appreciate it.
First identify that the user entered integer or not using int.TryParse(), if user entered integer then add it to the sum variable otherwise check the string
do
{
Console.WriteLine("Insert the number or OK (ok) for exit: ");
input = Console.ReadLine();
//This will add number only if user enters integer.
if(int.TryParse(input, out int number)
sum += number
} while (input != "OK" && input != "ok");
You have to test for OK before you try to convert to a number, because OK won't convert to a number
string input= "";
int sum = 0;
while(true)
{
Console.WriteLine("Insert the number or OK (ok) for exit: ");
input = Console.ReadLine();
if("OK".Equals(input, StringComparison.OrdinalIgnoreCase)) //do a case insensitive check. Note that it's acceptable to call methods on constants, and doing a string check this way round cannot throw a NullReferenceException
break;//exit the loop
sum += Convert.ToInt32(input);
}
Console.WriteLine(sum);
You'll still get the error if the user enters input other than OK, that is not convertible to a number, but this is the crux of your current problem. I'll leave dealing with other garbages as an exercise for you...
I am in my second week of C# training, so I am pretty new to programming. I have to make a program that returns the smallest integer out of a series of random integer inputs. Once the input = 0, the program should break out of the loop. I am only allowed to use while and for loops. For some reason my program breaks out of loop after the second input and it looks like it doesn't even care if there is a "0" or not. Could you please see where I went wrong? I have been busting my head off with this. Sorry if this question has already been posted by somebody else but I did not find an answer to it anywhere.
PS: The zero input should be taken into account for the comparison.
So this is what I've got so far:
class Program
{
static void Main()
{
int i = 0;
int input = Int32.Parse(Console.ReadLine());
int min = default;
while (input != 0)
{
Console.ReadLine();
if (i == 0)
{
min = input;
break;
}
if (input < min && i !=0)
{
input = Convert.ToInt32(Console.ReadLine());
min = input;
}
i++;
}
Console.WriteLine(min);
}
First of all you will want to re-read the documentation for for- and while-loops. There are several useful pages out there.. e.g. for / while.
Problem
The reason why your loop breaks is that you initialize i with 0.
int i = 0;
Inside your loop you are using the if-statment to break the loop if the condition "i is 0" is met.
if (i == 0)
{
min = input;
break;
}
The input that the user has to provide each iteration of the loop is ignored by your program as you are never storing this kind of information to any variable.
while (input != 0)
{
Console.ReadLine();
// ...
}
Possible Solution
As a beginner it is helpful to tackle tasks step by step. Try to write down each of this steps to define a simple algorithm. As there are many solutions to this problem one possible way could be:
Declare minimum value + assign max value to it
Use a while loop and loop till a specific condition is matched
Read user-input and try converting it to an integer
Check whether the value is 0 or not
4.1. If the value is 0, go to step 8
4.2. If the value is not 0, go to step 5
Check whether the value is smaller than the current minimum value
5.1. If the value is smaller, go to step 6
5.2. If the value is not smaller, go back to step 3
Set the new minimum
Go back to step 3
Break the loop
End program
A program that handles the above steps could look like:
using System;
namespace FindMinimum
{
public class Program
{
static void Main(string[] args)
{
// Declare minimum value + assign initial value
int minValue = int.MaxValue;
// Loop until something else breaks out
while (true)
{
Console.WriteLine("Please insert any number...");
// Read io and try to parse it to int
bool parseOk = int.TryParse(Console.ReadLine(), out int num);
// If the user did not provide any number, let him retry
if (!parseOk)
{
Console.WriteLine("Incorrect input. Please insert numbers only.");
continue;
}
// If the user typed in a valid number and that number is zero, break out of the loop
if (parseOk && num == 0)
{
break;
}
// If the user typed in a valid number and that number is smaller than the minimum-value, set the new minimum
if (parseOk && num < minValue)
{
minValue = num;
}
}
// Print the result to the console
Console.WriteLine($"Minimum value: {minValue}.");
// Keep console open
Console.ReadLine();
}
}
}
Try This:
int input;
Console.Write("Enter number:");
input = Int32.Parse(Console.ReadLine());
int min = input;
while(true)
{
if (input == 0)
break;
if (min > input)
min = input;
Console.Write("Enter number:");
input = Int32.Parse(Console.ReadLine());
}
Console.WriteLine(min);
Console.ReadKey();
I hope it helps.
I have a simple program that takes a number from the user and returns the number located at that position/index in an array. However, if the given number is not withing the index range, it throws an exception.
Here is my code:
int[] arr = { 1, 2, 3, 4, 5, 6 };
Console.WriteLine("input int");
int k = int.Parse(Console.ReadLine());
Console.WriteLine("before");
try
{
double n = 5 / k;
Console.WriteLine(n);
int l=arr[k];
Console.WriteLine(l);
}
catch (DivideByZeroException)
{
throw new ArgumentException("you cant divid by 0!");
}
catch (ArgumentOutOfRangeException)
{
throw new ArgumentException("please give a number between 0-5");
}
catch (Exception)
{
throw new ArgumentException("something went worng, please try again");
}
finally
{
Console.WriteLine("after");
Console.WriteLine("process compited!");
}
The problem however is, if the entered number is 7, which is not within the range, it shows ArgumentOutOfRangeException exception .
What should I do in case I want the Exception to be like "please give a number between 0-5"? (using try-catch method)
There is a difference between IndexOutOfRangeException and ArgumentOutOfRangeException.
You have to catch IndexOutOfRangeException instead.
Do not use exceptions to direct your application logic flow. Better check proactively if the index is not too big for your array. This index number is an input from outside so you are entitled to put any guards on it you see fit.
Other than that #Ciubotariu Florin is right.
I'm recreating the game Hammurabi (just an assignment for my uni) and I want somehow my code to check if the user is typing text so it gets in a while loop to prompt him to type text. I know how to make the user type the numbers I want him to but I don't know how to fix it if he types something like "a" then my program will bug.
Here is an example of what I'm talking about:
while (acresToBuy < 0)
{
Console.WriteLine("Please type a positive number or 0");
acresToBuy = int.Parse(Console.ReadLine());
}
int cost = trade * acresToBuy;
while (cost > bushels)
{
Console.WriteLine("We have but " + bushels + " bushels of grain, not " + cost);
acresToBuy = int.Parse(Console.ReadLine());
cost = trade * acresToBuy;
}
You can use Int.TryParse for this. For example:
while (acresToBuy < 0)
{
Console.WriteLine("Please type a positive number or 0");
acresToBuy = int.TryParse(Console.ReadLine(), out acresToBuy) ? acresToBuy : -1;
}
If Int.TryParse fails, then the method will return false, in which then we assign -1 to acresToBuy, otherwise, if it succeeds, we simply assign it back to itself.
You shouldn't use int.Parse (or other types' equivalents) unless you can absolutely guarantee that the input will be parsable, and that's something you cannot do where user input is involved. Instead, you should use int.TryParse:
do
{
Console.WriteLine("Please type a positive number or 0");
int input;
if (int.TryParse(Console.ReadLine(), out input)
&& input >= 0) // You can validate the input at the same time
{
acresToBuy = input;
}
else
{
Console.WriteLine("That was not the correct input. Please try again.");
acresToBuy = -1;
}
} while (acresToBuy < 0);
Edit: The while loop will always check it's condition first before executing, so keep in mind that your code will only run if acresToBuy has an initial value of something less than 0 (i.e. -1). To prevent from having to constantly check this against pre-existing conditions, you should instead use a do-while loop, which will always run at least once.
So i'm working on a revision tool that'll ask defined questions randomly using console command C#. I can create the random number but cannot seem to use the Switch function properly. Can anyone help?
// The random Object
Random Number = new Random();
while (true)
{
int Question = Number.Next(1);
Console.WriteLine("{0}", Question);
string Answer = Console.ReadLine();
if (Answer.ToLower() == "finished")
{
break;
}
if(Answer.Length == 0)
{
Console.WriteLine("Write Please");
continue;
}
switch (Question)
{
case 0:
{
Console.WriteLine("What is the nucleus of an atom made of");
if (Answer == "neutrons and protons")
{
Console.WriteLine("Well Done!");
}
if (Answer == "protons and neutrons")
{
Console.WriteLine("Well Done!");
}
Console.WriteLine("Try Again");
break;
}
}
}
}
}
}
Your code is quite strange; for example you are trying to read a response before you have even printed a question. However, your immediate question relating to the random number is simple.
You are using int Question = Number.Next(1);. According to MSDN:
Returns a non-negative random integer that is less than the specified maximum.
since you are storing the number as an int, and you have 1 as the specified maximum, you will always receive 0 from this assignment. I would assume that you have other case statements in your switch, and if you use the number of questions you have rather than 1, your switch will work. You will still have other issues with things printing in the wrong order, though....