Where do i put the try-catch in my for-loop? - c#

I'm now done with the basics of my code, and it works like it should. But now i want to add a try-catch exception so that if the user put is anything else than integers, it will throw an exception and say something like: Wrong input try again. Here is where i need it:
for (int i = 0; i < nummer.Length; i++)
{
Console.Write("Nummer " + talnr + ": ");
talnr++;
string str = Console.ReadLine();
int element = Convert.ToInt32(str);
nummer[i] = element;
}
The loop will loop 10 times and store the inputs in an array. When i try it either makes an exception but contiues the loop or breaks the loop and goes on to the next block of code..

I would favour the use of...
bool parsed = Int.TryParse(str, out myInt);
If (parsed)
{
// do something
}
IMHO, a try/catch block should only really be used when there is a possibility on an unhandled exception (e.g. something volatile such as filesystem interaction) that cannot be "predicted" so as to handle accordingly (e.g. log errors etc.) and then continue without crashing your program.
Always try and handle a "known" with the methods and functions available in the framework to do so.

What you're trying to do doesn't require a try-catch. You can use the TryParse method to check whether the desired input is a properly formed integer, and prompt the user to enter a different input.
for (int i = 0; i < nummer.Length; i++)
{
bool isAnInteger = false;
int element = 0;
Console.Write("Nummer " + talnr + ": ");
talnr++;
string str = Console.ReadLine();
// evaluates to true if str can be parsed as an int, false otherwise
// and outputs the parsed int to element
isAnInteger = int.TryParse(str, out element);
while (!isAnInteger)
{
Console.Write("Wrong input, try again. ");
str = Console.ReadLine();
isAnInteger = int.TryParse(str, out element);
}
nummer[i] = element;
}

Use the int.TryParse method.
This code reads the trimmed input string from the user and tries to convert it to an integer. If the conversion is successful, it creates an integer variable called "result" which you can then use in the IF block. If the conversion fails, you can write the code for what you want to happen in the ELSE block. If you need a total of 10 integers in the list, I would drop the FOR loop in favor of a DO WHILE loop that checks for how many integers were successfully converted and added to the list. It will keep requesting input until the list is filled with 10 integers.
List<int> elements = new List<int>();
do
{
Console.WriteLine("Please enter an integer.");
if (int.TryParse(Console.ReadLine().Trim(), out int result))
{
Console.WriteLine($"You entered the integer {result}");
elements.Add(result);
}
else
{
Console.WriteLine("You must enter an integer. Please try again.");
}
} while (elements.Count < 10);

If you want to keep your code with the try catch loop here it is:
for (int i = 0; i < nummer.Length; i++)
{
try {
Console.Write("Nummer " + talnr + ": ");
talnr++;
string str = Console.ReadLine();
int element = Convert.ToInt32(str);
nummer[i] = element;
}
catch
{
MessageBox.Show("Error, numbers only");
goto breakloop;
}
}
breakloop:;
The goto statement ends the loop if an error occured

