First of all, I am a complete newbie at programming and c#..so here is my dilemma.
The user should only enter a number, entering anything else should fail and repeat the question.
I have been using try catch but, as soon as the error gets thrown the user doesn't have a second chance to enter a number again, I just get an error and the ConsoleApp Closes.
This is my code atm
static public int AskInt(string question)
{
try
{
Console.Write(question);
return int.Parse(Console.ReadLine());
}
catch (Exception)
{
throw new FormatException("Please Enter a Number");
}
}
Thank you in advance.
static public int AskInt(string question)
{
int answer = 0;
bool successfullyParsed = false;
do
{
Console.Write(question);
successfullyParsed = int.TryParse(Console.ReadLine(), out var parsedAnswer);
if(!successfullyParsed){
Console.WriteLine("Only Numbers, dude");
}
answer = parsedAnswer;
} while (!successfullyParsed);
return answer;
}
Explaining a bit. TryParse will return a boolean indicating the success of the operation and an out variable with the result.
I can't return the parsedAnswer because it is in the context of the do loop.
You can make this code less legible but short. I tried to make it this why to be kinda of self explanatory.
Use below code which uses TryParse of int to parse the entered string. If TryParse succeed then it will break the while loop.
public static int AskInt(string question)
{
int questionId;
while (true)
{
Console.Write(question);
string input = Console.ReadLine();
if (int.TryParse(input , out questionId))
{
break;
}
}
}
int i=1;
while(i==1)
{
try {
Console.WriteLine("your question");
int number= int.Parse(Console.ReadLine());
i=0;
}
catch (Exception)
{
i=1;
Console.WriteLine("Please Enter a Number");
}
}
static public int AskInt(string question)
{
for (;;)
{
Console.Write(question);
if (int.TryParse(Console.ReadLine(), out int result))
{
return result;
}
}
}
Related
I'm working on this commandline based dice. And I want it to be able to output statistics and reset those internal statistics. Currently I have the following classes: Dice and DiceInterface.
I want the user to be able to use the following format for input: "'Throw' to throw the dice, alternate use 'Throw(x)', 'Stat(side)' to see how many times (side) has been thrown, or 'Reset' to reset thrown statistics"
I need a way to determine if the user has typed Throw, Throw(x), Stat(side) or Reset. Throw and Reset are obvious to me but I find it quite difficult to imagine a way to do Throw(x) and Stat(side). Does anyone have any tips or a solution?
Thanks in advance!
using System;
using System.Collections.Generic;
using System.Text;
namespace Oefening_2
{
class DiceInterface
{
static void Main()
{
StartProgram();
}
static void StartProgram()
{
Console.WriteLine("Hello, how many sides would you like the dice to have?");
var input = Console.ReadLine();
if (Int32.TryParse(input, out int number))
{
int desiredSides = number;
Dice NewDice = new Dice(desiredSides);
Console.WriteLine("What would you like to do? ");
Console.WriteLine("Type: 'Throw' to throw the dice, alternate use 'Throw(x)', 'Stat(side)' to see how many times (side) has been thrown, or 'Reset' to reset thrown statistics");
MainIO(NewDice);
}
else
{
Console.WriteLine("That is not an integer! The program will restart now...");
StartProgram();
}
}
static void MainIO(Dice CurrentDice)
{
Console.Write("Input: ");
string input = Console.ReadLine();
//Throw
if (input == "Throw")
{
Console.WriteLine(CurrentDice.Throw());
MainIO(CurrentDice);
}
//Throw(x)
else if(input == "")
//Thrown(side)
//Reset
else if (input == "Reset")
{
CurrentDice.ResetStatistics();
MainIO(CurrentDice);
}
}
}
}
using System;
namespace Oefening_2
{
class Dice
{
public int Sides { get; set; }
private readonly Random _rnd = new Random();
public int[] Thrown;
public Dice(int sides)
{
Sides = sides;
Thrown = new int[sides--];
}
public Dice():this(6)
{
}
public int Throw()
{
int thrownNumber = _rnd.Next(1, Sides);
Thrown[thrownNumber]++;
return thrownNumber;
}
public int NrOfTimesThrown(int side)
{
int result;
result = Thrown[side];
return result;
}
public void ResetStatistics()
{
for(int i = 0 ; i < Sides; i++)
{
Thrown[i] = 0;
}
}
}
}
This can be fairly simply done with StartsWith to check if a string starts with some prefix, and use .Remove to get anything after this prefix:
if(input.StartsWith("Stat"){
var parameterString = input.Remove(0, "Stat".Length);
if(int.TryParse(parameterString , out var side){
...
}
}
If I correctly understood your problem, it could be solved with an approach like this:
Console.WriteLine("Enter a value");
var s = Console.ReadLine();
if(s.Contains('('))
{
int pFrom = s.IndexOf("(");
int pTo = s.LastIndexOf(")");
var myChoice = s.Substring(0, pFrom);
var myValue = s.Substring(pFrom + 1, pTo - pFrom);
Console.WriteLine($"You choosed : {myChoice}");
Console.WriteLine($"With a value of: {myValue}");
}
This is just a brief example of how to "understand" if there is a value and then recover it.
I hope this could help you somehow.
namespace C2360_Ch07_Console1_InRange
{
class InRange
{
static void Main(string[] args)
{
Console.WriteLine("Num:");
String theLine;
theLine = Console.ReadLine();
try
{
theLine = Convert.ToInt32(Console.ReadLine());//cant convert
}
catch (FormatException)
{
Console.WriteLine("Input string was not in a correct format.");
}
IsWithinRange(theLine);
}
static void IsWithinRange(String theLine)
{
int Line1;
Int32.TryParse(Console.ReadLine(), out Line1);
try
{
if ((Line1 < 1) || (Line1 > 10))
{
throw new OverflowException();
}
}
catch (OverflowException)
{
Console.WriteLine("number must be between 1 and 10.");
}
Console.ReadLine();
}
}
}
What im trying to do is to convert string to integer to validate Main and IsWithinRange method. I get an error, where the comment is at, when I convert theLine to Int32.TryParse. Is this ever possible?
Anything would help?
I suggest extracting a method for reading integer value:
private static int ReadInteger(string title) {
while (true) {
Console.WriteLine(title);
if (int.TryParse(Console.ReadLine(), out int result))
return result;
Console.WriteLine("Incorrect syntax. Please, try again");
}
}
And then use it:
static void Main(string[] args) {
int theLine = 0;
while (true) {
theLine = ReadInteger("Num:");
// theLine is an integer, but we want an extra conditions meet:
if (theLine >= 1 && theLine <= 10)
break;
Console.WriteLine("The value must be in [1..10] range. Please, try again");
}
// from now on theLine is an integer in [1..10] range
//TODO: put relevant code here
}
Please, note, that exceptions FormatException, OverflowException are for exceptional behavior; here (user input validation), good old if is enough.
Edit: If you don't want to extract method (why?) but preserve IsWithinRange you can put something like this:
static void Main(string[] args) {
int theLine = 0;
while (true) {
Console.WriteLine("Num:");
if (!int.TryParse(Console.ReadLine(), out theLine)) {
Console.WriteLine("Syntax error. Please, try again");
continue;
}
if (IsWithinRange(theLine))
break;
Console.WriteLine("Sorry, the value is out of range. Please, try again");
}
// from now on theLine is an integer in [1..10] range
//TODO: put relevant code here
Where IsWithinRange can be
// Least Confusion Principle: For "Is [the value] Within Range" question
// the expected answer is either true or false
private static bool IsWithinRange(int value) {
return value >= 1 && value <= 10;
}
I'm having issues creating a program that is a number guessing program. I think I have the written part right but possibly not the order of it? I have to use multiple methods such as a method for number generator of the number that is supposed to be guessed, a method for collecting the guess input, and method for checking the guess to see if it's right. I've literally have tried just about everything for days but all I get is rather a repeat of, "Enter the number: " even if its right, although it's supposed to repeat if it's too high or low. Or sometimes the console won't print anything. what is wrong? Here is the code:
using System;
namespace GuessTheNumber
{
class Program
{
public static int RandomNumberGenerator()
{
Random random = new Random();
return random.Next(1, 21);
}
public static int InputGetter()
{
Console.Write("Enter in a number: ");
int guess = Convert.ToInt32(Console.ReadLine());
return guess;
}
public static String GuessChecker(int guess, int secretNumber)
{
if(guess > secretNumber)
{
return "Too high!";
}
else if (guess < secretNumber)
{
return "Too low!";
}
else
{
return "Correct";
}
}
static void Main(string[] args)
{
int secretNumber = 10;
Console.WriteLine("" + secretNumber);
while (true)
{
while (InputGetter() != secretNumber)
{
InputGetter();
GuessChecker(InputGetter(), secretNumber);
}
if (GuessChecker(InputGetter(), secretNumber) == ("Correct!"))
{
Console.WriteLine("Would you like to play again?");
String input = Console.ReadLine();
if (GuessChecker(InputGetter(), secretNumber) == ("Yes"))
{
secretNumber = RandomNumberGenerator();
}
else if (GuessChecker(InputGetter(), secretNumber) == ("No"))
{
break;
}
}
}
}
}
}
You are invoking InputGetter() multiple times and your logic is incorrect.
It has nothing to do with Random instance being used.
I have quickly modified your code and it should work now as follows:
New number is generated, if you enter low/high message is displayed, if you enter correct number you are presented with the Would you like to try again message.
EDIT: I did not want to change original code much,In general Comparing strings is bad, you should not use it. Creating enum like and comparing would be much better
class Program
{
public static int RandomNumberGenerator()
{
Random random = new Random();
var generatedNumber = random.Next(1, 21);
Console.WriteLine($"New Number generated! {generatedNumber}");
return generatedNumber;
}
public static int InputGetter()
{
Console.Write("Enter in a number: ");
int guess = Convert.ToInt32(Console.ReadLine());
return guess;
}
public static String GuessChecker(int guess, int secretNumber)
{
if (guess > secretNumber)
{
Console.WriteLine("Too High");
return "Too high!";
}
else if (guess < secretNumber)
{
Console.WriteLine("Too low!");
return "Too low!";
}
else
{
Console.WriteLine("Correct");
return "Correct";
}
}
static void Main(string[] args)
{
int secretNumber = 10;
Console.WriteLine("" + secretNumber);
while (true)
{
int enteredNumber = 0;
do
{
enteredNumber = InputGetter();
} while (GuessChecker(enteredNumber, secretNumber)!="Correct");
Console.WriteLine("Would you like to play again?[Yes/No]");
String input = Console.ReadLine();
if (input=="Yes")
{
secretNumber = RandomNumberGenerator();
}
else
{
break;
}
}
}
}
Hey guys this is what i got so far:
static string ConvertToInt()
{
string a = Console.ReadLine();
int num = int.Parse(a);
Console.WriteLine(num);
if (int.TryParse(a, out num))
{
return a;
}
else
{
return "-1";
}
}
What I'm trying to do is to write a custom Convert.ToInt function without actually using the method which is already available in the library. So I tried using int.Parse. It's also supposed to return -1 if the input by the user is NOT a number.
My problem here is that the application simply stops when debugging if I enter "a" and gives me the error that the input string is not in the correct format.
When testing the method, I created a new project with these modifications:
static void Main(string[] args)
{
string a = Console.ReadLine();
int num = int.Parse(a);
Console.WriteLine(num);
if (int.TryParse(a, out num))
{
Console.WriteLine(a);
}
else
{
Console.WriteLine("-1");
}
}
Thanks in advance.
remove the first Parse and leave it as int num;
static void Main(string[] args)
{
string a = Console.ReadLine();
int num;
if (int.TryParse(a, out num))
{
Console.WriteLine(a);
}
else
{
Console.WriteLine("-1");
}
}
Problem : int.Parse() throws FormatException when string is not in correct format.
Solution: remove the int.Parse() function and don't assign value to num variable
Try This:
string a = Console.ReadLine();
int num;
if (int.TryParse(a, out num))
{
Console.WriteLine(a);
}
else
{
Console.WriteLine("-1");
}
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