I have tried to create a C# program that gives the user 3 options:
Create name (gets the user to enter their first name and surname and display it as J.Blogg)
Factorial of a number (outputs as for example 5x4x3x2x1 =120 which is the factorial of 5
Quit
I have the program work fine but when I try picking option 1 (create name) and then option 2 it goes to option 1 instead and then it doesn't lets me Quit (option 3).
I'm new to programming so it could be simple but I can't see where i'm going wrong,
Any help would be very greatful.
I want to keep the same layout, I think my problem could be the loops but any help and improvement would be great.
static void Main(string[] args)
{
//The value returned from the topmenu method is stored in a variable called useroption
int useroption;
useroption = topmenu();
// excute while loop untill option is not 1-3
do
{
if (useroption == 1)
{
Console.Clear();
Createname();
//break;
}
if (useroption == 2)
{
Console.Clear();
factorial();
// break;
}
if (useroption == 3)
{
Console.Clear();
Console.WriteLine("Thank you for using my program, Good bye !!!");
// break;
}
//topmenu();
}
while (useroption != 3);
Console.ReadKey();
}
//This method present the user with an menu which the user has a choice of 3 options
static int topmenu()
{
int option;
string option_str;
Console.Clear();
Console.WriteLine("********************************************************************************");
Console.WriteLine("********************************************************************************");
Console.WriteLine("********* OPTION 1 : Enter your name *********");
Console.WriteLine("********* OPTION 2 : Enter the number you want to factorise *********");
Console.WriteLine("********* OPTION 3 : Quit *********");
Console.WriteLine("********************************************************************************");
Console.WriteLine("********************************************************************************");
option_str = Console.ReadLine();
option = Convert.ToInt32(option_str);
Console.Clear();
if (option < 0 || option > 3)
{
Console.WriteLine("You have enter an invald option,");
Console.WriteLine("Please chose a option between 1-3 (Please press any key to return to main menu)");
Console.ReadLine();
Console.Clear();
topmenu();
}
else
{
Console.WriteLine("You have chosen option: " + option + " (Please press any key continue)");
}
Console.ReadKey();
return option;
}
//this method asks user to enter their name (1st name then surname) and presents it back to the user as their intial(1st name) and surname
static void Createname()
{
string firstname, surname, firstname_str, surname_str, userfullname;
Console.Clear();
Console.WriteLine("Please enter your first name ");
firstname_str = Console.ReadLine();
firstname = Convert.ToString(firstname_str);
Console.Clear();
Console.WriteLine("Please enter your surname name ");
surname_str = Console.ReadLine();
surname = Convert.ToString(surname_str);
Console.Clear();
userfullname = firstname + surname;
Console.WriteLine("You have entered your name as " + firstname[0] + "." + surname);
Console.WriteLine("(Please press any key to return to main menu)");
Console.ReadKey();
topmenu();
}
//this method asks the user to enter a number and returns the factorial of that number
static double factorial()
{
string number_str;
double factorial = 1;
Console.WriteLine("Please enter number");
number_str = Console.ReadLine();
int num = Convert.ToInt32(number_str);
// If statement is used so when the user inputs 0, INVALID is outputed
if (num <= 0)
{
Console.WriteLine("You have enter an invald option");
Console.WriteLine("Please enter number");
number_str = Console.ReadLine();
Console.Clear();
num = Convert.ToInt32(number_str);
//Console.Clear();
//topmenu();
//number_str = Console.ReadLine();
}
if (num >= 0)
{
while (num != 0)
{
for (int i = num; i >= 1; i--)
{
factorial = factorial * i;
Console.Write(i + " * ");
}
Console.WriteLine("= "+factorial+ " which is factorial of " + number_str.ToString() );
Console.WriteLine("(please any key to return to main menu)");
Console.ReadKey();
Console.Clear();
topmenu();
}
}
return factorial;
}
}
}
Just put these line inside do...while
int useroption;
useroption = topmenu();
rearrange as following...
int useroption;
// excute while loop untill option is not 1-3
do
{
useroption = topmenu();
and your program will work fine
The full code is here : http://pastebin.com/fCh0ttUY
First of al, set useroption to 0 after executing some code. Otherwise it will keep executing it.
Second, ReadKey() right before your while statement. Otherwise you won't be able to read the input.
The issue is that although you display topmenu again you never re-assign the value of useroption.
As gypsyCoder said, moving the display of your menu inside the do{}while() block will fix your issue because it will cause the useroption to be re-assigned each time round the loop.
Related
This question already has answers here:
check for valid number input - console application
(5 answers)
Allow To Only Input A Number - C#
(1 answer)
Closed 2 years ago.
I have just started a table programme. I am just a trainee learning C# from internet, so I am not so good in this.
I just wanted the programme to run according to the user. I want that if the user hits enter simply, the programme should not crash. That is I just wanted to know how to prevent null enter. This is the code is used:
The "______" which used if for writing a line
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace tables
{
class Program
{
static void Main(string[] args)
{
goto found;
found:
Console.WriteLine("");
string textToEnter = "MULTIPLATION TABLES";
Console.WriteLine(String.Format("{0," + ((Console.WindowWidth / 2) + (textToEnter.Length / 2)) + "}", textToEnter));
Console.WriteLine("");
Console.WriteLine("________________________________________________________________________________");
Console.WriteLine("");
int num, j, i;
Console.Write("enter the number of which table u need ? :- ");
num = Convert.ToInt32( Console.ReadLine());
while (num == 0)
{
Console.WriteLine("please enter a valid input");
Console.Write("enter the number of which table u need ? :- ");
num = Convert.ToInt32(Console.ReadLine());
}
Console.Write("enter the number till which the table need to be ? :- ");
j = Convert.ToInt32(Console.ReadLine());
while (j == 0)
{
Console.WriteLine("please enter a valid input");
Console.Write("enter the number till which the table need to be ? :- ");
j = Convert.ToInt32(Console.ReadLine());
}
i = Convert.ToInt32(j);
for (j=1; ; j++)
{
if (j > i)
{
break;
}
Console.WriteLine(num + " * " + j + " = " + num * j);
}
string str;
Console.Write("do you want to continue? (y/n) :- " );
str= Console.ReadLine();
foreach (char ch in str)
{
if (ch == 'y')
{
goto found;
}
else if (ch=='n' )
{
Console.WriteLine("");
Console.WriteLine("THANK YOU FOR USING MY PRODUCT");
}
else
{
Console.WriteLine("please enter a valid input");
}
}
Console.ReadKey();
}
}
}
As suggested in the comments, I'd use int.TryParse(), but inside a do...while() loop. Use a separate flag (boolean) to track whether the user should keep trying again:
bool invalid;
int num, j, i;
do
{
invalid = true;
Console.Write("enter the number of which table u need ? :- ");
String response = Console.ReadLine();
if (int.TryParse(response, out num))
{
invalid = false;
}
else
{
Console.WriteLine("Invalid input. Please try again.");
}
} while (invalid);
// ...repeat the above do...while() block for "j" and "i"...
When you're accepting user input, it's important to perform validation on it. You can't assume that the user will always enter correctly formatted data that your program will be able to work with. As you discovered, a user who hits enter will give you an empty string (""), which can't be parsed to anything.
C# has several ways of attempting parsing. The first, which you're using, is Convert.ToInt32(), which throws an exception if the input it receives is not, in fact, a number. You have to catch the exception with a try/catch block, like so:
try
{
num = Convert.ToInt32(Console.ReadLine());
}
catch(FormatException ex)
{
Console.WriteLine("You didn't enter a proper number!");
}
However, in general, exceptions should be, well, exceptional. They should only be relied upon when rare failures occur, because unwinding the call stack can be expensive.
I would argue that C# has a better method for you to use in this instance: Int32.TryParse()
You can see the documentation here.
TryParse takes two parameters, the thing you're trying to parse (convert), and then a number to store the value in. It returns true or false, indicating if it succeeded or failed in converting the number.
You might use it like this:
var success = Int32.TryParse(Console.ReadLine(), num);
if (success)
{
// do something with 'num' -- it has a valid value now.
}
else
{
// Warn the user, perhaps prompt them to try again
Console.WriteLine("That wasn't a valid number!");
}
You can use a methode to get a safe int value:
private static int ReadIntValue(string psMessage)
{
int lnInt;
string lsValue = string.Empty;
do
{
Console.Write(psMessage);
lsValue = Console.ReadLine();
} while (!int.TryParse(lsValue, out lnInt));
return lnInt;
}
And then use this:
num = ReadIntValue("enter the number of which table u need ? :- ");
I am trying to create the menu for a mastermind game which can be ran in a command prompt using C#. The issue I am running into is capturing the users input for the menu. If they enter a 2 then it should display that they entered the number two and if not then it would say they have not displayed the number two.
The issue I am having is that it wont turn the users input into a working integer and will either come up saying that it can't explicitly convert from System.ConsoleKeyInfo to int or string to int.
using System;
namespace MasterMind
{
class Program
{
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(" MasterMind's Main Menu");
Console.WriteLine(" 1: Play");
Console.WriteLine(" 2: Help");
Console.WriteLine(" 0: Exit");
int userinput = Console.ReadKey();
if (Nuserinput == 2);
{
Console.WriteLine("This is a number 2");
}
else
{
Console.WriteLine("This is not a number 2");
}
}
}
}
Console.ReadKey() returns a ConsoleKeyInfo object, which is not an int object. You can get a char from that, for example:
var key = Console.ReadKey();
var keyChar = key.KeyChar;
If you expect that char value to represent an integer, you can convert it to one:
int keyInt = (int)Char.GetNumericValue(keyChar);
Aside from other error checking you might want to put in place in case the user doesn't enter a valid integer, this would at least get your the integer value you're looking for.
Console.ReadKey() returns a ConsoleKeyInfo, so you'll need to do something like this:
ConsoleKeyInfo data = Console.ReadKey();
int num;
if (int.TryParse(data.KeyChar.ToString(), out num) && num == 2)
{
Console.WriteLine("This is a number 2");
}else{
Console.WriteLine("This is not a number 2");
}
Change your
int userinput = Console.ReadKey();
if (Nuserinput == 2)
To:
string userInput = Console.ReadKey().KeyChar.ToString();
if(input == "2")
Or covert the string to an int as shown in other answers. But for this, a string works fine.
I've put in a loop with Try.Parse so that if the user enters a decimal number, the program will ask them to enter another number until they put in a integer and then the program will carry on with the next part.
However what i'm struggling with is putting in another loop that makes it so that the user can only enter a number between 1 and 100, and if they don't there should be an error message that loops until they do enter this. Id like them to run at the same time and i have this one, but i want it to also check whether its in the range and i'm not sure how to do that.
I'm new to programming so I'm not great at this.
Thank you in advance!
string inputcost;
string inputmoney;
int validcost;
int validmoney;
int changereq;
Console.Write("Please Enter The Cost, In Pennies, Of The Item You Have Purchased: ");
inputcost = Console.ReadLine();
bool result = int.TryParse(inputcost, out validcost);
while (!int.TryParse(inputcost, out validcost))
{
if (result == true)
{
Console.Write("Valid Value");
}
if (result == false)
{
Console.Write("Please Enter A Valid Integer Value");
Console.WriteLine();
inputcost = Console.ReadLine();
}
}
Your problem here is that the result variable you're looking at is only written once: outside the loop. Consider trying something like the following pseudocode (a do-while loop works exactly the same as a while loop, except it always gets executed once before the condition is checked):
bool validInput;
do
{
// If you set it true to begin with, you can set it false on any unmet conditions
// If it doesn't get set false, you've got a valid input and can exit the loop.
validInput = true;
Read input from user
Check if it's a valid integer, if not print message and validInput = false
Check if it's between 1-100, if not print message and validInput = false;
} while (!validInput);
Then if you want to tackle something more advanced, look at the continue keyword.
Try something like this.
string inputcost;
string inputmoney;
int validcost;
int validmoney;
int changereq;
while (true)
{
Console.Write("Please Enter The Cost, In Pennies, Of The Item You Have Purchased: ");
inputcost = Console.ReadLine();
if (!(valuecost >=1 && valuecost <=100))
{
Console.Write("Please enter value between 1 and 100.");
}
bool result = int.TryParse(inputcost, out validcost);
if (result == true)
{
Console.Write("Valid Value");
}
if (result == false)
{
Console.Write("Please Enter A Valid Integer Value");
}
}
It would be useful to use a method and do something like:
Console.Write("Please Enter The Cost, In Pennies, Of The Item You Have Purchased: ");
inputcost = Console.ReadLine();
bool result = false;
while (!result)
{
result = checkNumber();
}
public static bool checkNumber()
{
if(inputcost < 1 || inputcost > 100)
{
Console.Write("Please Enter a valid value: ");
inputcost = Console.ReadLine();
return false;
}
else
return true;
}
Hope this helps.
string inputcost;
string inputmoney;
int validcost = 0;
int validmoney = 0;
Console.Write("Please Enter The Cost, In Pennies, Of The Item You Have Purchased: ");
inputcost = Console.ReadLine();
// only accept integers
while (!int.TryParse(inputcost, out validcost))
{
Console.Write("Please Enter An Integer Value: ");
inputcost = Console.ReadLine();
}
// valid integer input in variable validcost
bool done = false;
while (!done)
{
Console.Write("Enter an integer between 1 and 100: ");
inputmoney = Console.ReadLine();
if (int.TryParse(inputmoney, out validmoney))
{
if (validmoney > 0 && validmoney < 101)
{
done = true;
}
else
{
Console.WriteLine("Invalid input: " + inputmoney);
}
}
else
{
Console.WriteLine("Invalid input: " + inputmoney);
}
}
//validcost is an integer and validmoney is an integer between 1 and 100
Console.WriteLine("validcost: " + validcost + " validmoney: " + validmoney);
Console.ReadKey();
Couldn't find any other answer on the site that covers this. If else is run and an error message is displayed, is it possible to restart the program by looping back to the start instead of restarting the console?
class Program
{
static void Main(string[] args)
{
int User;
int Array;
StreamWriter outfile = new StreamWriter("C://log.txt");
Console.WriteLine("Input an number between 1 and 100");
User = Convert.ToInt32(Console.ReadLine());
if (User < 101 && User > 0)
{
for (Array = 1; Array <= User; Array++)
{
Console.WriteLine(Array + ", " + Array * 10 * Array);
outfile.WriteLine(Array + ", " + Array * 10 * Array);
}
{
Console.WriteLine("Press Enter To Exit The Console");
outfile.Close();
Console.ReadLine();
}
}
else
{
Console.WriteLine("Sorry you input an invalid number. ");
Console.ReadLine();
}
}
}
Sorry! To be more clear I need to make the Program start again if the user inputs an invalid number
Thanks for the help!
You can do this instead
User = Convert.ToInt32(Console.ReadLine());
while (User >= 101 || User <= 0)
{
Console.WriteLine("Sorry you input an invalid number. ");
User = Convert.ToInt32(Console.ReadLine());
}
An easy way of doing this is placing your code inside a while loop, so that the code keeps repeating. The only way to exit the loop would be for the condition you just set in the if clause to be true. So something along the lines of:
class Program
{
static void Main(string[] args)
{
int User;
int Array;
bool isUserWrong = true; //This is a flag that we will use to control the flow of the loop
StreamWriter outfile = new StreamWriter("C://log.txt");
while(isUserWrong)
{
Console.WriteLine("Input an number between 1 and 100");
User = Convert.ToInt32(Console.ReadLine());
if (User < 101 && User > 0)
{
for (Array = 1; Array <= User; Array++)
{
Console.WriteLine(Array + ", " + Array * 10 * Array);
outfile.WriteLine(Array + ", " + Array * 10 * Array);
}
isUserWrong = false; // We signal that we may now leave the loop
}
else
{
Console.WriteLine("Sorry you input an invalid number. ");
Console.ReadLine();
//Note that here we keep the value of the flag 'true' so the loop continues
}
}
Console.WriteLine("Press Enter To Exit The Console");
outfile.Close();
Console.ReadLine();
}
}
I'm making a program that has little programs inside of it, and I've come to a dilemma. On my first mini-program which rearranges digits to find the greatest possible number from those digits, it asks if the user wants to quit. If they respond "Yes" then the function returns 0 which is evaluated in the main(string[] args) method. My problem is that whenever the user says "No", the mini-program still doesn't continue. Here's my source:
namespace ACSL_Competition
{
class Program
{
static int DigitRearranger()
{
string[] mainString = {};
Console.WriteLine("---------Welcome to the Digit Re-arranger!---------");
Console.WriteLine("I take a positive number up to 10000, and find the highest number that can be made out of its digits.");
Console.WriteLine("Instructions: Enter a number up to 10000, and see the results!");
drLabel:
Console.Write("Your Number: ");
string input = Console.ReadLine();
int inputNumber = 0;
try { inputNumber = int.Parse(input); }
catch (Exception ex) { Console.WriteLine("Error: {0}", ex.Message); goto drLabel; }
/*Placeholder code for the moment*/Console.WriteLine(inputNumber.ToString());
evaluate:
Console.Write("Do you want to exit? Yes/No: ");
if (Console.ReadLine().Equals("Yes"))
return 1;
else if (Console.ReadLine().Equals("No"))
{
goto drLabel;
}
else
{
return 1;
}
}
static void Main(string[] args)
{
Console.WriteLine("Welcome to the ACSL Competition Program. Choose a program to begin:");
Console.Write("\n\t");
Console.WriteLine("1\tDigit Re-arranger");
label:
Console.Write("\nProgram: ");
string input = Console.ReadLine();
int number = 0;
try { number = int.Parse(input); }
catch (Exception ex) { Console.WriteLine("Error: {0}", ex.Message); goto label; }
if (number == 1)
{
Console.WriteLine("\n");
if (DigitRearranger() == 1)
{
goto label;
}
else if (DigitRearranger() != 1)
{
DigitRearranger();
}
}
else if (!number.Equals(1))
{
Console.WriteLine("Not a valid program.");
goto label;
}
//----------------
Console.ReadLine();
}
}
}
The underlying problem is that you're calling readline twice. The first time it gets the entered value, i.e. Yes, the second time you call it there is no data to read so it returns "". If you need to reuse the same input store it in a variable, i.e.
string inputVal = Console.ReadLine();
I hate goto statements, maybe you could restructure your code in to a while loop, something like:
bool exit = false;
while(!exit)
{
Console.Write("Your Number: ");
//Your main code
Console.Write("Do you want to exit? Yes/No: ");
if(Console.ReadLine() != "No")
exit = true;
}
In fact, you could get rid of the exit variable, just do while(true) and return if the user enters anything other than no.
I have a few suggestions:
Write your code to be more modular to improve readability. The Main() method should only drive the outer UI loop, each module provides its own UI.
Never use goto statements.
Don't use Console.Readline() inside an if condition (when not "Yes", it was called twice).
Here is my refactored version of your code:
class Program {
static void DigitRearranger()
{
string response = "";
int num;
do
{
Console.Clear();
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("---------Welcome to the Digit Re-arranger!---------");
Console.WriteLine("I take a positive number up to 10000, and find the highest number that can be made out of its digits.");
Console.WriteLine("Instructions: Enter a number up to 10000, and see the results!");
Console.ResetColor();
Console.Write("Your Number: ");
if (!int.TryParse(Console.ReadLine(), out num))
{
Console.WriteLine("Not a number. Press any key to continue");
Console.ReadKey();
continue;
}
//todo: reaarrange the number & print results
/*Placeholder code for the moment*/
Console.WriteLine(num);
Console.Write("Do you want to exit? Yes/No: ");
response = Console.ReadLine();
} while (response.ToLower() != "yes");
}
//UI driver only in Main method:
static void Main(){
string response = "";
do
{
Console.Clear();
Console.WriteLine("Welcome to the ACSL Competition Program. Choose a program to begin:");
Console.WriteLine("\n\t1\tDigit Re-arranger");
Console.WriteLine("\tq\tQuit");
Console.Write("\nProgram: ");
response = Console.ReadLine();
switch(response)
{
case "1":
DigitRearranger();
break;
case "q":
break;
default:
Console.WriteLine("Not a valid program. Press any key to continue");
Console.ReadKey();
break;
}
} while (response.ToLower() != "q");
Console.ReadLine();
}}