It's a good idea to not throw exceptions at all if you can help it. In this case, you can use int.TryParse() instead. This block of code can replace your one int element... line:
int element;
if (!int.TryParse(str, out element)) {
Console.WriteLine("Bad!!");
i--;
continue;
}
The i-- is to make sure that i has the same value on the next interaction of the loop. Doing that will make sure you still get 10 valid inputs before you finish the loop. (Many will say this is a really bad thing to do, but the reason for that is readability - if you have a large for loop and decrement the value somewhere in the middle, it makes it difficult for the next guy looking at your code to understand exactly what's going on. But this is a short loop, so it's pretty obvious. Just be aware of this.)
The continue keyword skips the rest of that iteration of the loop and moves on to the next (so you don't add the bad value to your array).

Related

Trouble with generic method

so I've been assigned a cinema project to complete for college, which involves me taking input of type Int and DateTime. I decided to create a method to speed up the error handling for every single variable that requires checking.
static T CheckInput <T> (string message, string errorMessage, T lowerBound, T higherBound)
{
T input;
do
{
Console.Write(message);
try
{
input = (T)Convert.ChangeType(Console.ReadLine(), typeof(T));
}
catch
{
input = lowerBound;
}
if (input > higherBound || input < lowerBound) Console.Write(errorMessage);
} while (input > higherBound || input < lowerBound);
return input;
}
This should technically allow me to take input of type int and Datetime, which is all I need it to do. However upon running it, the code keeps running until the datetime is valid andthen just continues the while loop without printing the user's ticket.
while (true)
{
// Print List of films
Console.Write("Welcome to Aquinas Multiplex\nWe are currently showing:\n");
for (int i = 0; i < films.Length; i++)
{
Console.Write("{0}. {1} ({2})\n", i + 1, films[i], filmAges[i]);
}
// Error checking for film and age input
filmToSee = CheckInput<int>("Please enter the number of the film you want to see: ", "That is not a valid film\n", 1, films.Length);
age = CheckInput<int>("Please enter your age: "," Not a valid age!\n", 1, 101);
// Age check
if (age < filmAges[filmToSee - 1])
{
Console.Write("ACCES DENIED - TOO YOUNG!\n(Press any key to proceed back to homepage)");
Console.ReadKey();
Console.Clear();
continue;
}
bookDate = CheckInput<DateTime>("Please enter the date you wish to see the film (must be no longer than a week in advance): ", "Not a valid date!\n",DateTime.Now.Date, DateTime.Now.Date.AddDays(7));
Console.Clear();
Console.Write("Your ticket:\n\n--------------------\nAquinas Multiplex\nFilm : {0}\nDate : {1}\n\nEnjoy the film!\n--------------------\n\n(Press any key to go back to the main menu)", films[filmToSee-1], bookDate.Date);
Console.ReadKey();
Console.Clear();
}
What is wrong with the code? I don't see anything in the while loop that would stop the final few lines and I have tried multiple ways to get the generic to output correctly. (Inputting an int to it works as intended, it's just not working for DateTime).
Go back to basics and add Exception handling. Wrap in try catch blocks and write the exception to console. It is important to always apply best practices. Also remember to leverage off the debugger built into your IDE and step through your code to see what it does, and what exceptions are thrown.
You will get a compilation error here:
if (input > higherBound || input < lowerBound) Console.Write(errorMessage);
So, I am not sure how this is running? You cannot compare greatness between T and T they are constrained to type IComparable<T>. Then you can use T.CompareTo(T). Refer to the where (generic type constraint).

Adding user input to a string array with while-loop without overwriting the current element at the index C# "RyggsÀck"

So HI! I'm new to C# (started about 3 weeks ago) and have taken up some programming courses and have run in to a problem.
Here is the for loop that I'm using, and I understand that the if statement looks contrary from what I wanna achieve, but when 'if (ruckSack[i] != "")' I got the "assigned string".
Furthermore, with the current code, if I just "add" an empty string to the array the it's assigned and I understand that I give the array an empty sting as a value.
int i = container;
while (i < 5)
{
if (ruckSack[i] == "")
{
Console.WriteLine("Assigned string");
i++;
}
else
{
Console.WriteLine("Empty string");
}
ruckSack[i] = Console.ReadLine();
i++;
}
So I have a display elements of array, and delete elements from array.
So I know that everything works except for the storage-func.
I would have used a list, but the assignment asks for a string array.
How would one do to solve this?
Thanks in advance!!
Best regards
EDIT: If any one wants the whole source code, tell me and i'll add it!
If yout want to avoid that the user can type a input if there is already any string in the array, yout need to inclue the Console.ReadLine() into the else-Block.
Also, you will need to use another way to check if a string is assigned as ruckSack[i] == "" only return true if the array contains an emtpy string (""). You can use string.IsNullOrEmpty(ruckSack[i]) or string.IsNullOrWhitespace(ruckSack[i]) (last one returns also true if only space on other white-spaces are in the string).
Put together:
int i = container;
while (i < 5)
{
if (string.IsNullOrWhiteSpace(ruckSack[i]))
{
Console.WriteLine("Assigned string");
i++;
}
else
{
Console.WriteLine("Empty string");
ruckSack[i] = Console.ReadLine();
}
i++;
}

Stop a loop before a predictable error happens

So I need to count lines in a textbox, to do this i use:
if (subject.Length <= 20)
{
bool moreLines = true;
int onLine = 2;
int count = 0;
while (moreLines)
{
textBody[count] = TextBox_Text.Text.Split('\n')[onLine];
Console.WriteLine("Line saved: " + textBody[count]);
onLine++;
count++;
try
{
if (TextBox_Text.Text.Split('\n')[onLine] == null)
{
}
}
catch (IndexOutOfRangeException)
{
moreLines = false;
}
}
return true;
}
I insert the split strings into textBody[] array but once I approach the last lines where there is no text I want the loop to stop. I tried to do an if statement which checks if the next line is null, and if yes stop the loop. However, I kept getting an IndexOutOfRangeException so I just put the whole thing in a try catch, but I feel like there would be an easier way to do this?
I think you might have over complicated things massively.
The String.Split method have multiple overloads, some of them takes as an argument a member of the StringSplitOptions enum - one of it's members is called None, and the other is called RemoveEmptyEntries - so as far as I understand, all you need is this:
var textBody = TextBox_Text.Text.Split(
new char[] {'\n'},
StringSplitOptions.RemoveEmptyEntries);
An easy way to do this would just to use the following:
TextBox_Text.Text.Split('\n').Length
The Length property returns the length of the array.
so I just used the LineCount property instead and done a compare to the onLine
if (TextBox_Text.LineCount >= onLine)
{
moreLines = false;
}

