If user input is not a number - c#

This is a very simple script I am trying to figure out and I have been looking for a simple answer and can't find it in the forums or in my C# book.
Console.Write("Enter a Number\n");
int input = Convert.ToInt32(Console.ReadLine()); //convert code to an integer
if (!Int32.IsNumber(input)) //if not a whole number input give an error
{
Console.WriteLine("Not an integer");
}
It's just that simple what I'm trying to do. This is a snippet from a bigger code.

Console.Write("Enter a Number\n");
string input = Console.ReadLine(); //get the input
int num = -1;
if (!int.TryParse(input, out num))
{
Console.WriteLine("Not an integer");
}
else
{
...
}
Int.TryParse will return false if the string is not a valid integer and vise versa

I figured out the easiest and best code to get this done from many answers:
Console.Write("\nEnter a Whole Number (Such as 12)\n");
string Input = Console.ReadLine();
char firstChar = Input[0];
bool isNumber = Char.IsDigit(firstChar);
if (!isNumber)
{
Console.WriteLine("Not an integer");
}
else
{
.......
}

Related

Calculating product of numbers using do while

I'm new to coding and trying my best but I got stuck. Again.
So. I need to calculate the product of some random numbers using do while.
You type the numbers and when you type x, the loop needs to close showing the result. If you ONLY type x, it needs to show "1".
I can't manage to only show "1" when you type "x".
I have this:
int product = 1;
Console.WriteLine();
String input = Console.ReadLine();
do
{
int n = Convert.ToInt32(input);
product = product * n;
input = Console.ReadLine();
} while (!input.ToLower().Equals("x"));
Console.WriteLine(product);
Console.ReadLine();
for and while breaks in the start of the loops and do while break at the end, sometimes you have to break it the middle (here after the input was entered, if it's x) and before the accumulation.
The best way to manage this is an infinite loop for(;;) or while(true) and uses of break:
var product = 1;
for(;;)
{
var input = Console.ReadLine();
if (input is null || input.Equals("x", StringComparison.OrdinalIgnoreCase))
break;
product *= Convert.ToInt32(input);
}
Console.WriteLine(product);
Console.ReadLine();
Or you can try to make it fit (mostly double calls to ReadLine).
A for version that looks ugly:
var product = 1;
for (var input = Console.ReadLine(); input != "x"; input = Console.ReadLine())
{
product *= int.Parse(input);
}
Console.WriteLine(product);
Console.ReadLine();
A while version:
var product = 1;
var input = Console.ReadLine();
while (!input.ToLower().Equals("x"))
{
product *= Convert.ToInt32(input);
input = Console.ReadLine();
}
Console.WriteLine(product);
Console.ReadLine();
Another while version that avoid ReadLine at multiple places:
var product = 1;
string input;
// an affectation actually evaluate to the value affected
// avoid this since it's not easily readable (= and == mismatch)
while ((input = Console.ReadLine()) != "x")
{
product *= Convert.ToInt32(input);
}
Console.WriteLine(product);
Console.ReadLine();
A do while version:
I add it because it's in the question title, otherwise I didn't consider it a good solution.
Based on yassinMi answer.
var product = 1;
var input = "1";
do
{
product *= int.Parse(input);
input = Console.ReadLine();
} while (input != "x");
Console.WriteLine(product);
Console.ReadLine();
A Linq version:
var product = Enumerable.Range(0, int.MaxValue) // many elements
.Select(_ => Console.ReadLine()) // discard them and take the console input
.TakeWhile(s => s != "x") // stop on 'x'
.Select(int.Parse) // parse to int
.Aggregate(1, (a, b) => a * b); // accumulate from 1 and by making the product
Console.WriteLine(product);
Console.ReadLine();
a simple fix: change the line
String input = Console.ReadLine();
to
String input = "1";
otherwise you would use the while loop, or add extra if statement..
Welcome to C#!
Your issue is most likely due to an error while converting a value. You are trying to convert "x" to int, but "x" is a letter, which cannot be converted to a number.
Cause of the issue
The problem of this program is that you are trying to convert a letter to a number. This is not possible in real life, and less possible in programming! A computer is not able to convert a number to a letter, unless you are explaining to it how, or if your handle the error properly.
The following line:
int n = Convert.ToInt32(input);
...Does not check for what has been entered. Convert.ToInt32() will throw an exception if the string? (From Console.ReadLine()) could not be converted.
The fix
To fix this issue, you need to handle the input of the user. Literally anything is accepted by Console.ReadLine() but you want a value that can be converted to a int.
The int type has a built-in function to convert a value without throwing an exception if it couldn't be converted, instead, it returns a bool (Either true or false).
So the following changes need to be brought to your program:
int product = 1;
string ? input;
do {
input = Console.ReadLine();
// Try to parse to integer, if it couldn't be parsed to integer, continue.
if (!int.TryParse(input, out int n)) {
continue;
}
product = product * n;
} while (!input.Equals("x", StringComparison.InvariantCultureIgnoreCase));
Console.WriteLine(product);
// End of the program
Console.WriteLine("Press any key to quit the program.");
Console.ReadKey();
Trying to parse a string to an integer
The method int.TryParse(string? input, out int output); allows you to try to convert a string to a int.
If the method fails, instead of throwing an Exception, it will returns false.
Getting the output value
The output value can be obtained from out int output, out allows you to output a value from a function.
The logic would be that if int.TryParse(...) returns true, the value can be used, otherwise you can continue.
The continue statement tells your loop that the current loop should be skipped and goes to the next one (= At the beginning of your loop).
Other changes
I've brought to your program some changes to make it more readable and easier to edit.
Firstly, you'd want to use Equals(input, StringComparison.InvariantCultureIgnoreCase) instead of ToLowerCase(), the result is the same and it is cleaner! 🙂
Also, you can directly ask the input within your while loop since this will be repeated each time, you just need to position it correctly so the value can be verified.
Final program
ConsoleKeyInfo continueProgram = new ConsoleKeyInfo();
ConsoleKeyInfo continueInput = new ConsoleKeyInfo();
List<int> products = new List<int>();
do
{
Console.Clear();
do
{
Console.Write("\nPlease enter new number . . . ");
if (int.TryParse(Console.ReadLine(), out int result))
{
products.Add(result);
Console.WriteLine("\nNew Product Added!");
}
else
{
Console.WriteLine("\nYou have entered a value that is not an integer!\n");
}
Console.Write("\nDo you want to enter an other value (press Y) or any key to exit . . . ");
continueInput = Console.ReadKey();
Console.WriteLine();
}
while (continueInput.Key == ConsoleKey.Y);
Console.WriteLine();
foreach (var item in products)
{
Console.WriteLine(item.ToString());
}
Console.ReadLine();
Console.Write("\n\nPress 'Y' to continue or any other key to exit! . . . ");
continueProgram = Console.ReadKey();
} while (continueProgram.Key == ConsoleKey.Y);
The problem is that Console.ReadLine() gets called twice before checking for x. The first input gets eaten up.
What you need to do is inside the loop ask and process the input, and exit the loop when the condition is met.
One way of doing this is by keeping a boolean value called done indicating when to exit the loop'
static void Main(string[] args)
{
int product = 1;
bool done = false;
do
{
Console.WriteLine("Enter number or 'x' to calculate result.");
string input = Console.ReadLine();
done = input.ToLower() == "x";
if (int.TryParse(input, out int value))
{
product *= value;
}
else
{
Console.WriteLine("Input ignored.");
}
} while (!done);
Console.WriteLine($"The product is {product}");
}
Another more succinct way is to use the break; statement
static void Main(string[] args)
{
int product = 1;
do
{
Console.WriteLine("Enter number or 'x' to calculate result.");
string input = Console.ReadLine();
if (input.ToLower() == "x")
{
// this exits the loop
break;
}
if (int.TryParse(input, out int value))
{
product *= value;
}
else
{
Console.WriteLine("Input ignored.");
}
} while (true);
Console.WriteLine($"The product is {product}");
}
Also, it is recommended to use int.TryParse(string, out integer) for better handling weird user inputs instead of Convert.ToInt32(). See the pattern above on how it is used.

c# input validation for strings and integers

I am trying to validate string and integer input
For string input, I am trying to implement a validation that do not accept null or integers and this is what i have for now which doesn't have error handling for integers:
string name = Console.ReadLine().ToLower();
if (name.Length == 0)
{
Console.WriteLine("Name cannot be an empty field, try again!");
name = Console.ReadLine().ToLower();
return; }
and for the integer input, I would like to only accept integers and my problem is that these codes only allow me to enter a wrong input once before it shows me an error handing exception error
Console.Write("Enter exp: ");
int exp = 0;
try
{
exp = int.Parse(Console.ReadLine());
}
catch
{
Console.Write("Invalid exp, please enter a valid numerical value!: ");
exp = int.Parse(Console.ReadLine());
}
How should I handle all these input errors or are there any improvements I can make to my codes that I have for now?
All help is greatly appreciated !
Use a while loop until the user enters an integer.
And you should never use try...catch to check if an integer can be parsed. Always use int.TryParse(...). Everything else is a code smell (and slower in the case when it is not an integer).
var integerEntered = false;
int exp;
while (!integerEntered)
{
Console.Write("Enter exp: ");
var entered = Console.ReadLine();
integerEntered = int.TryParse(entered, out exp);
if (!integerEntered)
Console.WriteLine("That was no valid integer. Please try again.");
}
Console.Write("Enter exp: ");
int exp;
bool result = int.TryParse(Console.ReadLine(), out exp)
if(result)
{
//you have an int value entered
}
else
{
Console.WriteLine("Please enter a valid number")
}
//code continues
I suggest extracting methods, e.g.
For string values input
private static string ReadString(string title,
Func<string, string> errorMessage = null) {
while (true) {
if (!string.IsNullOrWhiteSpace(title))
Console(title);
string input = Console.ReadLine();
string message = errorMessage == null
? null
: errorMessage(input);
if (!string.IsNullOrWhiteSpace(message))
return input;
Console.WriteLine(message);
}
}
For integer values
private static string ReadInt(string title, Func<x, string> errorMessage = null) {
while (true) {
if (!string.IsNullOrWhiteSpace(title))
Console(title);
string input = Console.ReadLine();
if (!int.TryParse(input, out int result)) {
Console.WriteLine("Not valid integer value. Please, try again.");
continue;
}
string message = errorMessage == null
? null
: errorMessage(result);
if (!string.IsNullOrWhiteSpace(message))
return input;
Console.WriteLine(message);
}
}
Then you can use them
string name = ReadString("Please, enter name",
v => string.IsNullOrWhiteSpace(v)
? "Name cannot be an empty field, try again!"
: "");
int exp = ReadInt("Enter exp: ", v => v < 0 ? "Exp must not be negative", "");
I have modified my code to have a function for each of your questions.
//input
get_input_func(){
string str = Console.ReadLine();
}
//validate
validation_func() {
try {
if(str.Length == 0 ) {
Console.WriteLine("Cannot be empty, please enter a num");
}
if(str.All(!Char.IsDigit)) {
Console.WriteLine("You can only enter numbers");
}
//catch multiple exceptions
catch(Exception e) {
switch(e) {
Console.WriteLine(e);
get_input_func();
}
}

Unexpected result at summing numbers using a while loops in console application

I am trying to make a program to sum numbers until the user enter OK.
The program make the sum, but return a bad result.
i'm not sure where is my error...
int sum = 0;
Console.WriteLine("Enter number:");
int num = Convert.ToInt32(Console.ReadLine());
while (Console.ReadLine() != "OK")
{
sum += num;
}
Console.WriteLine(sum);
you don't keep the number the use enter in the while loop.
you need to input the readline to a variable.
var num = Console.Readline();
sum += num; //parse first
Inside your while loop you need to update num:
int num = Convert.ToInt32(Console.ReadLine());
while (Console.ReadLine() != "OK")
{
num = Int32.Parse(Console.ReadLine());
sum += num;
}
Also just as a note, if you need your program to be a little safer, you can you use the following:
int num;
if(Int32.TryParse(Console.ReadLine(), out num)) {
//do something..
}
else {
//do something else.. like end program, throw exception etc.
}
Int32.TryParse:
Converts the string representation of a number to its 32-bit signed
integer equivalent. A return value indicates whether the conversion
succeeded
This way you can do something in the instance that the input string was not a valid conversion. Example: if someone input cat, which can not be converted to an int, it would crash your program without the TryParse.
You need to input the number once per iteration, and store it each time. So each value retrieved from Console.ReadLine() needs to be captured in an assignment statement, then converted to a number if it is not "OK".
I think you're after this:
int sum = 0;
string input;
Console.WriteLine("Enter number: ");
while ((input = Console.ReadLine()) != "OK")
{
int inputNum = Convert.ToInt32(input);
sum += num;
Console.WriteLine("Enter number: ");
}
The statement (input = Console.ReadLine() assigns the user input to the input variable, then the assignment statement returns the value of input. Then that value is compared against OK.
An alternative way to get input, then check it is:
Console.WriteLine("Enter number: ");
input = Console.ReadLine()
while (input != "OK")
{
...
Console.WriteLine("Enter number: ");
input = Console.ReadLine()
}
int sum = 0;
Console.WriteLine("Enter number:");
int num = int.Parse(Console.ReadLine());
while (sum< num)
{
sum++;
}
Console.WriteLine(sum);

How do I ask the user for input in C#

I am switching from Python to C# and I am having trouble with the ReadLine() function. If I want to ask a user for input Python I did it like this:
x = int(input("Type any number: "))
In C# this becomes:
int x = Int32.Parse (Console.ReadLine());
But if I type this I get an error:
int x = Int32.Parse (Console.ReadLine("Type any number: "));
How do I ask the user to type something in C#?
You should change this:
int x = Int32.Parse (Console.ReadLine("Type any number: "));
to this:
Console.WriteLine("Type any number: "); // or Console.Write("Type any number: "); to enter number in the same line
int x = Int32.Parse(Console.ReadLine());
But if you enter some letter(or another symbol that cannot be parsed to int) you will get an Exception. To check if entered value is correct:
(Better option):
Console.WriteLine("Type any number: ");
int x;
if (int.TryParse(Console.ReadLine(), out x))
{
//correct input
}
else
{
//wrong input
}
Starting from C# 7 you can use inline variable declaration (out variables):
Console.WriteLine("Type any number: ");
if (int.TryParse(Console.ReadLine(), out var x)) // or out int x
{
//correct input
}
else
{
//wrong input
}
Console.WriteLine("Type any number");
string input = Console.ReadLine();
int x;
if (int.TryParse(input, out x))
{
//do your stuff here
}
else
{
Console.WriteLine("You didn't enter number");
}
Console.WriteLine("Type any number: ");
string str = Console.ReadLine();
Type a = Type.Parse(str);
where Type is Data Type you want to cast user input to.
I suggest reading few books on C# fundaments before turning to forums.
To be more generic I would suggest you to make an additional object ( because you cannot extend static objects in C# ) to behave like you've specified.
public static class ConsoleEx
{
public static T ReadLine<T>(string message)
{
Console.WriteLine(message);
string input = Console.ReadLine();
return (T)Convert.ChangeType(input, typeof(T));
}
}
Of course you this code is not error free because it does not contains any constraints about the output type but still It will cast into some types without any problems.
For example. Using this code :
static void Main()
{
int result = ConsoleEx.ReadLine<int>("Type any number: ");
Console.WriteLine(result);
}
>>> Type any number:
<<< 1337
>>> 1337
Check this online
try this
Console.WriteLine("Type any number: ");
int x = Int32.Parse (Console.ReadLine());

How do I only allow number input into my C# Console Application?

Console.WriteLine("Enter the cost of the item");
string input = Console.ReadLine();
double price = Convert.ToDouble(input);
Hello, I want the keyboard buttons, A-Z, brackets, question mark, etc to be disabled. I want it so if you type it in, it will not show up in the Console. I only want the numbers 1-9 to show up. This is in C# Console application. Thanks for the help!
try this code snippet
string _val = "";
Console.Write("Enter your value: ");
ConsoleKeyInfo key;
do
{
key = Console.ReadKey(true);
if (key.Key != ConsoleKey.Backspace)
{
double val = 0;
bool _x = double.TryParse(key.KeyChar.ToString(), out val);
if (_x)
{
_val += key.KeyChar;
Console.Write(key.KeyChar);
}
}
else
{
if (key.Key == ConsoleKey.Backspace && _val.Length > 0)
{
_val = _val.Substring(0, (_val.Length - 1));
Console.Write("\b \b");
}
}
}
// Stops Receving Keys Once Enter is Pressed
while (key.Key != ConsoleKey.Enter);
Console.WriteLine();
Console.WriteLine("The Value You entered is : " + _val);
Console.ReadKey();
This MSDN article explains how to read characters one at a time in a console window. Test each character as it is input with the Char.IsNumber() method, and reject those characters that fail the test.
In a while, I got a solution really short:
double number;
Console.Write("Enter the cost of the item: ");
while (!double.TryParse(Console.ReadLine(), out number))
{
Console.Write("This is not valid input. Please enter an integer value: ");
}
Console.Write("The item cost is: {0}", number);
See you!
Here is one approach. It's probably overkill if you're just starting out in C#, since it uses some more advanced aspects of the language. In any case, I hope you find it interesting.
It has some nice features:
The ReadKeys method takes an arbitrary function for testing whether the string so far is valid. This makes it easy to reuse whenever you want filtered input from the keyboard (e.g. letters or numbers but no punctuation).
It should handle anything you throw at it that can be interpreted as a double, e.g. "-123.4E77".
However, unlike John Woo's answer it doesn't handle backspaces.
Here is the code:
using System;
public static class ConsoleExtensions
{
public static void Main()
{
string entry = ConsoleExtensions.ReadKeys(
s => { StringToDouble(s) /* might throw */; return true; });
double result = StringToDouble(entry);
Console.WriteLine();
Console.WriteLine("Result was {0}", result);
}
public static double StringToDouble(string s)
{
try
{
return double.Parse(s);
}
catch (FormatException)
{
// handle trailing E and +/- signs
return double.Parse(s + '0');
}
// anything else will be thrown as an exception
}
public static string ReadKeys(Predicate<string> check)
{
string valid = string.Empty;
while (true)
{
ConsoleKeyInfo key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter)
{
return valid;
}
bool isValid = false;
char keyChar = key.KeyChar;
string candidate = valid + keyChar;
try
{
isValid = check(candidate);
}
catch (Exception)
{
// if this raises any sort of exception then the key wasn't valid
// one of the rare cases when catching Exception is reasonable
// (since we really don't care what type it was)
}
if (isValid)
{
Console.Write(keyChar);
valid = candidate;
}
}
}
}
You also could implement an IsStringOrDouble function that returns false instead of throwing an exception, but I leave that as an exercise.
Another way this could be extended would be for ReadKeys to take two Predicate<string> parameters: one to determine whether the substring represented the start of a valid entry and one the second to say whether it was complete. In that way we could allow keypresses to contribute, but disallow the Enter key until entry was complete. This would be useful for things like password entry where you want to ensure a certain strength, or for "yes"/"no" entry.
This code will allow you to:
Write only one dot (because numbers can have only one decimal separator);
One minus at the begining;
One zero at the begining.
It means that you not be able to write something like: "00000.5" or "0000...-5".
class Program
{
static string backValue = "";
static double value;
static ConsoleKeyInfo inputKey;
static void Main(string[] args)
{
Console.Title = "";
Console.Write("Enter your value: ");
do
{
inputKey = Console.ReadKey(true);
if (char.IsDigit(inputKey.KeyChar))
{
if (inputKey.KeyChar == '0')
{
if (!backValue.StartsWith("0") || backValue.Contains('.'))
Write();
}
else
Write();
}
if (inputKey.KeyChar == '-' && backValue.Length == 0 ||
inputKey.KeyChar == '.' && !backValue.Contains(inputKey.KeyChar) &&
backValue.Length > 0)
Write();
if (inputKey.Key == ConsoleKey.Backspace && backValue.Length > 0)
{
backValue = backValue.Substring(0, backValue.Length - 1);
Console.Write("\b \b");
}
} while (inputKey.Key != ConsoleKey.Enter); //Loop until Enter key not pressed
if (double.TryParse(backValue, out value))
Console.Write("\n{0}^2 = {1}", value, Math.Pow(value, 2));
Console.ReadKey();
}
static void Write()
{
backValue += inputKey.KeyChar;
Console.Write(inputKey.KeyChar);
}
}
You can do it with a single line code as follows:
int n;
Console.WriteLine("Enter a number: ");
while (!int.TryParse(Console.ReadLine(), out n)) Console.WriteLine("Integers only allowed."); // This line will do the trick
Console.WriteLine($"The number is {n}");
You can change int into double in case you wanted to allow double instead of integers and so on.
string input;
double price;
bool result = false;
while ( result == false )
{
Console.Write ("\n Enter the cost of the item : ");
input = Console.ReadLine ();
result = double.TryParse (input, out price);
if ( result == false )
{
Console.Write ("\n Please Enter Numbers Only.");
}
else
{
Console.Write ("\n cost of the item : {0} \n ", price);
break;
}
}

Categories