Have a simple console app where user is asked for several values to input. Input is read via console.readline(). Ex
Name: Fred //string
Lastname: Ashcloud //string
Age: 28 //int
I would like to make sure that int and double types are entered and if the user enters garbage, lets him repeat the procedure.
Example, if the user enters "28 years old" where age expects int the app will crash. What is the best way to check for these inputs?
Right now I can only think of:
while (!Int32.TryParse(text, out number))
{
Console.WriteLine("Error write only numbers");
text = Console.ReadLine();
}
Is there any other way to do this? try catch statements if one wants to give a more detailed feedback to the user? How in that case?
For a console application, your code is perfectly fine.
However, you might want to abstract that into a reusable function so that you can read different numbers without repeating the code.
Also, you might want to provide some way for the user to cancel.
using System.Text.RegularExpressions;
int GetNumberFromString( string str_age )
{
Regex number = new Regex("[0-9][0-9]?");
Match n = number.Match(str_age);
if (n.Value != "")
return System.Convert.ToInt16(n.Value, 10);
else
return -1;
}
This will parse any data out besides the age or return -1 if no age is present.
this also assumes age 0-99.
Actually, your code is good. I would add negative number check, and perhaps huge number check too.
Regular Expressions are good.
Regex age = new Regex(#"^[0-9]*$");
while (!age.match(age_from_console)) {
Console.WriteLine("Age Invalid, try again ->");
}
Related
My goal is to actually make a guessing game, so I created two arrays with Mysql data called answers and questions. And what I want to do is take the value from the user and if it is true, for example my first answer 'fashion' matches the guess the user entered in the textbox, I want the label to write correct and continue with the next answer and try to find the next answer
My code returns true when I enter my values in the array into the textbox, but I want them to be in order. How do you think I can use the for loop. How do you think I can use the for loop to make an ordered comparison?
for (int i=0;i<cevaplar.Count;i++)
{
string tahmin = textBox1.Text;
if(cevaplar.Contains(tahmin))
{
label1.Text = "true";
continue;
}
else
{
label1.Text = "false";
break;
}
}
}
In your code you use "cevaplar.Contains(tahmin)". With contains you're checking if tahim can be found anywhere in your array, without taking any order in account.
The solution to your problem should be quite simple. Just don't use contains in this situation but use a simple indexer to compare the elements. Try the following:
Replace:
if(cevaplar.Contains(tahmin))
{
...
}
With
if(cevaplar[i] == tahim) //here you check only if the i'th element is matching.
{
...
}
Good luck!
Sorry if this is a simple question; this is my first language and I'm trying my best to seek out and follow examples and explanations on this site and otherwise.
I've been trying to expand on a Microsoft C# tutorial program that creates "bank accounts." I'm trying to work on catching and handling exceptions, specifically by prompting the user to try again for a valid input.
I've come across this thread and many similar threads about running a loop while the input is invalid, and this example specifically using try/catch, which if I'm understanding correctly, is what I want to use here because I have a few lines of code that could throw multiple exceptions (it could be non-numerical or it could be negative). Following those and other examples, I can't figure out how to assign the initial balance input to a value that I can reference outside the loop (but still only within the CreateAccount method) once the input is valid.
I'm not sure what I have currently is working otherwise, but currently this code produces an error because initBalInput is left unassigned after the while loop, even though it's declared outside the loop and assigned in the try block.
public static void CreateAccount()
{
// Prompt for BankAccount constructor parameter {name} which is passed to BankAccount.Owner in constructor
Console.WriteLine("Name on new account: ");
string nameInput = Console.ReadLine();
decimal initBalInput;
bool valid = false;
while (valid == false)
{
try
{
Console.WriteLine("How much to deposit for initial balance: ");
initBalInput = Convert.ToDecimal(Console.ReadLine());
}
catch (ArgumentOutOfRangeException)
{
Console.WriteLine("Initial balance must be positive!");
valid = false;
continue;
}
catch (FormatException)
{
Console.WriteLine("Initial balance must be a number!");
valid = false;
continue;
}
valid = true;
}
// Create new instance "account" of type BankAccount and set its parameters
BankAccount account = new BankAccount(nameInput, initBalInput);
Console.WriteLine($"Account {account.Number} was created for {account.Owner} with {account.Balance} initial balance.");
}
Instead of catching the exceptions, write the code that handles the invalid input.
public static void CreateAccount()
{
// Prompt for BankAccount constructor parameter {name} which is passed to BankAccount.Owner in constructor
Console.WriteLine("Name on new account: ");
string nameInput = Console.ReadLine();
string initBalInput = Console.ReadLine();
// try parse will check for invalid decimal values and also, positive values can be checked
if(decimal.TryParse(initBalInput, out decimal initBal) && initBal > 0) {
// Create new instance "account" of type BankAccount and set its parameters
BankAccount account = new BankAccount(nameInput, initBal);
Console.WriteLine($"Account {account.Number} was created for {account.Owner} with {account.Balance} initial balance.");
} else {
Console.WriteLine("Invalid initial balance");
}
}
but currently this code produces an error because initBalInput is left unassigned after the while loop, even though it's declared outside the loop and assigned in the try block
The problem is that the compiler doesn't know if execution will ever reach the try block:
while (valid == false)
is evaluated at runtime. You and me both know that execution will enter at least once the while loop because valid is initially false but the compiler doesn't go into that type of analysis where variables are involved and therefore assumes execution might never enter the while loop and an unitialized initBalInput can be read.
That said, you should not get into the habit of using exepctions as control flow mechanisms. Exceptions should be exceptions, don't base the logic of your programs around exceptions. In your case, you should look into the method decimal.TryParse.
Also, always break up your problem into smaller problems. At the beginning, start small, make one liner methods that are obviously correct. It's very hard to write a bug in methods that are one or two lines long.
So what do you need?
A method that prompts the user for an input.
A method that validates the input
Something that asks the user to try again if the input is wrong.
Ok, numer one:
static string RequestUserInput(string message)
{
Console.Write(message);
return Console.ReadLine();
}
Number two: We already have it with decimal.TryParse(string, out decimal d). This method will return true if the input string can be parsed into a valid decimal number which will be assigned to d and false otherwise.
Number three:
public static decimal GetDecimalInput(string message)
{
decimal d;
while (true)
{
if (!decimal.TryParse(RequestUserInput(message), out d))
//tryparse failed, input is not a valid decimal number
Console.WriteLine("Initial balance must be a number!");
else if (d < 0) //try parse succeeded, we know input is a valid
// decimal number d but it might be negative.
Console.WriteLine("Initial balance must be positive!");
else
//we know inout is a valid non negative decimal number.
//break out of the loop, we don't need to ask again.
break;
}
return d;
}
And now, you put it all together:
var accountBalance = GetDecimalInput("How much to deposit for initial balance: ");
First, I have two articles on Exception handling that I consider required reading:
This one helps to classify the 4 common exception types - and if you should even consider catching them.
While this one goes into more details for good practices.
You should not be using convert, but parse. Or even better TryParse(). The exceptions on the string -> number conversion are the examples for vexing exceptions.
If there is no TryParse, I did once wrote a custom implementation of Int.TryParse() for someone still on Framework 1.1:
//Parse throws ArgumentNull, Format and Overflow Exceptions.
//And they only have Exception as base class in common, but identical handling code (output = 0 and return false).
bool TryParse(string input, out int output){
try{
output = int.Parse(input);
}
catch (Exception ex){
if(ex is ArgumentNullException ||
ex is FormatException ||
ex is OverflowException){
//these are the exceptions I am looking for. I will do my thing.
output = 0;
return false;
}
else{
//Not the exceptions I expect. Best to just let them go on their way.
throw;
}
}
//I am pretty sure the Exception replaces the return value in exception case.
//So this one will only be returned without any Exceptions, expected or unexpected
return true;
}
But that code looks like you want to have detailed information why it failed. At wich point you may have to write a detailed list of catch blocks.
I am really into the basics of programming and while writing a few lines of code to convert Celsius to Fahrenheit, which is pretty easy I started to wonder the following:
Can I make the program show me an answer depending if I wrote in the Console:
25C //to convert to F
or for example 100F // to convert to C
So far my knowledge goes to advanced "if" constructs and "for" cycles. Just started to study "do-while".
I am missing some knowledge how to properly search an input for number && specific char in order to give proper calculation.
I know that it seems a little complicated to make input :
25F // in one line instead of
25
F
but this will expand my knowledge and understanding.
I will try the latter now, should be easy, but can't find out how to do the former.
Thanks in advance!
Darin
In C# any string is actually a class, which contains useful methods for example:
string input = "25F";
if (input.EndsWith("F"))
{
// handle Fahrenheit
}
Then you can get rid of the last character like so:
string inputWithoutLastCharacter = input.Substring(0, input.Length - 1);
To convert a string to a number you can:
try
{
int number = int.Parse(inputWithoutLastCharacter);
}
catch (Exception ex)
{
Console.WriteLine("Could not convert your input to a number " + ex.ToString());
}
Try/catch is there to handle error cases where the input is not a valid number.
Also check out other methods of string. For example ToLower() to handle both "f" and "F".
Good luck.
String temp = Console.ReadLine();
char scale = temp[temp.Length-1];
if(temp.ToUpper().Contains("F")) {
int temperature = Int32.Parse(temp.Remove(temp.Length-1,1));
double celciusValueOfTemp = (temperature-32)/1.8;
Console.WriteLine(celciusValueOfTemp);
}
else if(temp.ToUpper().Contains("C")) {
int temperature = Int32.Parse(temp.Remove(temp.Length-1,1));
double fahrenheitValueOfTemp = temperature*1.8+32;
Console.WriteLine(fahrenheitValueOfTemp);
}
I've tried to make a text adventure and a got an error when I get to the "if" part. I got it to work once but not like I wanted it.
I changed it a bit and then gave up and went to the original script but it wasn't working like last time and instead gave me this error:
cs0131 The left-hand side of an assingnment must be a variable,
property or indexer
Here is my code:
Console.WriteLine("What's your name");
string name = Console.ReadLine();
Console.Write("Hello " + name);
Console.WriteLine(" do you like games?");
Console.WriteLine("yes or no");
string yes = Console.ReadLine();
string no = Console.ReadLine();
if (Console.ReadKey() = yes) { Console.WriteLine("Great!, Lets play one"); }
//the error is at "if (console.readkey()"
In C# and many languages, there is a distinction between assigning a variable is equal to a value and testing for equality.
In C# = is used to assign values. int x = 1; will create a variable with the value 1.
== is used to test a value, so you would write if (x == 100) { /* something */ }
Going on your current code, you probably should have something more like this:
Console.WriteLine("yes or no");
string answer = Console.ReadLine();
if (answer == "yes") { Console.WriteLine("Great!, Lets play one"); }
Major differences are:
You are reading the answer a user types after asking yes or no, however in your code you are then trying to re-read another answer. Which doesn't quite make sense. The console will hang until the user enters another response.
As JamesFaix said, you are then trying to assign a value to Console.ReadKey() of whatever the user responded with first, after you asked them if they want to play. Instead you should be checking if the user's response was a positive reply.
Alright, nub question. I know. Basic response might be
Convert.ToInt32(string);
But naturally, C# does every natural process to make sure just that doesn't happen.
Here's my code:
while (true)
{
while (true)
{
//ask for time
Console.WriteLine("What is the hour?");
Console.WriteLine();
string s = Console.ReadLine();
//convert input to int
YourTime.nHour = Convert.ToInt32(s);
//check to see if it's legal
if ((YourTime.nHour <= 12) || (YourTime.nHour > 0))
{
break;
}
//etc etc code
}
}
I want to make sure the input is an actual hour. When I run this code, it always labels the if() statement as "true" and breaks, even if I inputted something like -13 or 99.
I'm sure there's a simple replacement for "Convert.ToInt32(s);", but to be honest it seems like I've tried everything. I decided it would be best to follow step-by-step instructions from people who are aware of the code at hand.
[EDIT] - Wrong operator, not the conversion. Thanks to everyone who helped!
You need to use AND not OR. So, change it to
if ((YourTime.nHour <= 12) && (YourTime.nHour > 0))
It's your if statement that's invalid, not the Convert.ToInt32
if ((YourTime.nHour <= 12) || (YourTime.nHour > 0)) will always be true. I think you meant to do if ((YourTime.nHour <= 12) && (YourTime.nHour > 0))
Do you mean no matter what integer you type in it always breaks?
If so its because no matter what integer you type in it will always pass one of those conditions.
i.e If I entered 10000000, it would still be greater than 0
and if I entered -10000000 it would still be less than 12
You just mixing two things that should not be mixed.
Converter from string to int should not have any business logic incorporated, that is model responsibility to know that this field is actually hours and not payment amount due
So to separate it you can use many things, for example data annotations, take a look at following code
public class MyTime
{
[Require]
[Range(0, 12, ErrorMessage = "Value for {0} must be between {1} and {2}.")]
public int Hours { get; set; }
[Require]
[Range(0, 59, ErrorMessage = "Value for {0} must be between {1} and {2}.")]
public int Minutes { get; set; }
}
this way you have model defined which can be validated against rules it knows about and you can get error message that has sense
PS this link can show you how to create custom validator if you are using data annotations outside asp.net mvc