Exception handling during runtime in array with C#

I'm beginner in programming and I have tried some simple code in C#. [1]: http://i.stack.imgur.com/zLVbz.jpg
This code deals with simple array initialization ,storing and sorting and so on.Its runs as usual in the first try but when I again want to store in the array it throws the exception which I don't understand.
[![Its the exception I'm getting][1]][1]
static void Main(string[] args)
{
int number;
char y;
string[] answer = new string[10];
bool keeprompting = true;
while (keeprompting)
{
Console.WriteLine("Enter the options given below 1.Add students\n 2.View all details\n 3.Sorting\n 4.Exit\n");
int input = Convert.ToInt16(Console.ReadLine());
switch (input) {
case 1:
Console.WriteLine("Enter the Number of Students to be added to the List");
number = Convert.ToInt16(Console.ReadLine()); **exception **
for (int i = 0; i < number; i++) {
answer[i] = Console.ReadLine();
}
break;
case 2:
foreach(var item in answer)
{
Console.WriteLine(item.ToString());
}
break;
case 3:
Array.Sort(answer);
foreach(var item in answer)
{
Console.WriteLine(item.ToString()); **exception **
}
break;
case 4:
Console.WriteLine("Are you sure you want to exit");
Console.WriteLine("1 for Yes and for No");
y = (char) Console.Read();
if (y != 1) {
keeprompting = true;
} else {
keeprompting = false;
}
Console.WriteLine("thank you");
break;
}
}
}
Any and all suggestion are welcome.
1) Possibly FormatException raised here int input = Convert.ToInt16(Console.ReadLine()); because you enter to the Console not '1', '2', etc., but '1.', '2.' and so on. Or may be you use other symbols that cannot be parsed using Convert.ToInt16() method. Value you enter should be in range -32768..32767 and should not contain any space, dot, comma and other symbols except minus sign.
2) The same may happen here number = Convert.ToInt16(Console.ReadLine()); **exception**
3) And here I think you get NullReferenceException:
Array.Sort(answer);
foreach (var item in answer)
{
Console.WriteLine(item.ToString()); **exception**
}
It happens because you have 10 items in your array (string[] answer = new string[10];), but when you insert students you may insert less than 10, so you have for exapmle 3 items initialized, and other set to its default value - null for string. So your array looks like this: { "John", "Jack", "Ben", null, null, ..., null }. A foreach statement later iterates each item including null values, and it tries to call method on a null object, so you get NullReferenceException.
May be you should better use List<string> instead of array to avoid such kind of problems. Call Add() to add items, and Clear() method before you enter students again(to get free of students from previous "session"). And when you later iterate this collection with a foreach loop everything will be ok.
I posted 2 solutions in your other question about this method in this program that accounts for the array size issues in two different ways. Use int.TryParse instead of convert and you either need to resize the array based on user input on the number of students or you need to check for nulls in each iteration of the answer array, skipping nulls. See the example code i provided in your other question.

Loop not completing

I have a simple program that is used to pass inputs to an array given the inputted size and inputted elements by the user as follows:
Full code
All the code works fine except this snippet :
for(int i=0; i<size; i++) {
flagger = false;
while(flagger == false) {
System.Console.WriteLine("Please enter number " + i + " : ");
nextInput = System.Console.ReadLine();
flagger = errorCheck(nextInput);
}
int varPass = System.Convert.ToInt32(nextInput);
System.Console.WriteLine(flagger);
arr[i] = varPass;
}
No matter what size I input the loop exits early and sorts an array with some empty elements, can anyone see the problem?
In errorCheck you're setting the value of size as you're passing it in the out parameter.
So the next time the user inputs a number smaller than i the loop exits early.
Create a dummy int or handle your error checking differently.
Example:
static bool errorCheck(string input) {
int temp=0;
if (int.TryParse(input, out temp))
return true;
return false;
}
This "bug" happens because size is static.
You can simplify your code further by just returning the result of TryParse.
static bool checkErr(string input) {
int temp=0;
return int.TryParse(input, out temp);
}
You haven't included errorCheck method which seems crucial to me.
If errorCheck returns true the Loop WILL end prematurely.
EDIT: Oops, you did include a link to full code.
As my predecessor said, errorCheck(...) modifies "size". Maybe that's why I still prefix member variables with underscore. It's so easy to miss.

Categories

Resources