Validation of input - Numbers vs. Letters - c#

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;

Related

Calculating average of all user input numbers using while loops in C#

I'm trying to work through a problem presented in one of my classes. The prompt is telling us to get the user to enter any numbers (can be positive, negative, or 0), while ignoring non-numeric inputs. Then we need to compute and display the average of all the numbers entered by the user. If the user doesn't give any numbers, I need to output "you didn't enter any numbers".
My main issue is that I'm not able to store and add the numbers given by the user properly. I'm fairly certain that everything before and after the while statement is sound. So, I know the issue must lie within while (enter!="Yes"||enter!="yes"||enter!="Y"||enter!="y"), but I'm not exactly sure what the issue is. Since I have variables for my average, the sum of the user given numbers, and a counter to keep track of loop iterations, I'm pretty sure my troubles are coming from my code not being in the correct order.
Console.WriteLine("Please enter any numbers, then type Yes to continue.");
string enter = Console.ReadLine();
string msg = "";
decimal average;
int counter = 0;
decimal sum = 0;
bool res = decimal.TryParse(enter, out average);
while (enter!="Yes"||enter!="yes"||enter!="Y"||enter!="y")
{
sum = decimal.Parse(enter);
Console.WriteLine("Please enter any numbers, then type Yes to continue");
enter = Console.ReadLine();
sum += counter;
counter++;
}
average = sum / counter;
msg = (res) ? $"The sum of your numbers is {average}" : "You didn't enter any numbers";
Console.WriteLine(msg);
try this one
static void Main()
{
int counter = 0;
decimal sum = 0;
bool exit=false;
do
{
Console.WriteLine("Please enter any number or type \"done\" to exit");
var enter = Console.ReadLine();
if (enter.Trim().ToLower() != "done")
{
var ok = decimal.TryParse(enter, out var num);
if(!ok) continue;
sum += num;
counter++;
} else exit=true;
} while (!exit);
var average = counter > 0 ? sum / counter:0;
var msg = average>0? $"The average of your numbers is {average}" : "You didn't enter any numbers";
Console.WriteLine(msg);
}
Here's an alternative for you to play with. Just to give you some more ideas.
string enter = "";
string[] stop = new [] { "yes", "y" };
List<int> numbers = new List<int>();
while (!stop.Contains(enter.ToLowerInvariant()))
{
Console.WriteLine("Please enter any numbers, then type Yes to continue.");
enter = Console.ReadLine();
if (int.TryParse(enter, out int number))
{
numbers.Add(number);
}
}
if (numbers.Any())
{
Console.WriteLine($"The average of your numbers is {numbers.Average()}");
}
else
{
Console.WriteLine("You didn't enter any numbers");
}
Try this......
string enter = "";
string msg = "";
decimal average;
int counter = 0;
decimal sum = 0;
decimal input;
while (enter!="Yes"&&enter!="yes"&&enter!="Y"&&enter!="y")
{
Console.WriteLine("Please enter any numbers, then type Yes to continue");
enter = Console.ReadLine();
bool res = decimal.TryParse(enter, out input);
if (res) {
sum += input;
counter++;
}
}
if (counter != 0)
{
average = sum / counter;
msg = $"The average of your numbers is {average}";
}
else {
msg = "You didn't enter any numbers";
}
Console.WriteLine(msg);
System.Threading.Thread.Sleep(5000);

how to output the contents of the list

