c# input validation for strings and integers - c#

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();
}
}

Related

How to restrict decimal in a console calculator in C#? Like when a decimal is inputted, it should print an error. But no if doesn't

Can someone help me modify my work? Help me add:
An error message when the user tries to enter decimal values.
A third operand for the calculator.
An error message when the user tries to enter any string value other than “exit”.
Here's my code:
class Program
{
static void Main(string[] args)
{
do
{
Console.Write("x = ");
string str = Console.ReadLine();
if (str == "exit")
{
Console.WriteLine("The Programme has stopped");
continue;
}
else
{
int x = Convert.ToInt32(str);
Console.Write("y = ");
int y = Convert.ToInt32(Console.ReadLine());
int sum = x / y;
Console.WriteLine("Result: {0}", sum);
}
}
while (true);
}
}
I'd be very grateful.
Here is a function you can use:
public static bool HasDecimals(decimal x) {
return Decimal.Round(x, 0) != x;
}
If I were going to do this, I'd create a function that I can use to handle most of the user interaction (emitting the prompt, parsing the input string, deciding if "Exit" was entered). In the code below, I kinda-sorta use the standard TryGetXxx pattern.
In this code below, if the TryGetDecimalValueWithPrompt returns true, then a properly parsed number is returned in the output. If it returns false, then the user has chosen to quit.
So, I start with that function:
public static bool TryGetDecimalValueWithPrompt(string prompt, out decimal outputValue)
{
while (true)
{
Console.Write(prompt + " > ");
var response = Console.ReadLine();
if (response.Equals("exit", StringComparison.OrdinalIgnoreCase) || response.Equals("quit", StringComparison.OrdinalIgnoreCase))
{
outputValue = 0.0m;
return false;
}
if (decimal.TryParse(response, out outputValue))
{
return true;
}
//otherwise, failure, so try again
Console.WriteLine("Sorry, incorrect format, try entering a correctly formatted decimal again");
}
}
The while(true) statement says Loop Forever. In this case, Forever lasts until the user has entered a properly formatted number or one of the "exit" keywords.
Then I construct my program around it:
if (!TryGetDecimalValueWithPrompt("Enter the first operand", out var operand1))
{
return;
}
if (!TryGetDecimalValueWithPrompt("Enter the second operand", out var operand2))
{
return;
}
if (operand2 == 0.0m)
{
Console.WriteLine("Sorry, you can't divide by zero");
return;
}
Console.WriteLine($"The result of op1/op2 is {operand1 / operand2}");
If you don't want to allow decimals being entered, change the TryGetDecimalValueWithPrompt function to work with integers instead:
public static bool TryGetIntValueWithPrompt(string prompt, out int outputValue)
{
while (true)
{
Console.Write(prompt + " > ");
var response = Console.ReadLine();
if (response.Equals("exit", StringComparison.OrdinalIgnoreCase) || response.Equals("quit", StringComparison.OrdinalIgnoreCase))
{
outputValue = 0;
return false;
}
if (int.TryParse(response, out outputValue))
{
return true;
}
//otherwise, failure, so try again
Console.WriteLine("Sorry, incorrect format, try entering a correctly formatted integer again");
}
}
If you work with integers, remember that integer division always yields an integer. For example, if you use integers in 7 / 2, the result will be 3, not 3.5. If you want 3.5, do something like 7 / (decimal) 2 (at that point, you are dividing an integer by a decimal and you'll get a decimal).
By the way, if you wanted to prompt for the operator (+, -, *, or /), you could create a TryGetOperator function in the same pattern and just check whatever you get from the user with something like:
var operators = new[] { "+", "-", "*", "/" };
bool goodOperator = operators.Contains(inputFromUser);

how to only have numbers stored in an string array in console application

So, I am trying to create a pizza ordering program for my school project which requires the customer/user to input their details e.g name phone number address and what not. I store all those information into a string array, but how to I only allow numbers to be entered into the phone number section. I tried using a method which I have been provided with but it doesn't seem to work it just errors.
Here is my current code
public static string[] GetCustInfo(string [] custInfo)
{
start:
bool success = false;
Console.Write("\n" + "Please input D for Delivery OR P for Pickup($3 for Delivery): " + "\n");
custInfo[0] = Console.ReadLine();
while (success != true)
{
if (custInfo[0] == "D" || custInfo[0] == "d")
{
custInfo[1] = ReadString("Please enter your name: ");
Console.Write(Readint("Please enter your Ph No. : "));
custInfo[2] = Console.ReadLine();
custInfo[3] = ReadString("Please enter your adress: ");
success = true;
}
else if (custInfo[0] == "P" || custInfo[0] == "p")
{
custInfo[1] = ReadString("Please enter your name: ");
success = true;
}
else
{
goto start;
}
}
return custInfo;
}
Here are the methods I am using to prevent the user from entering a number or letter:
public static int Readint(String prompt)
{
int userInput = 0;
Boolean success = false;
while (!success)
{
Console.Write(prompt);
try
{
userInput = Convert.ToInt32(Console.ReadLine());
success = true;
}
catch
{
Console.WriteLine("Please Enter a VALID NUMBER");
}
}
return userInput;
}
public static string ReadString(String prompt)
{
string userInput = " ";
Boolean success = false;
while (!success)
{
Console.Write(prompt);
try
{
userInput = Console.ReadLine();
if (userInput.Length <= 20 && userInput.Length>1)
{
success = true;
foreach (char charcter in userInput)
{
if (Char.IsNumber(charcter) || Char.IsSymbol(charcter) || Char.IsPunctuation(charcter))
{
success = false;
}
}
}
if (success == false)
{
Console.WriteLine("Please enter a valid input!" + "\n");
}
else
{
success = true;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
return userInput;
}
I tried inserting:
custInfo[2] = Readint("Please enter your Ph No.");
but it just gave me an error saying:
"cannot implicate type int to string"
but how to I only allow numbers to be entered into the phone number
You ReadInt method already takes care of this point with the while-loop and the try/catch clause. If you want to store this information into the array you need to get your number into the correct/fitting data type for the array saying: string. You return value of ReadInt is an int and this class has an implementation of the ToString method which in your case would convert the int into a string. So you can simply call it on the returnvalue of ReadInt:
custInfo[1] = ReadString("Please enter your name: ");
custInfo[2] = Readint("Please enter your Ph No.").ToString();
custInfo[3] = ReadString("Please enter your adress: ");
Insted of public static string[] GetCustInfo(string [] custInfo), you might add array of an objects, but keep in mind next : Object array store elements of different types in a single collection. An object reference can point to any derived type instance.
Whatever you could do this :
object[] array1 = new object[5];
array1[0] = new object();
array1[1] = new StringBuilder("Initialized");
array1[2] = "String literal";
array1[3] = 3;
array1[4] = null;
So in your case: this might look like this
public static object[] GetCustInfo(object [] custInfo)
You trying to insert an int value into string array..surely make sense that you convert the value into a string?

Decline a string in a string variable

I need to decline the ability to write strings in my console application, at the moment, when text is entered instead of numbers, the console crashes.
I have something along the lines of this right now
class Program
{
static void Main(string[] args)
{
string[] names = new string[2];
string age;
bool agetest = false;
Console.WriteLine("Hello, I am the NameBot2000, What is your first name?");
names[0] = Console.ReadLine();
Console.WriteLine("Well done. What is your surname?");
names[1] = Console.ReadLine();
Console.WriteLine("What year were you born in?");
age = Console.ReadLine();
int.Parse(age);
if (Enumerable.Range(0,2015).Contains(age));
int year = 0;
string wow = "";
if (Enumerable.Range(0,31).Contains(year))
wow = "young";
else if (Enumerable.Range(31,51).Contains(year))
wow = "old";
else if (Enumerable.Range(51,500).Contains(year))
wow = "ancient";
Console.WriteLine("Well done. You said your name was {0} {1}, and you are {2} years old!", names[0], names[1], year);
Console.WriteLine("You are so {0}!", wow);
Console.ReadLine();
}
}
I have tried to incorporate a boolean but I am unsure how to compare the variable to check which format it is in.
Thanks heaps in advance!
Instead of Parse, use TryParse.
int age = 0;
if (Int32.TryParse(Console.Readline, out age)
// Correct format.
else
// error!
What TryParse() will do, is take the user input, Try to Parse it to an int, and if successful, will output an int (and a bool = true), otherwise it will output a bool = false.
use a try catch
string age = console.readline();
bool validage = false;
While(!validage)
{
try
{
int myage = int.parse(age);
validage = true;
}
catch
{
console.write("Please Enter an Integer value for age:");
age = console.readline();
}
}
You can check ConsoleKeyInfo to make sure user can only enter digits for age.
Console.WriteLine("Enter Age : ");
ConsoleKeyInfo key;
string ageStr = "";
do
{
key = Console.ReadKey(true);
if (key.Key != ConsoleKey.Backspace && key.Key != ConsoleKey.Enter)
{
if (char.IsNumber(key.KeyChar))//Check if it is a number
{
ageStr += key.KeyChar;
Console.Write(key.KeyChar);
}
}
else
{
if (key.Key == ConsoleKey.Backspace && ageStr.Length > 0)
{
ageStr = ageStr.Substring(0, (ageStr.Length - 1));
Console.Write("\b \b");
}
}
}
while (key.Key != ConsoleKey.Enter);
Console.WriteLine("Age is {0}", ageStr);

"Not all code paths return a value" error message

I wrote this method but it is giving me this error message.
"Not all code paths return a value" on GetInputstring
What do I have to do? Thanks in advance.
public string GetInputstring(string myInput)
{
int myInt;
Console.Write("Please enter a number: ");
myInput = Console.ReadLine();
myInt = Int32.Parse(myInput);
if (myInt <= 0)
{
Write1(myInt);
}
else
{
Write2(myInt);
}
Console.ReadKey();
}
You have to return string from the method but you are not returning the string that is reason for getting the error. You can return the input being taking from user and stored in myInput by using return statement.
public string GetInputstring(string myInput)
{
int myInt;
Console.Write("Please enter a number: ");
myInput = Console.ReadLine();
myInt = Int32.Parse(myInput)
if (myInt <= 0)
{
Write1(myInt);
}
else
{
Write2(myInt);
}
Console.ReadKey();
return myInput;
}
Your method does not return anything. If you are not going to return a value it should be set to void instead of public string GetInputString(string myInput) such as in the format public void GetInputString(string myInput). If you do actually want your method to return a value you must return something from each possible branch/path of your code.
In case you need some additional tips here is the MSDN documentation for the return reserved word: http://msdn.microsoft.com/en-us/library/1h3swy84.aspx

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