Getting a system format exception at the int32.parse line - c#

For some reason, I continue to get a system format exception at the int32.parse line. I don’t understand what I’m doing wrong.
My assignment is to:
Create a simple application in which you have variables of appropriate types to
store the user’s name and three test grades.
Ask for this information from the user and store it appropriately.
Create a variable to store the user’s test average.
Calculate and assign
this value using the stored information given to you by the user.
My code follows:
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("Please enter your name: ");
string name;
name = Console.ReadLine ();
Console.WriteLine ("Hello, " + name);
int score;
Console.Write ("What are your last three test scores: ");
score = Int32.Parse(Console.ReadLine ());
Console.WriteLine("Your test scores are" + score + "90,92,95");}
}

It's important to inspect user input in order to avoid Exceptions due to invalid input. Here's how I would do it:
class MainClass
{
public static void Main(string[] args)
{
//Variable Declarations
string response,
name;
string[] scores;
int sumOfAllScores,
scoreCount;
bool validResponse;
System.Text.RegularExpressions.Regex onlyDigits;
//We need to assign response an initial value or else Visual Studio will complain
//since it only receives its real value within a while loop (which as far as the parser is concerned
//may or may not ever iterate.
response = string.Empty;
//Booleans are automatically assigned an intial value of 'false' but I like to intialize them anyway
validResponse = false;
//Initialize the score sum and score counter variables.
sumOfAllScores = 0;
scoreCount = 0;
//This Regex pattern will allow us to inspect a string to ensure that it contains only digits.
onlyDigits = new System.Text.RegularExpressions.Regex(#"^\d+$");
Console.Write("Please enter your name: ");
name = Console.ReadLine();
Console.WriteLine("Hello, " + name);
//This loop will iterate until the user provides valid input (comma-separated integers).
while (!validResponse)
{
//When we enter the while loop, set validResponse to true.
//If we encounter any invalid input from the user we will set this to false so that
//the while loop will iterate again.
validResponse = true;
Console.Write("What are your last three test scores (comma-separated list, please): ");
response = Console.ReadLine();
//Split response into an array of strings on the comma characters
scores = response.Split(',');
//Inspect each element of the string array scores and take action:
foreach (string scoreEntry in scores)
{
//If the current array member being inspected consists of any characters that are not integers,
//Complain to the user and break out of the foreach loop. This will cause the while loop to iterate
//again since validResponse is still false.
if (!onlyDigits.IsMatch(scoreEntry))
{
//Complain
Console.WriteLine("Invalid response. Please enter a comma-separated list of test scores");
Console.WriteLine(Environment.NewLine);
//Re-initialize the score sum and score count variables since we're starting over
sumOfAllScores = 0;
scoreCount = 0;
//Set validResponse to false and break out of the foreach loop
validResponse = false;
break;
}
//Otherwise, we have valid input, so we'll update our integer values
else
{
//Iterate the number of scores that have been entered and validated
scoreCount++;
//Use the static Convert class to convert scoreEntry to an Integer
//and add it to the score sum
sumOfAllScores += Convert.ToInt32(scoreEntry);
}
}
}
//Report the results to the user:
Console.WriteLine("Your test scores are: " + response);
Console.WriteLine("Your average score is " + sumOfAllScores / scoreCount);
}
}

Console.Readline() returns a string. In your case this string might be something like "96,92,99".
string inputs = Console.ReadLine();
First step would be to split the string into three strings like "96", "92", "99" by using the comma as a separator
string[] parts = input.Split(',');
Now each string needs to be converted into an integer, one by one
// Create array of integers with the same size as the array of parts
int[] grades = new int[parts.Length];
// Loop through the input parts and convert them into integers
for(i=0; i<parts.Length; i++)
{
// Use `TryParse()` as it wont throw an Exception if the inputs are invalid
int.TryParse(parts[i], out grades[i]);
}
Now you can do things like calculate an average. I prefer the use the built in functions like .Average() or .Sum()
Console.WriteLine("The average grade is " + grades.Average().ToString("F1"));
You can combine an array of values into a comma separated string using the string.Join() function.
Console.WriteLine("I parsed these values: " + string.Join(",", grades));
So for example if the input is invalid you will see a 0 in place of the invalid value. Here is an example console output.
Enter grades separated by commas:
92,A,96,94
I parsed these values: 92,0,96,94
The average grade is 70.5
To convert the array of strings into an array of integers with one statement, use LINQ.
int[] grades = parts.Select((part) => int.Parse(part)).ToArray();
This will though an exception with invalid inputs. Making the above to work with TryParse() is tricker, but doable.

Related

How do I correctly convert strings to ints and input them into a list?

I'm making a program that asks the user for numbers for as long as he inputs positive values.
Here's the code that I currently have written, but I've not come to complete understanding with the function of and .Parse methods.
using System;
using System.Collections.Generic;
namespace Chapter
{
class Program
{
static void Main()
{
int input;
List<int> numbers = new List<int>();
Console.WriteLine("Input number: ");
input = Convert.ToInt32(Console.ReadLine());
numbers.Add(input);
while (input >= 0)
{
Console.WriteLine("Input number: ");
input = Convert.ToInt32(Console.ReadLine());
int val = Int32.Parse(input);
numbers.Add(val);
}
Console.WriteLine("the numbers you have input are");
foreach (int number in numbers)
{
Console.Write(number + " ");
}
}
}
}
The best way to achieve this is to use the Int32.TryParse method. This allows you to validate the input and handle it accordingly as well as converting to an int.
See the below example:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
int input;
List<int> numbers = new List<int>();
do
{
Console.WriteLine("Input number: ");
while (!Int32.TryParse(Console.ReadLine(), out input))
{
Console.WriteLine("The value entered was not a number, try again.");
Console.WriteLine("Input number: ");
}
if (input >= 0)
numbers.Add(input);
}
while (input >= 0);
Console.WriteLine("the numbers you have input are");
foreach (int number in numbers)
{
Console.Write(number + " ");
}
}
}
Calling Convert.ToInt32(string) or Int32.Parse(string) do nearly the same thing. The difference is that Convert.ToInt32 will return 0 if the input is null and Int32.Parse will throw an exception.
If you were to look at the implementation you will find that Convert.ToInt32 calls Int32.Parse.
Anothing thing to note is that the Convert class allows you to convert a much wider range of types to intergers. The Int32.Parse method only accepts strings.
The issue with your code is in this block:
input = Convert.ToInt32(Console.ReadLine());
int val = Int32.Parse(input);
The input value has already been converted and is now an integer. This cannot be parsed (and doesn't have to be).
When working with user input, I'd rather use int.TryParse (what if user provides "bla-bla-bla"?).
I aslo suggest using infinite loop: keep asking user until (s)he puts negative value (in which case
we break the loop):
List<int> numbers = new List<int>();
// keep reading user input
while (true) {
Console.WriteLine("Input number: ");
// We try parsing (i.e. converting) user input - Console.ReadLine()
// into integer value - number
if (!int.TryParse(Console.ReadLine(), out int number))
// if parsing fails, say, user put "aha!", we let user know it
Console.WriteLine("Not a valid integer number, please, try again");
else if (number < 0)
// if number is negative stop asking user
break;
else
// non-negative numbers are added into the list
numbers.Add(number);
}
Console.WriteLine("the numbers you have input are");
// You can print the list in one go:
Console.Write(string.Join(" ", numbers));
Parseing detail:
int.TryParse(Console.ReadLine(), out int number)
int.TryParse takes user input Console.ReadLine() as an argument and returns true or false whether parsing succeeds or not. In case parsing succeeds, number contains parsed value.

How do you use a "char" as a sentinel value in a while loop

My Instructions:
Implement a C# console application/program that makes use of a sentinel controlled while-loop structure to continuously prompt, read and store the test results entered by the user. The user will stop his/her input sequence by entering a ‘x’ character. You also need to make use of a switch selection structure (nested inside of the while loop).
e.g code to be used:
char stop = 'x';
Console.WriteLine("Enter result (x to stop): ");
results = Convert.ToChar(Console.ReadLine());
while(results != stop)
{
Console.WriteLine("Enter result (x to stop): ");
results = Convert.ToChar(Console.ReadLine());
}
When I try to enter the 'x' as is, it does not work
you are using Console.WriteLine, but you should use Console.ReadKey and omit Convert.ToChar instead get the KeyChar property of the returned value.
so
while(results != stop)
{
Console.WriteLine("Enter result (x to stop): ");
results = Console.ReadKey().KeyChar;
}
should work, I didn't test it
You convert into wrong type: not every string can be converted into a single char (say, "xenogg").
However, every char can be represented as a string with a help of ToString():
char stop = 'x';
// Keep looping ...
while (true) {
// ...and asking user for input...
Console.WriteLine("Enter result (x to stop): ");
string results = Console.ReadLine();
// ... until (s)he puts "x"
// put StringComparison.OrdinalIgnoreCase if 'X' is exit as well as 'x'
if (string.Equals(results.Trim(), x.ToString(), StringComparison.Ordinal))
break;
// results is not "x"
//TODO: add relevant code here
}

How can I insert an "array" of strings into a value?

I simply want to enter the following numbers
100 8
15 245
1945 54
into a value, but for some reason when I copy-paste it into my ReadLine - program kicks me out (with no error or smth - so I cannot barely understand what's just happened...)
I've already a code that allows me to insert a set of numbers when they are arranged in a LINE (but not as a table as shown in the description...)
int numberOfElements = Convert.ToInt32(Console.ReadLine());
int sum = 0;
string input = Console.ReadLine();
var numbers = Array.ConvertAll(input.Split(' '), int.Parse).ToList();
Console.ReadKey();
I expect to have my numbers in a List
Console.ReadLine() only reads one line. string input = Console.ReadLine() reads first line When you get into new line. In your case only first line is read then for the second line your program only gets first character and exits.
Check This:
int numberOfElements = Convert.ToInt32(Console.ReadLine());
int sum= 0;
for (int i=0; i< numberOfElements; i++)
{
string input = Console.ReadLine();
sum += Array.ConvertAll(input.Split(' '), int.Parse).Sum();
}
Console.WriteLine(sum);
Working Fiddle
Obviously when you paste in Carriage returns, ReadLine only takes up to the first Carriage Return, you will need a loop of some description
int numberOfElements = Convert.ToInt32(Console.ReadLine());
var sb = new StringBuilder();
for (int i = 0; i < numberOfElements; i++)
{
Console.WriteLine($"Enter value {i+1}");
sb.AppendLine(Console.ReadLine());
}
var input = sb.ToString();
// do what ever you want here
Console.ReadKey();
I'm assuming that you're looking for a way to allow a user to paste something from another source into your console program, so you're looking for an answer where you can process a multi-line string input from the user (where they paste a string that contains one or more newline characters).
If this is the case, then one way to do this would be to check the value of Console.KeyAvailable after the first call to ReadLine to see if there's still more input in the buffer, and if there is, add it to the input you've already captured.
For example, here's a method that takes in a prompt (to display to the user), and then returns a List<string> that contains an entry for each row the user pasted (or typed):
private static List<string> GetMultiLineStringFromUser(string prompt)
{
Console.Write(prompt);
// Create a list and add the first line to it
List<string> results = new List<string> { Console.ReadLine() };
// KeyAvailable will return 'true' if there is more input in the buffer
// so we keep adding the lines until there are none left
while(Console.KeyAvailable)
{
results.Add(Console.ReadLine());
}
// Return the list of lines
return results;
}
In use, this might look something like:
private static void Main()
{
var input = GetMultiLineStringFromUser("Paste a multi-line string and press enter: ");
Console.WriteLine("\nYou entered: ");
foreach(var line in input)
{
Console.WriteLine(line);
}
GetKeyFromUser("\nDone!\nPress any key to exit...");
}
Output
What you do next depends on what you want to accomplish. If you want to take all the lines, split them on the space character, and return all the results as a list of individual integers, you could do something like this:
private static void Main()
{
int temp = 0;
List<int> numbers =
GetMultiLineStringFromUser("Paste a multi-line string and press enter: ")
.SelectMany(i => i.Split()) // Get all the individual entries
.Where(i => int.TryParse(i, out temp)) // Where the entry is an int
.Select(i => Convert.ToInt32(i)) // And convert the entry to an int
.ToList();
Console.WriteLine("\nYou entered: ");
foreach (var number in numbers)
{
Console.WriteLine(number);
}
GetKeyFromUser("\nDone!\nPress any key to exit...");
}
Output
Or you could even do something fancy like:
Console.WriteLine($"\n{string.Join(" + ", numbers)} = {numbers.Sum()}");
Output

C# List of names task

So im making a program for college in which i must Write a program that will store names into an array.
As a new name is entered it will be added to the end of the array. The user can keep adding names until they enter the dummy val-ue ‘exit’
Once this has been done the program will display any duplicate names.
E.g.
Enter name: Bill
Enter name: Mary
Enter name: Anisha
Enter name: Mary
Enter name: exit
Mary is a duplicate.
I should also try to show how many times each name was duplicated.
static void Main(string[] args)
{
Console.WriteLine("This program allows you to write names to a list,");
int i = 0;
//Due to the fact than i cannont resize an array after initialization, i used a list and converted it to an array at a later point
List<string> names = new List<string>();
string name = " ";
Console.WriteLine("Enter names then press enter to add them to the list of names! if you wish to exit simple type exit.");
//This loop adds names to the list
while (name.ToLower() != "exit")
{
Console.WriteLine("Enter Name: ");
name = Console.ReadLine();
names.Add(name);
i++;
}
//This line converts the list to an array
string[] nameArray = names.ToArray();
for(int z = 0;z <nameArray.Length + 1;z++)
{
for (int y = 0; y < z ; y++)
{
if (nameArray[y] == nameArray[z])
{
Console.WriteLine("The name: " + nameArray[y] + " is a duplicate.");
}
else
{
Console.Write(" ");
}
}
}
Console.ReadLine();
}
This is my code but it crashes when I compare the names, it gives me one duplicate name and no others. and then crashes, i think it is relative to the second for loop but please could someone run this and help me out.
An array can not be resized after initialization. You'll have to use List instead of an array.
If you only want to use array, then you will have to fix its size at the time of initialization. You can ask the user to enter the array size. Or you can initialize a long length array (but its not recommended).
Program is incorrect, in fact this is a case for exception, since your initial value for i is 1 and your string [] is of size 1 so at most you can access index 0, in fact in the first loop itself you are trying index 1, which is out of range exception. Even if you correct that the logic is incorrect, the way it has been designed. Following is a better solution
static void Main(string[] args)
{
Console.WriteLine("This program allows you to write names to a list,");:
List<string> nameList = new List<string>();
string name = " ";
Console.WriteLine("Enter names then press enter to add them to the list of names! if you wish to exit simple type exit.");
while (name.ToLower() != "exit")
{
Console.WriteLine("Enter Name: ");
name = Console.ReadLine();
nameList.Add(name);
}
string[] nameArray = nameList.ToArray();
Console.ReadLine();
}
nameArray will be the array that you need as a response

Inputing a selection from an array c#

Hi there I'm very new to C# so please bear with me if my question has a very obvious answer.
I am trying to write a code that displays an array of options to the user with a number to select the option. The user then selects their option and the code will display their selection from the array.
So for example
Select 1 for apples
Select 2 for oranges
Select 3 for pears
Please Enter your Selection :
I keep typing a for loop to display my area but I cannot get my program to read the input from the array this is what I have so far
static void Main(string[] args) {
string[] fruit = [3]
fruit[0]=("apples");
fruit[1]=("oranges");
fruit[2]=("pears");
for (int i = 0; i < fruit.length; i++)
{
Console.WriteLine("Enter {0} to select {1}", i, fruit[i]);
}
string choice = Console.ReadLine();
int i = int.Parse(choice);
Console.WriteLine("You have selected {0} which is {1}", i, fruit[i]);
Console.ReadLine();
}
This gives me an error and if I place this within the for loop then the program does not display me all my options.
Multiple problems with your code:
Define your string array like string[] fruit = new string[3];
Since you have defined i in your for loop, you need to use a new variable for your input.
Your condition in for loop should be i < fruit.Length
This is more of a suggestion, use int.TryParse to parse input from console, check if the entered number is an int and also check if the number is less than the array length.
You need to give different name to your loop variable or the user choice.
Also you might want to use TryParse intead of Parse to prevent possible FormatExceptions:
int userChoice;
if(int.TryParse(choice, out userChoice) && userChoice < fruit.Length)
Console.WriteLine("You have selected {0} which is {1}", userChoice, fruit[userChoice]);
void Main()
{
// compile a list of possible fruits (remember that c# arrays are
// 0-indexed (first element is actually 0 and not 1))
string[] fruits = new[]{
"apples",
"oranges",
"pears"
};
// iterate over the options and output each one
for (var i = 0; i < fruits.Length; i++){
// add one to index value to make it non-0 based
Console.WriteLine("Enter {0} to select {1}", i + 1, fruits[i]);
}
// continue to read user input until they select a valid choice
Int32 choice = 0;
do
{
// read user input
String input = Console.ReadLine();
// [try to] convert the input to an integer
// if it fails, you'll end up with choice=0
// which will force the while(...) condition to fail
// and, therefore, retry for another selection.
Int32.TryParse(input, out choice);
}
// number should be between 1 and (fruits.Length + 1)
while (choice < 1 || choice > (fruits.Length + 1));
// to reference it, subtract 1 from user's choice to get back to
// 0-indexed array
Console.WriteLine("You have selected {0} which is {1}", choice, fruits[choice - 1]);
}
You have multiple typos and you can't use the variable i twice.
Try this:
static public void Main(string[] args)
{
string[] fruit = new string[3];
fruit[0]=("apples");
fruit[1]=("oranges");
fruit[2]=("pears");
for (int i = 0; i < fruit.Length; i++)
{
Console.WriteLine("Enter {0} to select {1}", i, fruit[i]);
}
string choice = Console.ReadLine();
int j = int.Parse(choice);
Console.WriteLine("You have selected {0} which is {1}", j, fruit[j]);
Console.ReadLine();
}
You might also want to include some error trapping if the user enters something that can't be parsed as an int (you could use TryParse for example).
Typos: Your array declaration was wrong and you need a captial L on length for the array length property.
Your string array declaration is incorrect. Try
string[] fruit = new string[3];
or you can declare and initiate thus:
string[] fruit = new string[3]{"apples", "oranges", "pears"};
or simpler:
string[] fruit = {"apples", "oranges", "pears"};

Categories