This question already has answers here:
Parse v. TryParse
(8 answers)
Closed 5 years ago.
I am doing something where I want a user to be able to enter a number between 0-9 and it spits out the word for it, eg. 1 into one. I am fine with the first part, however, I don't know how to get it so that it tells the user if it has entered an invalid number or letter.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _0_9_output
{
class Program
{
static void Main(string[] args)
{
Console.Write("Write a number between 0-9: ");
int number = int.Parse(Console.ReadLine());
if (number == 0)
{
Console.WriteLine("Zero");
}
else if (number == 1)
{
Console.WriteLine("One");
}
else if (number == 2)
{
Console.WriteLine("Two");
}
else if (number == 3)
{
Console.WriteLine("Three");
}
else if (number == 4)
{
Console.WriteLine("Four");
}
else if (number == 5)
{
Console.WriteLine("Five");
}
else if (number == 6)
{
Console.WriteLine("Six");
}
else if (number == 7)
{
Console.WriteLine("Seven");
}
else if (number == 8)
{
Console.WriteLine("Eight");
}
else if (number == 9)
{
Console.WriteLine("Nine");
}
else
{
(number >= 10);
}
{
Console.Write("That was an invalid statement.");
}
}
}
}
This is one of my first pieces of code so please be generous in giving tips/advice. I am a young programmer and I am only just beginning to learn this in school.
I suggest two main things:
Extracting model (i.e. numbers' names) s_Numbers array in the code below
Using int.TryParse instead of Parse (checking for bool is easier in the context than catching exception)
Something like this:
class Program {
// Model: numbers' names
private static string[] s_Numbers = new string[] {
"Zero", "One", "Two", "Three", "Four",
"Five", "Six", "Seven", "Eight", "Nine"
};
static void Main(string[] args) {
Console.Write("Write a number between 0-9: ");
// cyclomatic complexity reduction (10 ifs dropped),
// readability increasing
//
// out var number - C# 7.0 construction; if early C# version used:
//
// int number;
// if (int.TryParse(Console.ReadLine(), out number)) ...
//
if (int.TryParse(Console.ReadLine(), out var number))
if (number >= 0 && number <= 9)
Console.Write(s_Numbers[number]); // number in [0..9] range
else
Console.Write("Out of [0..9] range"); // number out of range
else
Console.WriteLine("That was an invalid statement."); // not an integer
}
}
You can change your code like below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _0_9_output
{
class Program
{
static void Main(string[] args)
{
Console.Write("Write a number between 0-9: ");
int number = int.Parse(Console.ReadLine());
if (number == 0)
{
Console.WriteLine("Zero");
}
else if (number == 1)
{
Console.WriteLine("One");
}
else if (number == 2)
{
Console.WriteLine("Two");
}
else if (number == 3)
{
Console.WriteLine("Three");
}
else if (number == 4)
{
Console.WriteLine("Four");
}
else if (number == 5)
{
Console.WriteLine("Five");
}
else if (number == 6)
{
Console.WriteLine("Six");
}
else if (number == 7)
{
Console.WriteLine("Seven");
}
else if (number == 8)
{
Console.WriteLine("Eight");
}
else if (number == 9)
{
Console.WriteLine("Nine");
}
else
{
Console.Write("That was an invalid statement.");
}
}
}
}
if input number isn't between 0-9 last else statement get execute and print message to output.
static void Main(string[] args)
{
string x = Console.ReadLine();
try
{
if (int.Parse(x) == 0)
{
Console.WriteLine("Zero");
}
else if (int.Parse(x) == 1)
{
Console.WriteLine("One");
}
else if (int.Parse(x) == 2)
{
Console.WriteLine("Two");
}
else if (int.Parse(x) == 3)
{
Console.WriteLine("Three");
}
else if (int.Parse(x) == 4)
{
Console.WriteLine("Four");
}
else if (int.Parse(x) == 5)
{
Console.WriteLine("Five");
}
else if (int.Parse(x) == 6)
{
Console.WriteLine("Six");
}
else if (int.Parse(x) == 7)
{
Console.WriteLine("Seven");
}
else if (int.Parse(x) == 8)
{
Console.WriteLine("Eight");
}
else if (int.Parse(x) == 9)
{
Console.WriteLine("Nine");
}
}
catch
{
Console.WriteLine("That was an invalid statement");
}
}
Related
Im trying to create a report card class and return a letter grade to main. I used a class constructor for the report card as the actual report card must be a class. In the event an invalid value is entered it will return an argument exception an prompt the user to try again. Here is my code:
using System;
using static System.Console;
class StudentGradeDemo
{
static void Main()
{
char lettergrade = new ReportCard();
}
class StudentGrades
{
public string studentName;
public double midtermGrade;
public double finalExamGrade;
public char letterGrade;
public char ReportCard(string studentName, double midtermGrade, double finalExamGrade)
{
char[] letterGrade = { 'A', 'B', 'C', 'D', 'F' };
Console.WriteLine("Enter midterm grade");
midtermGrade = Convert.ToInt32(Console.ReadLine());
if(midtermGrade >= 0 && midtermGrade <= 100)
{
Console.WriteLine("Enter final exam grade");
finalExamGrade = Convert.ToInt32(Console.ReadLine());
if (finalExamGrade >= 0 && midtermGrade <= 100)
{
double gradeAverage = ((midtermGrade + finalExamGrade) / 2);
if(gradeAverage >= 90 && gradeAverage <= 100)
{
return letterGrade[0];
}
else if(gradeAverage >= 80 && gradeAverage <= 90)
{
return letterGrade[1];
}
else if(gradeAverage >= 70 && gradeAverage <= 80)
{
return letterGrade[2];
}
else if(gradeAverage >= 60 && gradeAverage <= 70)
{
return letterGrade[3];
}
else if(gradeAverage < 60)
{
return letterGrade[4];
}
}
else
{
try
{
throw new System.ArgumentException();
}
catch (ArgumentException)
{
Console.WriteLine("Grades must be between 0 - 100");
return letterGrade[0];
}
}
}
else
{
try
{
throw new System.ArgumentException();
}
catch (ArgumentException)
{
Console.WriteLine("Grades must be between 0 - 100");
return letterGrade[0];
}
}
return letterGrade[0];
}
}
}
The error that returns is: Error CS0246 The type or namespace name 'ReportCard' could not be found (are you missing a using directive or an assembly reference?)
This first thing you need to do is create an instance of the StudentGrades class. This will allow you to access the ReportCard method, as it's a method of the class. (see #1). https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/methods
Next, if you look at the ReportCard method it takes 3 parameters: studentName, midtermGrade, finalGrade. These values MUST be passed into the method when you call it (see #2). https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/passing-parameters
static void Main()
{
var studentGrades = new StudentGrades(); // #1
Console.WriteLine("Enter student name");
var studentName = Console.ReadLine();
Console.WriteLine("Enter midterm grade");
var midtermGrade = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Enter final exam grade");
var finalExamGrade = Convert.ToDouble(Console.ReadLine());
var lettergrade = studentGrades.ReportCard(studentName, midtermGrade, finalExamGrade); // #2
Console.WriteLine($"{studentName}'s grade is an {lettergrade}");
}
Update: If you want to read input from the user, read in each line and assign to appropriate variable to pass in. I took this code from your ReportCard method, so you need to make sure to remove it from there. Also, you should be doing the appropriate type checking and handling for midterm and finalExamGrade. I'll leave that to you.
This is how to solve your problem:
class Program
{
static void Main(string[] args)
{
char lettergrade = StudentGrades.ReportCard();
}
}
public static class StudentGrades
{
public static char ReportCard()
{
char[] letterGrade = { 'A', 'B', 'C', 'D', 'F' };
Console.WriteLine("Enter midterm grade");
double midtermGrade = Convert.ToInt32(Console.ReadLine());
if (midtermGrade >= 0 && midtermGrade <= 100)
{
Console.WriteLine("Enter final exam grade");
double finalExamGrade = Convert.ToInt32(Console.ReadLine());
if (finalExamGrade >= 0 && midtermGrade <= 100)
{
double gradeAverage = ((midtermGrade + finalExamGrade) / 2);
if (gradeAverage >= 90 && gradeAverage <= 100)
{
return letterGrade[0];
}
else if (gradeAverage >= 80 && gradeAverage <= 90)
{
return letterGrade[1];
}
else if (gradeAverage >= 70 && gradeAverage <= 80)
{
return letterGrade[2];
}
else if (gradeAverage >= 60 && gradeAverage <= 70)
{
return letterGrade[3];
}
else if (gradeAverage < 60)
{
return letterGrade[4];
}
}
else
{
try
{
throw new System.ArgumentException();
}
catch (ArgumentException)
{
Console.WriteLine("Grades must be between 0 - 100");
return letterGrade[0];
}
}
}
else
{
try
{
throw new System.ArgumentException();
}
catch (ArgumentException)
{
Console.WriteLine("Grades must be between 0 - 100");
return letterGrade[0];
}
}
return letterGrade[0];
}
}
The else statement, "Weight must be greater than 0" is working, but if I were to enter a letter into my PackageWeight.Text textbox, the else statement won't show.
if (decimal.TryParse(PackageWeight.Text, out weight))
{
if (weight > 0)
{
weightcost = pound * weight;
Weight.Text = weightcost.ToString("c");
}
else
{
MessageBox.Show("Weight must be greater than 0.");
}
}
else
{
MessageBox.Show("Invalid input for weight.");
}
static void Main(string[] args)
{
Parse("1");
Parse("-1");
Parse("DDD");
}
private static void Parse(string x)
{
if (decimal.TryParse(x, out decimal weight))
{
if (weight > 0)
{
var weightcost = 2 * weight;
Console.WriteLine(weightcost.ToString("c"));
}
else
{
Console.WriteLine("Weight must be greater than 0.");
}
}
else
{
Console.WriteLine("Invalid input for weight.");
}
}
produces the correct output:
I'm trying to compile this code but I get an "not all code paths return a value" in judgeRockPaperScissors(). I need the three methods to work in the main method. I not sure what is wrong. I was having issues with converting int to strings as well. Any help would be great! Thank you!
using System;
using System.Windows.Forms;
class RockPaperScissors
{
static string response;
static string respond;
static string player1Sel;
static int player2Sel;
static int result;
static Random numberGenerator = new Random(); //Generates a random number.
public static void Main(string[] args)
{
Console.Write("Do you want to play Rock, Paper, Scissors?");// User writes yes or anything else.
respond = Console.ReadLine();
respond = respond.ToUpper(); //Makes the responce uppercase.
while (respond == "YES")
{ //Beginning of "while loop".
player1Sel = promptForInput();
player2Sel = generateAutoSelect();
result = judgeRockPaperScissors();
switch (result)
{
case 00:
Console.WriteLine("Draw!");
break;
case 12:
Console.WriteLine("Paper covers rock. Player 2 Wins!");
break;
case 23:
Console.WriteLine("Scissors cut paper. Player 2 Wins!");
break;
case 31:
Console.WriteLine("Rock smashes scissors. Player 2 Wins!");
break;
case 13:
Console.WriteLine("Rock smashes scissors. Player 1 Wins!");
break;
case 21:
Console.WriteLine("Paper covers rock. Player 1 Wins!");
break;
case 32:
Console.WriteLine("Scissors cut paper. Player 1 Wins!");
break;
}// End of switch.
Console.Write("Do you want to play again?");// Where the player decides to play again.
respond = Console.ReadLine();
respond = respond.ToUpper();
} //End of "while loop".
} //End of Main.
private static int judgeRockPaperScissors()
{
throw new NotImplementedException();
}
public static string promptForInput()
{
Console.Write("Player one, make a selection. Type 1=rock, 2=paper, or 3=scissors and press enter: ");
player1Sel = Console.ReadLine();
if (player1Sel == "")
{
MessageBox.Show("You must select a valid choice.");
Environment.Exit(0);
}
else
if (int.Parse(player1Sel) < 1 | int.Parse(response) > 3)
{
MessageBox.Show(response + " - is not a valid choice.");
Environment.Exit(0);
}
return player1Sel;
}// End of promptForInput.
public static int generateAutoSelect()
{
int player2Sel = numberGenerator.Next(1, 4);//Generates random number between 1 and 3.
if (player2Sel == 1)
{
MessageBox.Show("Player2 chose rock.");
}
else
if (player2Sel == 2)
{
MessageBox.Show("Player2 chose paper.");
}
else
if (player2Sel == 3)
{
MessageBox.Show("Player2 chose scissors.");
}
return player2Sel;
} // End of generateAutoSelect.
public static string judgeRockPaperScissors(int player1Sel, int player2Sel)
{
if (player1Sel == player2Sel)
{ return "00"; }
else if (player1Sel == 1 && player2Sel == 2)
{ return "12"; }
else if (player1Sel == 2 && player2Sel == 3)
{ return "23"; }
else if (player1Sel == 3 && player2Sel == 1)
{ return "31"; }
else if (player1Sel == 1 && player2Sel == 3)
{ return "13"; }
else if (player1Sel == 2 && player2Sel == 1)
{ return "21"; }
else if (player1Sel == 3 && player2Sel == 2)
{ return "32"; }
}// End of judgeRockPaperScissors.
} // End of class.
The compiler does not know that you have handled all possible cases in your if/else if blocks because the range of int is far more than 0-2. The easiest way to get your code compiling is to add a generic else block:
...
else
{
throw new ArgumentException("Player selections out of range");
}
Since the input is invalid throw an exception.
On a side note, using strings the way you are is definitely not the right approach.
Update the function to return null if no conditions are met:
public static string judgeRockPaperScissors(int player1Sel, int player2Sel)
{
if (player1Sel == player2Sel)
{ return "00"; }
else if (player1Sel == 1 && player2Sel == 2)
{ return "12"; }
else if (player1Sel == 2 && player2Sel == 3)
{ return "23"; }
else if (player1Sel == 3 && player2Sel == 1)
{ return "31"; }
else if (player1Sel == 1 && player2Sel == 3)
{ return "13"; }
else if (player1Sel == 2 && player2Sel == 1)
{ return "21"; }
else if (player1Sel == 3 && player2Sel == 2)
{ return "32"; }
return null;
}
That way it will always return with something. You'll also want to add a null check on the result variable in your main function to make sure it didn't return null.
Long story short, I am making an ATM application for a school assignment. Bank account information needs to be stored into a file to keep those account balances up to date.
I have two questions - (1) In the serialization process I get an error on line 49 that says:
(field)Account[] RunAccount.acctArray
An object reference is required for the non-static field, method, or property 'RunAccount.acctArray'
(2) Do my read-in and read-out serialization locations make sense?
I am very new at this and feel like I have no idea what I am doing so all advice is appreciated and welcome. Thanks!
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
namespace Bank_Midterm_Project
{
public class RunAccount
{
Account[] acctArray = new Account[3];
private static int i;
bool acctscreated = false;
bool acctsloaded = false;
private object test;
public static void Main(String[] args)
{
RunAccount ra = new RunAccount();
int input;
do
{
Console.WriteLine("Please enter a choice:");
Console.WriteLine("1) Populate Accounts");
Console.WriteLine("2) Load Accounts From File");
Console.WriteLine("3) Select Account");
Console.WriteLine("4) Exit");
input = Convert.ToInt32(Console.ReadLine());
if (input == 1 && ra.acctscreated == false)
{
ra.populateArray();
}
else if (input == 2 && ra.acctsloaded == false)
{
ra.readArray();
}
else if (input == 3 && ra.acctscreated == true)
{
ra.pickAccountMenu();
}
else if (input == 4)
{
Stream FileStream = File.Create("test.xml");
XmlSerializer serializer = new XMLSerializer(typeof(Account[]));
serializer.Serialize(FileStream, acctArray);
FileStream.Close();
}
else
{
if (input == 1 && ra.acctscreated == true)
{
Console.WriteLine("You have already populated the accounts. Please try again.");
}
else if (input == 2 && ra.acctscreated == true)
{
Console.WriteLine("You have already loaded the accounts. Please try again.");
}
else if (input == 3 && ra.acctscreated == false)
{
Console.WriteLine("You must create the accounts first. Please try again.");
}
}
} while (input != 5);
//ATM atm = new ATM();
//atm.topMenu();
//ra.writeArray();
//{
//}
}
//private void readArray()
//{
// throw new NotImplementedException();
public void readArray()
{
Stream FileStream = File.OpenRead("test.xml");
XmlSerializer deserializer = new XmlSerializer(typeof(Account[]));
acctArray = (Account[])deserializer.Deserialize(FileStream);
FileStream.Close();
}
//}
public void populateArray()
{
//int[] acctArray = new int[3];
//prompt for username
Console.WriteLine("Please enter three account numbers, separated by spaces:");
string[] tokens = Console.ReadLine().Split();
for (int i = 0; i < acctArray.Length; i++)
{
acctArray[i] = new Account(tokens[i]);
}
acctscreated = true;
}
public void pickAccountMenu()
{
string sinput = null;
int input = -1;
while (input != 4)
{
Console.WriteLine("Please enter 0, 1, or 2 for your account. 4 to quit.");
sinput = Console.ReadLine();
input = Convert.ToInt32(sinput);
if (input != -99)
{
acctArray[input].menu();
}
}
}
}
internal class XMLSerializer : XmlSerializer
{
public XMLSerializer(Type type) : base(type)
{
}
}
}
Use ra.acctArray. You have to access that property using the class instance variable.
I have written my codes and i want to validate it in such a way thet it will only allow intergers to be inputed and not alphabets. Here is the code, please I will love you to help me. Thanks.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace minimum
{
class Program
{
static void Main(string[] args)
{
int a = Convert.ToInt32(Console.ReadLine());
int b = Convert.ToInt32(Console.ReadLine());
int c = Convert.ToInt32(Console.ReadLine());
if (a < b)
{
if (a < c)
{
Console.WriteLine(a + "is the minimum number");
}
}
if (b < a)
{
if (b < c)
{
Console.WriteLine(b + "is the minimum number");
}
}
if (c < a)
{
if (c < b)
{
Console.WriteLine(c + "is the minimum number");
}
}
Console.ReadLine();
}
}
}
You should test if it's an int instead of converting in right away.
Try something like :
string line = Console.ReadLine();
int value;
if (int.TryParse(line, out value))
{
// this is an int
// do you minimum number check here
}
else
{
// this is not an int
}
Simply call Readline() and loop with Int.TryParse until the user inputs a valid number :)
int X;
String Result = Console.ReadLine();
while(!Int32.TryParse(Result, out X))
{
Console.WriteLine("Not a valid number, try again.");
Result = Console.ReadLine();
}
Hope that helps
To get the console to filter out alphabetical keystrokes you have to take over input parsing. The Console.ReadKey() method is fundamental to this, it lets you sniff the pressed key. Here's a sample implementation:
static string ReadNumber() {
var buf = new StringBuilder();
for (; ; ) {
var key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter && buf.Length > 0) {
return buf.ToString() ;
}
else if (key.Key == ConsoleKey.Backspace && buf.Length > 0) {
buf.Remove(buf.Length-1, 1);
Console.Write("\b \b");
}
else if ("0123456789.-".Contains(key.KeyChar)) {
buf.Append(key.KeyChar);
Console.Write(key.KeyChar);
}
else {
Console.Beep();
}
}
}
You could add, say, Decimal.TryParse() in the if() statement that detects the Enter key to verify that the entered string is still a valid number. That way you can reject input like "1-2".
Do not Convert the input from the user immediately. Put it in a string and use Int32.TryParse(...) to find out whether or not a number was entered. Like this:
int i;
string input = Console.ReadLine();
if(Int32.TryParse(input, out i))
{
// it is a number and it is stored in i
}
else
{
// it is not a number
}
Note that
if (a < b) {
if (a < c) {
is equivalent to
if (a < b && a < c) {
and that this latter form introduces less nesting and is more readable, particularly if your code grows more complex. Also, you should probably never use Convert.ToInt32 - it has a particularly ill-conceived and surprising corner case; and it's also less type-safe than int.Parse which is the superior choice where possible - or int.TryParse when you're unsure whether the string is valid. Basically, avoid Convert.... wherever possible.
string Temp;
int tempInt,a;
bool result=false;
while ( result == false )
{
Console.Write ("\n Enter A Number : ");
Temp = Console.ReadLine ();
result = int.TryParse (Temp, out tempInt);
if ( result == false )
{
Console.Write ("\n Please Enter Numbers Only.");
}
else
{
a=tempInt;
break;
}
}
My preferred solution would be:
static void Main()
{
Console.WriteLine(
(
from line in Generate(()=>Console.ReadLine()).Take(3)
let val = ParseAsInt(line)
where val.HasValue
select val.Value
).Min()
);
}
static IEnumerable<T> Generate<T>(Func<T> generator) {
while(true) yield return generator();
}
static int? ParseAsInt(string str) {
int retval;
return int.TryParse(str,out retval) ? retval : default(int?);
}
Of course, depending on the specification (should invalid number be retried?), it may need to be tweaked.
Double/Float:
I'm just extending #Hans Passant answer (Taking care of DecimalSeparator and "-"):
static double ReadNumber()
{
var buf = new StringBuilder();
for (; ; )
{
var key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter && buf.Length > 0)
{
Console.WriteLine();
return Convert.ToDouble(buf.ToString());
}
else if (key.Key == ConsoleKey.Backspace && buf.Length > 0)
{
buf.Remove(buf.Length - 1, 1);
Console.Write("\b \b");
}
else if (System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator.Contains(key.KeyChar) && buf.ToString().IndexOf(System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator) == -1)
{
buf.Append(key.KeyChar);
Console.Write(key.KeyChar);
}
else if ("-".Contains(key.KeyChar) && buf.ToString().IndexOf("-") == -1 && buf.ToString() == "")
{
buf.Append(key.KeyChar);
Console.Write(key.KeyChar);
}
else if ("0123456789".Contains(key.KeyChar))
{
buf.Append(key.KeyChar);
Console.Write(key.KeyChar);
}
else
{
Console.Beep();
}
}
}
var getInput=Console.ReadLine();
int option;
//validating input
while(!int.TryParse(getInput, out option))
{
Console.WriteLine("Incorrect input type. Please try again");
getInput=Console.ReadLine();
}
Try This Simple
try
{
string x= "aaa";
Convert.ToInt16(x);
//if success is integer not go to catch
}
catch
{
//if not integer
return;
}