essentially I'm making a guessing game for an assignment but as I try to output the list it comes out as
System.Collections.Generic.List`1[System.Int32]
System.Collections.Generic.List`1[System.Int32]
essentially I just need to store a users guess number and their attempt number so that once they guess the correct number it will display it as
"YOU WON, the number was ___ and here are your attempts
you chose 45
you chose 54
you chose 32
you chose ___
using System;
using System.Collections.Generic;
namespace main__4_8_2021_
{
class Program
{
public static void Main(string[] args)
{
while (true)
try
{
int NumberOfTries = 0;
Console.WriteLine("Guess a number between 1 and 100");
int number = Convert.ToInt32(Console.ReadLine());
List<int> mylist2 = new List<int>(number);
List<int> mylist = new List<int>(NumberOfTries);
int rng = new Random().Next(1, 101);
if (number == rng)
{
Console.WriteLine("Your guess was correct! The number was " + number + "!");
Console.WriteLine(mylist);
Console.WriteLine(mylist2);
break;
}
else if (number > rng)
{
NumberOfTries++;
Console.WriteLine("Your guess was too high ");
Console.WriteLine(mylist);
Console.WriteLine(mylist2);
Console.WriteLine("you now have done " + NumberOfTries + " Tries");
}
else if (number < rng)
{
NumberOfTries++;
Console.WriteLine("too low, ");
Console.WriteLine(mylist);
Console.WriteLine(mylist2);
Console.WriteLine("you now have done " + NumberOfTries + " Tries");
}
Console.Write($"Try again. ");
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
(the other console.writelines of the lists are just there for debug)
You have a number of issues with your code.
First, you don't need a counter for number of attempts, a Count property on the List is enough.
Second, you need to keep that list outside of the loop so it is not recreated each time.
Try the below
using System;
using System.Collections.Generic;
namespace main__4_8_2021_
{
class Program
{
public static void Main(string[] args)
{
List<int> mylist = new List<int>();
void PrintListContents() {
Console.WriteLine("here are your attempts");
var index = 0;
foreach(var value in mylist) {
Console.WriteLine($"{index}. You chose {value}");
index++;
}
}
while (true)
try
{
Console.WriteLine("Guess a number between 1 and 100");
int number = Convert.ToInt32(Console.ReadLine());
mylist.Add(number);
int rng = new Random().Next(1, 101);
if (number == rng)
{
Console.WriteLine("Your guess was correct! The number was " + number + "!");
PrintListContents()
break;
}
else if (number > rng)
{
NumberOfTries++;
Console.WriteLine("Your guess was too high ");
PrintListContents()
Console.WriteLine("you now have done " + myList.Count + " Tries");
}
else if (number < rng)
{
NumberOfTries++;
Console.WriteLine("too low, ");
PrintListContents()
Console.WriteLine("you now have done " + myList.Count + " Tries");
}
Console.Write($"Try again. ");
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
Console.WriteLine(mylist);
If value is null, only the line terminator is written. Otherwise, the
ToString method of value is called to produce its string
representation, and the resulting string is written to the standard
output stream.
SOURCE https://learn.microsoft.com/en-us/dotnet/api/system.console.writeline?view=net-5.0#System_Console_WriteLine_System_Object_
this means that you actually calling the ToString method of the list. Most of the "complex" types do not overwrite the ToString method which results in just returning the string representation of Type. In your case: List<int> which is represented as System.Collections.Generic.List`1[System.Int32]
you may also want to have a look at https://learn.microsoft.com/en-us/dotnet/api/system.object.tostring?view=net-5.0

I need to check 3 things in a 1 do while loop and I am out of ideas

I am basically building a lottery game, and I need to check several parameters in 1 loop.
I need to check that the user has actually input a number and not something else, I need to check if that number is within the range of 1 to 47, and I need to check that the user did not input the same number.
If any of those conditions are not met the user is prompted to repeat himself until all of the conditions are met.
But I am stuck, and I am not really sure how to proceed with the checking of the same number.
for (int i = 0 ; i < 6; i++)
{
do
{
string input = Console.ReadLine();
isValidNumber = int.TryParse(input, out valueFromUser);
isNumberInRange = valueFromUser > 0 && valueFromUser < 47;
Console.WriteLine("Please enter a number");
if (!isNumberInRange)
{
Console.WriteLine("Please input only numbers bigger than 0 and less than 47");
}
else if (!isThesame)
{
}
} while(!isValidNumber || !isNumberInRange || !isThesame);
lucky[i] = valueFromUser;
}
Console.WriteLine("Your chosen numbers are: {0} ,{1}, {2}, {3}, {4}, {5} ", lucky[0], lucky[1], lucky[2], lucky[3], lucky[4], lucky[5]);
You can use the Array.IndexOf method to search for an item in an array. If that item is not found, it will return -1. So if this method returns anything other than -1, we know that the user has entered the number before.
if (i == 0) {
isThesame = false;
} else if (Array.IndexOf(lucky, valueFromUser, 0, i - 1) != -1) {
isThesame = true;
}
Or simply:
isThesame = i != 0 && Array.IndexOf(lucky, valueFromUser, 0, i - 1) != -1;
Note that we only search the array up to the element before lucky[i], this is because technically, the rest of the array hasn't been "filled". We don't want to take the initial values at those indices into account.
This also means that we need to handle the special case of i == 0. When i == 0, i - 1 will be negative, and passing that to Array.IndexOf will throw an exception, which is why we handle it separately.
Probably not the most elegant solution. Obviously, the code could be trimmed, just a tad:
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
int valueFromUser;
//Method 1
List<int> lucky = new List<int>();
for (int i = 0; i < 5; i++)
{
do
{
Console.WriteLine("Please enter a number");
if (int.TryParse(Console.ReadLine(), out valueFromUser))
{
if (!lucky.Contains(valueFromUser) && (valueFromUser > 0 && valueFromUser < 48))
{
lucky.Add(valueFromUser); break;
}
}
} while (true);
}
Console.WriteLine($"Your chosen numbers are: {lucky[0]}, {lucky[1]}, {lucky[2]}, {lucky[3]}, {lucky[4]}"); Console.ReadKey();
//Method 2
int[] lucky2 = new int[5];
for (int i = 0; i < 5; i++)
{
do
{
Console.WriteLine("Please enter a number");
if (int.TryParse(Console.ReadLine(), out valueFromUser))
{
if ((Array.IndexOf(lucky2, valueFromUser) == -1) && (valueFromUser > 0 && valueFromUser < 48))
{
lucky2[i] = valueFromUser; break;
}
}
} while (true);
}
Console.WriteLine("Your chosen numbers are: {0}, {1}, {2}, {3}, {4} ", lucky2[0], lucky2[1], lucky2[2], lucky2[3], lucky2[4]); Console.ReadKey();
}
}
}

c# Need help trying to put in and run two loops for the same input

I've put in a loop with Try.Parse so that if the user enters a decimal number, the program will ask them to enter another number until they put in a integer and then the program will carry on with the next part.
However what i'm struggling with is putting in another loop that makes it so that the user can only enter a number between 1 and 100, and if they don't there should be an error message that loops until they do enter this. Id like them to run at the same time and i have this one, but i want it to also check whether its in the range and i'm not sure how to do that.
I'm new to programming so I'm not great at this.
Thank you in advance!
string inputcost;
string inputmoney;
int validcost;
int validmoney;
int changereq;
Console.Write("Please Enter The Cost, In Pennies, Of The Item You Have Purchased: ");
inputcost = Console.ReadLine();
bool result = int.TryParse(inputcost, out validcost);
while (!int.TryParse(inputcost, out validcost))
{
if (result == true)
{
Console.Write("Valid Value");
}
if (result == false)
{
Console.Write("Please Enter A Valid Integer Value");
Console.WriteLine();
inputcost = Console.ReadLine();
}
}
Your problem here is that the result variable you're looking at is only written once: outside the loop. Consider trying something like the following pseudocode (a do-while loop works exactly the same as a while loop, except it always gets executed once before the condition is checked):
bool validInput;
do
{
// If you set it true to begin with, you can set it false on any unmet conditions
// If it doesn't get set false, you've got a valid input and can exit the loop.
validInput = true;
Read input from user
Check if it's a valid integer, if not print message and validInput = false
Check if it's between 1-100, if not print message and validInput = false;
} while (!validInput);
Then if you want to tackle something more advanced, look at the continue keyword.
Try something like this.
string inputcost;
string inputmoney;
int validcost;
int validmoney;
int changereq;
while (true)
{
Console.Write("Please Enter The Cost, In Pennies, Of The Item You Have Purchased: ");
inputcost = Console.ReadLine();
if (!(valuecost >=1 && valuecost <=100))
{
Console.Write("Please enter value between 1 and 100.");
}
bool result = int.TryParse(inputcost, out validcost);
if (result == true)
{
Console.Write("Valid Value");
}
if (result == false)
{
Console.Write("Please Enter A Valid Integer Value");
}
}
It would be useful to use a method and do something like:
Console.Write("Please Enter The Cost, In Pennies, Of The Item You Have Purchased: ");
inputcost = Console.ReadLine();
bool result = false;
while (!result)
{
result = checkNumber();
}
public static bool checkNumber()
{
if(inputcost < 1 || inputcost > 100)
{
Console.Write("Please Enter a valid value: ");
inputcost = Console.ReadLine();
return false;
}
else
return true;
}
Hope this helps.
string inputcost;
string inputmoney;
int validcost = 0;
int validmoney = 0;
Console.Write("Please Enter The Cost, In Pennies, Of The Item You Have Purchased: ");
inputcost = Console.ReadLine();
// only accept integers
while (!int.TryParse(inputcost, out validcost))
{
Console.Write("Please Enter An Integer Value: ");
inputcost = Console.ReadLine();
}
// valid integer input in variable validcost
bool done = false;
while (!done)
{
Console.Write("Enter an integer between 1 and 100: ");
inputmoney = Console.ReadLine();
if (int.TryParse(inputmoney, out validmoney))
{
if (validmoney > 0 && validmoney < 101)
{
done = true;
}
else
{
Console.WriteLine("Invalid input: " + inputmoney);
}
}
else
{
Console.WriteLine("Invalid input: " + inputmoney);
}
}
//validcost is an integer and validmoney is an integer between 1 and 100
Console.WriteLine("validcost: " + validcost + " validmoney: " + validmoney);
Console.ReadKey();

checking that a number is within range

am trying to make a mastermind game using an array of ints where I having the user guess a number sequence between 4-10 instead of colours. My GetAValidNumber is suppose to displays a prompt to the user and
get a number from the user in the minimum/maximum range as specified in
the parameters. If the number entered is outside the minimum/maximum
range, then an error message is suppose to be displayed and
the user is re-prompted for the number but for some reason it isn't validating properly.
Any Guidance would be appreciated
public static int GetAValidNumber(string inputMessage)
{
// declare variables
int validInteger;
bool inputIsValid = false;
int lowValue = 1;
int highValue = 10;
while (!int.TryParse(Console.ReadLine(), out validInteger))
{
Console.WriteLine("Invalid entery - try again.");
Console.Write(inputMessage, lowValue, highValue);
do
{
while (!int.TryParse(Console.ReadLine(), out validInteger))
{
Console.WriteLine("Invalid entery - try again.");
Console.Write(inputMessage);
}
if (validInteger < lowValue || validInteger > highValue)
{
Console.WriteLine("Your number is out of Range: ");
}
else
{
inputIsValid = true;
}
} while (validInteger < lowValue || validInteger > highValue);
}
return validInteger;
}
// This method directs the play of the game
public static void PlayGame()
{
int userNumbers;
int userGuess;
int difficulty;
int randomNumbers;
Console.WriteLine("How Many Numbers Would You Like To Use When Playing(4-10): ");
userNumbers = GetAValidNumber(Console.ReadLine());
Console.WriteLine("Choose a difficulty level (1 -3");
difficulty = GetAValidNumber(Console.ReadLine());
Console.WriteLine("A 5-digit number has been chosen. Each possible digit may be the number 1, 2, 3, or 4");
Console.ReadLine();
Console.WriteLine("Enter Your Guess {0} guesses remaning", GetGameDifficulty(difficulty, randomNumbers = GetRandomNumberCount(difficulty)));
userGuess = GetAValidNumber(Console.ReadLine());
Console.WriteLine("Your Guess was {0}, Your Results are {1}", userGuess, CountHits(userGuess, randomNumbers));
Console.ReadLine();
}
Here's a simplified version of your code:
public static int GetAValidNumber(string inputMessage)
{
int validInteger = 0;
//Range between 4 to 10
int lowValue = 4;
int highValue = 10;
int.TryParse(inputMessage, out validInteger);
while (validInteger < lowValue || validInteger > highValue)
{
Console.WriteLine("Invalid entery - try again.");
inputMessage = Console.ReadLine();
int.TryParse(inputMessage, out validInteger);
}
return validInteger;
}
The issue here is you are having multiple while loops that is not validating your inputs correctly.
Take note that on your other validating number inputs you need different ranges so I would suggest setting the lowValue and highValue as extra parameters on your function:
public static int GetAValidNumber(string inputMessage, int lowValue, int highValue)

Categories

Resources