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();
}}
Related
Need to get it to loop after the user presses "r" at this part, need it to do as it says in the Console.WriteLine and redo all the questions
if (numOfCorrect > 7)
Console.Clear();
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("You got " + numOfCorrect + "correct! Incredible job! Can you do it again though? ");
Console.WriteLine("If you want to retry the quiz press 'r', if you wish to exit the program press 'c'");
if (Console.ReadKey().Key != ConsoleKey.R)
Console.Clear();
using System;
namespace ConsoleApp1
{
class Program
{
static int iNum1;
static int iNum2;
static int numOfCorrect;
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Ten Question Multiplication Quiz");
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Instructions");
Console.WriteLine("This program will give you 10 questions on multiplication for you to answer, after answering the ten questions it will display how many you got right!");
Console.WriteLine("If you decide to retry the quiz it will have 10 completely different questions! So be prepared for a challenge.");
Console.ResetColor();
Console.WriteLine("Press Enter to Start");
Console.ReadKey();
Console.Clear();
Random rRandom = new Random();
for (int loop = 0; loop < 10; loop++)
{
int userAnswer;
int answer;
iNum1 = rRandom.Next(11);
iNum2 = rRandom.Next(11);
{
Console.Write("What is " + iNum1 + " times " + iNum2 + "? ");
answer = iNum1 * iNum2;
userAnswer = Convert.ToInt32(Console.ReadLine());
}
if (answer == userAnswer)
{
Console.WriteLine(userAnswer + " is correct ");
numOfCorrect++;
Console.Clear();
}
else
{
Console.WriteLine(userAnswer + " is incorrect ");
Console.Clear();
}
if (userAnswer > 100)
{
loop += (loop - 1);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("That number is too high, try again");
}
}
{
if (numOfCorrect > 7)
Console.Clear();
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("You got " + numOfCorrect + "correct! Incredible job! Can you do it again though? ");
Console.WriteLine("If you want to retry the quiz press 'r', if you wish to exit the program press 'c'");
if (Console.ReadKey().Key != ConsoleKey.R)
Console.Clear();
else if (Console.ReadKey().Key != ConsoleKey.C)
System.Environment.Exit(0);
}
}
}
}
You can either capsulate your whole code inside another loop like pawel stated in his comment. Or you could also create a recursive function call like:
static void Main(string[] args)
{
Quiz();
}
void Quiz(){
// Initialize stuff
// Display stuff
for(int loop = 0; loop < 10; loop++)
{
// Question User
// Evaluate Answers
// and so on
// Check user input for retry
if (Console.ReadKey().Key != ConsoleKey.R)
{
Console.Clear();
Quiz(); // <---- Calls the same method again
}
}
}
I'm trying to run a console application that will allow a user to pick which type of job they would like to run on their PC and their response will translate to which functions the program runs. The way it is written right now the program will lock up and not allow anything else when the user inputs any options other than 4 which will successfully close the program.
static void Main(string[] args)
{
int userInput = 0;
DisplayMenu();
do
{
if (userInput == 1)
{
QuickClean();
}
else if (userInput == 2)
{
DeepClean();
}
else if (userInput == 3)
{
SuperClean();
}
} while (userInput != 4);
}
static public int DisplayMenu()
{
Console.WriteLine("");
Console.WriteLine();
Console.WriteLine("1. Quick Clean");
Console.WriteLine("2. Deep Clean");
Console.WriteLine("3. Super Clean (admin needed)");
Console.WriteLine("4. exit");
var result = Console.ReadLine();
return Convert.ToInt32(result);
}
static void QuickClean()
{
Console.WriteLine("quickclean");
Console.ReadLine();
}
static void DeepClean()
{
Console.WriteLine("deepclean");
Console.ReadLine();
}
static void SuperClean()
{
Console.WriteLine("superclean");
Console.ReadLine();
}
The DisplayMenu method returns what your user chooses but you don't assign this return to your usermenu local variable.
As you have written it now, you ask for input just one time and then enter the loop without setting the local variable usermenu to the user choice so it is still zero when it reaches the while to test the exit condition and the loop enters the infinite condition.
You need to move the call to DisplayMenu inside the loop and assign the return value to usermenu, so your user can see again the menu and input a different choice and you can perform the required operations.
static void Main(string[] args)
{
int userInput = 0;
do
{
userInput = DisplayMenu();
if (userInput == 1)
{
QuickClean();
}
....
} while(userInput != 4)
}
I suggest also to change the code in DisplayMenu and avoid to use Convert.ToInt32 to parse the user input. If the user doesn't type a number the Convert.ToInt32 will crash your program. Instead use Int32.TryParse
static public int DisplayMenu()
{
Console.Clear();
while(true)
{
Console.WriteLine("");
Console.WriteLine();
Console.WriteLine("1. Quick Clean");
Console.WriteLine("2. Deep Clean");
Console.WriteLine("3. Super Clean (admin needed)");
Console.WriteLine("4. exit");
int result;
if(Int32.TryParse(Console.ReadLine(), out result))
return result;
else
Console.WriteLine("Please enter a number");
}
}
You are not storing the returned value anywhere. userInput is still 0 after DisplayMenu() is called, that's why you get into an infite loop at the do-while.
do{
int userInput = DisplayMenu();
[...]
} while (userInput != 4)
So I recently started my first coding course for C#. I am currently trying to write a short program that prints out Yay! as many times as I indicate. Now to prevent any format exceptions, I've tried to add a try and catch to it. But, for some reason this isn't working and I can't seem to figure out why. The code is below:
Console.Write("Enter the number of times to print \"Yay!\": ");
string entry = Console.ReadLine();
var number = int.Parse (entry);
bool print = true;
while(print)
{
try
{
if(number <= 0)
{
print = false;
}
else
{
Console.WriteLine("Yay!");
number -= 1;
}
}
catch(FormatException)
{
Console.WriteLine("You must enter a whole number.");
}
}
Now to my knowledge, I have everything I need to make this work. Can anyone see where I went wrong with this?
Thanks a lot for reading!
It's
var number = int.Parse (entry);
that should throw the exception, and since it's beyond try {} scope, the
exception has not been caught. Move the fragment into the scope:
Console.Write("Enter the number of times to print \"Yay!\": ");
string entry = Console.ReadLine();
bool print = true;
try {
// int.Parse is within the try {} scope now
var number = int.Parse (entry);
while(print) {
...
}
}
catch(FormatException) {
Console.WriteLine("You must enter a whole number.");
}
Or convert int.Parse into int.TryParse and drop try {...} catch {...} at all (a better solution)
Console.Write("Enter the number of times to print \"Yay!\": ");
int number;
if (!int.TryParse(Console.ReadLine(), out number)) {
Console.WriteLine("You must enter a whole number.");
return;
}
bool print = true;
// There's no need in try {} catch {} now
while(print) {
...
}
You need to place your int.Parse inside your try-catch block.
Here's a revised version of your code.
static void Main(string[] args)
{
bool print = true;
while (print)
{
Console.Write("Enter the number of times to print \"Yay!\": ");
string entry = Console.ReadLine();
try
{
var number = int.Parse(entry);
for (int i = 0; i < number; i++)
{
Console.WriteLine("Yay!");
}
}
catch (FormatException)
{
Console.WriteLine("You must enter a whole number.");
}
}
}
My input gets checked by "TryParse". And if it is false I want to let the user retype it correctly. But when I click any key after the check it deletes everything above cause of "Console.Clear();". - I want to delete only the input part and nothing above it.
namespace Practice
{
class Program
{
static void Main(string[] args) // Main Method
{
byte age1, age2;
string input;
do
{
Console.Write("Enter Age 1: "); input = Console.ReadLine();
if (!byte.TryParse(input, out age1)) Error();
} while (!byte.TryParse(input, out age1));
do
{
Console.Write("Enter Age 2: "); input = Console.ReadLine();
if (!byte.TryParse(input, out age1)) Error();
} while (!byte.TryParse(input, out age2));
}
static void Error()
{
Console.ForegroundColor = ConsoleColor.Red;
Console.Write("Invalid Input...");
Console.ResetColor();
Console.ReadKey();
Console.Clear();
}
}
}
I'm not sure that you can erase a single line from the Console buffer. But you can simulate it if you change the second while in your code:
while (!byte.TryParse(input, out age2) && counter)
{
Error();
Console.WriteLine("Enter Age 1: {0}",age1);
Console.Write("Enter Age 2: ");
input = Console.ReadLine();
} // Check And Error Output
with this line Console.WriteLine("Enter Age 1: {0}",age1); after the Console.Clear(); executes, It seems like you have erased the wrong input line.
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.