Noob trying to combine while and if statements - c#

I'm trying to learn C# and wanted to try making a simple program from scratch that asks the user to enter a number between 1-3, every number yields a lottery win and writing "exit" is supposed to exit the program. When one number is answered the user is supposed to be prompted to answer again until choosing to exit. No matter what I do when trying to combine a while loop and if statements I get errors or just infinite loops that won't stop. Probably some simple syntax misunderstanding.. Any help would be greatly appreciated.
This is my code so far:
static void Main(string[] args)
{
string userInput = "";
Console.Write("Pick a number between 1-3, type 'exit' to stop the program: ");
userInput = Console.ReadLine();
while (userInput != "exit")
if (userInput == "1")
{
Console.WriteLine("You won a car");
}
else if (userInput == "2")
{
Console.WriteLine("You won a boat");
}
else if (userInput == "3")
{
Console.WriteLine("Sorry, no luck this time. Try again");
}
else if (userInput == "exit")
{
Console.WriteLine("Exiting...");
break
}
else
{
Console.WriteLine("The number has to be between 1-3, try again.");
}
Console.ReadLine()
}
}
}
}

This should work
static void Main(string[] args)
{
string userInput = "";
Console.Write("Pick a number between 1-3, type 'exit' to stop the program: ");
userInput = Console.ReadLine();
while (userInput != "exit")
{
if (userInput == "1")
{
Console.WriteLine("You won a car");
}
else if (userInput == "2")
{
Console.WriteLine("You won a boat");
}
else if (userInput == "3")
{
Console.WriteLine("Sorry, no luck this time. Try again");
}
else if (userInput == "exit")
{
Console.WriteLine("Exiting...");
break
}
else
{
Console.WriteLine("The number has to be between 1-3, try again.");
}
userInput = Console.ReadLine()
}
}
}

The value of userInput is never updated in the loop, which means that each time the loop runs, the value stays the same.
A solution is to move the prompt and the reading into the start of the loop.

To add to Zayenz's answer, this is the key to all infinite loops; the circumstance evaluated that decides whether or not to begin the loop is always true. If you ever have this problem again, you just need to look at the code to make sure that whatever should break you out of the loop actually changes whatever criteria it needs to in order to make the condition false;

Related

How do I stop the Console.ReadLine() command triggering multiple times in my loop?

I'm a complete newbie when it comes to C#, and I'm sure this has a very simple answer:
I've written a super simple piece of code to enable a user to pop in a number and receive the square of that number back out. I've also enabled the user to decide whether they want to play or not, with Yes, No, or 'else' triggering different outcomes.
The 'Yes' input works just fine, with the program working as expected. However, the 'No' or 'else' response seems to require the user to enter a response a second time before triggering the outcome properly.
I can't see why it would be looking for a response twice in a row, so if you can offer any help I'd really appreciate it.
Here's the code I'm using:
namespace Playground
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("If you enter a number, I'll report back the number squared. Would you like to play? Enter Yes or No");
int x = 100;
while (x == 100)
{
if (Console.ReadLine() == "Yes")
{
Console.WriteLine("Great! Enter a number");
int initial = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(initial * initial);
Console.WriteLine("Would you like to try again?");
}
else if(Console.ReadLine() == "No")
{
Console.WriteLine("Ok, goodbye! Press any key to Exit");
Console.ReadLine();
Environment.Exit(0);
}
else
{
Console.WriteLine("Sorry, I didn't understand that. Please enter Yes or No");
}
}
}
}
}
When running into the first if the condition run the function Console.ReadLine() so you have to write the answer. This is going to happen also in the else if (Console.ReadLine() == "No").
What you have to do is save the user input only once and decide what to do from that answer.
The code is:
int x = 100;
while (x == 100)
{
string answer = Console.ReadLine();
if (answer == "Yes")
{
Console.WriteLine("Great! Enter a number");
int initial = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(initial * initial);
Console.WriteLine("Would you like to try again?");
}
else if(answer == "No")
{
Console.WriteLine("Ok, goodbye! Press any key to Exit");
Console.ReadLine();
Environment.Exit(0);
}
else
{
Console.WriteLine("Sorry, I didn't understand that. Please enter Yes or No");
}
}
You can also use the switch statement:
int x = 100;
while (x == 100){
string answer = Console.ReadLine();
switch (answer){
case "Yes":
Console.WriteLine("Great! Enter a number");
int initial = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(initial * initial);
Console.WriteLine("Would you like to try again?");
break;
case "No":
Console.WriteLine("Ok, goodbye! Press any key to Exit");
Console.ReadLine();
Environment.Exit(0);
break;
default:
Console.WriteLine("Sorry, I didn't understand that. Please enter Yes or No");
break;
}
}

I have a sentinel while loop with if statments inside them, I want to break out of the if statements without breaking out of the while loop C#

I am supposed to use only a sentinel while loop for an assignment. The user is meant to enter a department code, and for each department code its supposed to intake a mark and then at the end when the while loop is exited it calculates the average. My question is can I break out an an If statement inside a while loop without breaking out of the while loop itself? And once Q is pressed exit out of the program?
Console.WriteLine("Enter a department code: ‘C’ or ‘c’ for Computer Science,‘M’ or " +
"‘m’ for Math, ‘B’ or ‘b’ for Business Admin, or enter ‘Q’ or ‘q’ to quit => C");
char deptCode = Console.ReadKey().KeyChar;
while (char.ToUpper(deptCode) != 'Q')
{
if (char.ToUpper(deptCode) == 'C')
{
Console.WriteLine("\nEnter the mark (>= 0 or <= 100)");
computerScienceMark = Convert.ToInt32(Console.ReadLine());
break;
}
else if (char.ToUpper(deptCode) == 'B')
{
Console.WriteLine("\nEnter the mark (>= 0 or <= 100)");
businessMark = Convert.ToInt32(Console.ReadLine());
break;
}
else if (char.ToUpper(deptCode) == 'M')
{
Console.WriteLine("\nEnter the mark (>= 0 or <= 100)");
mathMark = Convert.ToInt32(Console.ReadLine());
break;
}
if (char.ToUpper(deptCode) == 'Q')
{
Console.WriteLine("you entered Q to quit");
Environment.Exit(0);
}
else
{
Console.WriteLine("\nYou entered a wrong input please try again");
break;
}
}
You could put the whole request for a department code inside a while.
That way the users will be asked for a new code until they enter 'Q', like this
while (true)
{
Console.WriteLine("Enter a department code: ‘C’ or ‘c’ for Computer Science,‘M’ or ‘m’ for Math, ‘B’ or ‘b’ for Business Admin, or enter ‘Q’ or ‘q’ to quit => C");
char deptCode = Console.ReadLine()[0];
if (char.ToUpper(deptCode) == 'Q')
break;
if (char.ToUpper(deptCode) == 'C')
{
Console.WriteLine("\nEnter the mark (>= 0 or <= 100)");
computerScienceMark = Convert.ToInt32(Console.ReadLine());
}
else if (char.ToUpper(deptCode) == 'B')
{
Console.WriteLine("\nEnter the mark (>= 0 or <= 100)");
businessMark = Convert.ToInt32(Console.ReadLine());
}
else if (char.ToUpper(deptCode) == 'M')
{
Console.WriteLine("\nEnter the mark (>= 0 or <= 100)");
mathMark = Convert.ToInt32(Console.ReadLine());
}
else
{
Console.WriteLine("\nYou entered a wrong input please try again");
}
}
https://www.jdoodle.com/iembed/v0/8Wi
You want two loops. One outer one to get the department codes, and one inner one to get the mark. Something along the lines of:
static void Main(string[] args)
{
while (true) // outer loop
{
string department;
Console.WriteLine("Enter department code:");
department = Console.ReadLine().ToUpper();
if (department == "Q")
{
break; // end the outer loop
}
else if (department == "C"
|| department == "B"
|| department == "M")
{
while (true) // inner loop
{
int mark;
Console.WriteLine("Enter mark:");
if (int.TryParse(Console.ReadLine(), out mark)
&& mark >= 0
&& mark <= 100))
{
break; // end the inner loop;
}
else
{
Console.WriteLine("Invalid mark. Try again.");
}
}
}
else
{
Console.WriteLine("Invalid department code. Try again.");
}
}
}
To end the outer loop check if department was "Q" and break. For the inner one break when the mark was correctly entered. You can use int.TryParse() to check if the string entered really represents an integer for that check.
bool check = false;
while (check == false)
{
Console.WriteLine("Enter a department code: ‘C’ or ‘c’ for Computer Science,‘M’ or ‘m’ " +
"for Math, ‘B’ or ‘b’ for Business Admin, or enter ‘Q’ or ‘q’ to quit => C");
char deptCode = Console.ReadLine()[0];
if (char.ToUpper(deptCode) == 'Q')
{
check = true;
}
Console.WriteLine("\nEnter the mark (>= 0 or <= 100)");
switch (char.ToUpper(deptCode))
{
case 'C':
computerScienceMark = Convert.ToInt32(Console.ReadLine());
check = true;
break;
case 'B':
businessMark = Convert.ToInt32(Console.ReadLine());
check = true;
break;
case 'M':
mathMark = Convert.ToInt32(Console.ReadLine());
check = true;
break;
default:
Console.WriteLine("\nYou entered a wrong input please try again");
break;
}
}
To a consenus it is bad programing form to use break, continue, goto and such. Don't let me tell you how to program, use whatever you like and be my guest. However, if you're a beginner and wanting to learn transferable skills it's genuinely regarded as sloppy to use break - this is because it can leave behind "un tided up" (for lack of a better expression) memory. I only mean when using break when in an iteration.
My soultion is very similar to Jack Lilhammers, although I prefer the switch statement here, it's a little neater. Furthermore, using an idividual variable for the while condition is a nice idea because it's a good habbit to get acustomed with when doing larger more complex while loops where u might find yourself stepping throught the code and having that variable allows you to nicely observe it's state throughout.

Nested If statements for checking eligbility

so I am pretty new to C# and after learning some fundamentals I tried making a simple program to check for someone's eligibility using if statements.
The program asks for 3 things: Age, Height, and CollegeDegree
You have to be 18 to go to the next question and you have to be taller than 160cm to go to the CollegeDegree question.
Now the program works fine, however looking at it, I come to realize that there are a lot of nested if statements and the code is just messy and unreadable.
What would I need to do to make it cleaner? I tried just doing it as follows
if
else
if
else
However, that causes the issue that if the first condition is not met, so the age is < 18 it just runs the next if statement instead of making the user be ineligible.
Current Code:
static void Main(string[] args)
{
int ageInput;
int heightInput;
bool hasCollegeDegree;
Console.WriteLine("How old are you?");
ageInput = Convert.ToInt32(Console.ReadLine());
if (ageInput >= 18)
{
Console.WriteLine("You are older than 18");
Console.WriteLine("How tall are you?");
heightInput = Convert.ToInt32(Console.ReadLine());
if (heightInput >= 160)
{
Console.WriteLine("You are taller than 160cm");
Console.WriteLine("Do you have a college degree?");
hasCollegeDegree = Convert.ToBoolean(Console.ReadLine());
if (hasCollegeDegree == true)
{
Console.WriteLine("You have a college degree");
Console.WriteLine("You are eligible");
}
else
{
Console.WriteLine("No College Degree");
Console.WriteLine("You are ineligible");
}
}
else
{
Console.WriteLine("You are too short");
}
}
else
{
Console.WriteLine("You are too young");
}
}
You can exit out of the code using a reverse condition. Example:
Console.WriteLine("How old are you?");
int ageInput = Convert.ToInt32(Console.ReadLine());
if (ageInput < 18)
{
Console.WriteLine("You are too young");
return;
}
Console.WriteLine("You are older than 18");
Console.WriteLine("How tall are you?");
int heightInput = Convert.ToInt32(Console.ReadLine());
if (heightInput < 160)
{
Console.WriteLine("You are too short");
return;
}
Console.WriteLine("You are taller than 160cm");
Console.WriteLine("Do you have a college degree?");
bool hasCollegeDegree = Convert.ToBoolean(Console.ReadLine());
if (!hasCollegeDegree)
{
Console.WriteLine("No College Degree");
Console.WriteLine("You are ineligible");
return;
}
Console.WriteLine("You have a college degree");
Console.WriteLine("You are eligible");
I suggest extracting methods to read integer:
private static int ReadInteger(string question) {
while (true) {
if (!string.IsNullOrWhiteSpace(question))
Console.WriteLine(question);
if (int.TryParse(Console.ReadLine(), out int result))
return result;
Console.WriteLine("Sorry, not a valid integer; please, try again.");
}
}
and boolean:
private static HashSet<string> s_Yes =
new HashSet<string>(StringComparer.OrdinalIgnoreCase) {
"Y", "Yes", "T", "True", "OK"
};
private static HashSet<string> s_No =
new HashSet<string>(StringComparer.OrdinalIgnoreCase) {
"N", "No", "F", "False"
};
private static bool ReadBoolean(string question) {
while (true) {
if (!string.IsNullOrWhiteSpace(question))
Console.WriteLine(question);
string input = Console.ReadLine().Trim();
if (s_Yes.Contains(input))
return true;
if (s_No.Contains(input))
return false;
Console.WriteLine("Sorry, not a valid value; please, try again.");
}
}
then you can put
if (ReadInteger("How old are you?") < 18) {
Console.WriteLine("You are too young");
return;
}
Console.WriteLine("You are older than 18");
if (ReadInteger("How tall are you?") < 160) {
Console.WriteLine("You are too short");
return;
}
Console.WriteLine("You are taller than 160cm");
if (!ReadBoolean("Do you have a college degree (Y/N)?")) {
Console.WriteLine("No College Degree");
Console.WriteLine("You are ineligible");
return;
}
Console.WriteLine("You have a college degree");
Console.WriteLine("You are eligible");
A disadvantage with the answers so far using return is that the method is exited and therefore you can't have any code below that point in the same method.
A different approach is to use a COMPOUND boolean statement and combine all the conditions into one boolean expression:
if (ageInput >= 18 && heightInput >= 160 && hasCollegeDegree)
{
Console.WriteLine("Congratulations! You meet the criteria.");
}
else
{
Console.WriteLine("You do not meet the criteria.");
}
This style of check might be useful if you have many different combinations that you need to check for. So the user enters all the information up front and then you can have a whole series of different compound checks to see which combinations they satisfy. Maybe you're checking to see which grants from a list that the user qualifies for.
See Boolean logical operators for more information on &&, ||, and !.

Return to a specific block of code in my application

I am fairly new to C# and currently building a simple ATM app. I am attempting to write code to return the user to the main menu according to his/her entry of the letter M. The break, continue, goto or return keywords do not seem to work in my scenario; perhaps I used them incorrectly. The statement directly below is where I would like to jump to.
Console.WriteLine("Select an option? \n VIEW BALANCE (B1) checking, (B2) saving \n DEPOSIT (C1) checking, (C2) saving \n WITHDRAW (W1) checking, (W2) saving");
I would like to jump from the line JUMP (below) within the else if statement nested within the switch statement into the section of code above. How can I achieve this? any help is appreciated...thanks!
switch (response)
{
case "C1":
Console.WriteLine("How much would you like to deposit to your checking account?");
string depositEntry = Console.ReadLine();
double checkingBalance = Convert.ToInt32(depositEntry) + currentCheckingBalance;
currentCheckingBalance += checkingBalance;
Console.WriteLine("Your current checking balance is " + checkingBalance + "\n (X) Exit, (M) Main Menu" );
string selection = Console.ReadLine().ToUpper();
if (selection == "X")
{
return;
}
else if (selection == "M")
{
***JUMP***
}
else
{
Console.WriteLine("Your entry was invalid");
}
break;
case "C2":
break;
case "W1":
Using a jump statement usually indicates the flow of logic is jumbled. I try to avoid any kind of jumps if necessary. The code below prints out a main menu and if the user types “x” the program will quit. If the user selects one of the other options, a message is simply printed out indicating what the user selected. After the user presses any key, the console clears and the main menu is re-displayed.
In the main menu, if the user does not type one of the selections, then the selection is ignored, the console is cleared, and the menu is reprinted. No error is displayed indicating invalid selections.
This does not require the user to type “m” to go back to the main menu. After a selection is made for Deposit/withdraw/… after the method is finished the code will automatically return to the main menu.
I am guessing this may be what you are looking for. Hope this helps.
static void Main(string[] args) {
string userInput = "";
while ((userInput = GetMainSelection()) != "x") {
switch (userInput) {
case "c1":
Console.WriteLine("C1 Deposit Checking method");
break;
case "c2":
Console.WriteLine("C2 Deposit Savings method");
break;
case "b1":
Console.WriteLine("B1 View Balance Checking method");
break;
case "b2":
Console.WriteLine("B2 View Balance Savings method");
break;
case "w1":
Console.WriteLine("W1 Withdraw Checking method");
break;
case "w2":
Console.WriteLine("W2 withdraw Savings method");
break;
}
Console.WriteLine("Press Any Key to continue"); // <-- show what method was just used
Console.ReadKey();
Console.Clear();
}
Console.Write("Press any key to exit the program");
Console.ReadKey();
}
private static string GetMainSelection() {
string userInput = "";
while (true) {
Console.WriteLine("Select an option? \n VIEW BALANCE (B1) checking, (B2) saving \n DEPOSIT (C1) checking, (C2) saving \n WITHDRAW (W1) checking, (W2) saving. (X) to EXit");
userInput = Console.ReadLine().ToLower();
if (userInput == "b1" || userInput == "b2" || userInput == "c1" || userInput == "c2" || userInput == "w1" || userInput == "w2" || userInput == "x") {
return userInput;
}
else {
Console.Clear();
}
}
}
Put the JUMP code in a function and return.
public void MainMenu() {
// Show the main menu
}
public void Response(string response) {
switch (response)
{
case "C1":
Console.WriteLine("How much would you like to deposit to your checking account?");
string depositEntry = Console.ReadLine();
double checkingBalance = Convert.ToInt32(depositEntry) + currentCheckingBalance;
currentCheckingBalance += checkingBalance;
Console.WriteLine("Your current checking balance is " + checkingBalance + "\n (X) Exit, (M) Main Menu" );
string selection = Console.ReadLine().ToUpper();
if (selection == "X")
{
return;
}
else if (selection == "M")
{
***JUMP***
MainMenu();
return;
}
else
{
Console.WriteLine("Your entry was invalid");
}
break;
case "C2":
break;
case "W1":
}
}
Similar to the already given answer, I suggest breaking this out. Here's an example:
The Main method:
static void Main(string[] args) {
string input = null;
do {
input = Console.ReadLine();
ParseInput(input);
} while (input != "X");
}
ParseInput:
static void ParseInput(string input) {
switch (input) {
case "X": //from Main(), this will close the app
return;
case "M":
MainMenu();
break;
case "C1":
ShowAccount("C1"); //move your deposit/withdraw logic into a method and call with the selected account
return;
//other accounts
default:
break; //error message?
}
}
and MainMenu:
static void MainMenu() {
Console.WriteLine("Select an option? \n VIEW BALANCE (B1) checking, (B2) saving \n DEPOSIT (C1) checking, (C2) saving \n WITHDRAW (W1) checking, (W2) saving");
}
This should let you read the input in a loop and the ParseInput function can handle your individual cases. You may also want to call MainMenu() at the start, so it shows from the beginning.
It works like this:
Get input from the user
Pass the input to ParseInput() which decides where to go next.
Any functions hit in ParseInput() will execute, writing to the console or asking for further input
Once that function returns, while (input != "X") evaluates. If input != "X", goto 1, else exit.
I suggest you use goto C# reference.
static void Main()
{
int x = 200, y = 4;
int count = 0;
string[,] array = new string[x, y];
// Initialize the array:
for (int i = 0; i < x; i++)
for (int j = 0; j < y; j++)
array[i, j] = (++count).ToString();
// Read input:
Console.Write("Enter the number to search for: ");
// Input a string:
string myNumber = Console.ReadLine();
// Search:
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
if (array[i, j].Equals(myNumber))
{
goto Found;
}
}
}
Console.WriteLine("The number {0} was not found.", myNumber);
goto Finish;
Found:
Console.WriteLine("The number {0} is found.", myNumber);
Finish:
Console.WriteLine("End of search.");
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
Output for the Input 44 would be:
Enter the number to search for: 44
The number 44 is found.
End of search.
See here for the MSDN reference.

C# integer validation

I have searched stackoverflow and haven't found anything that answers my question. Unfortunately it is not an easy question to word as a search query.
I'm using c# and I have a menu that asks the user to pick an option from 1 - 4. I am validation that the value picked is an integer, but my code breaks whenever I enter a letter or symbol. How do I add the validation for this to? My code currently is as follows.
static void Main(string[] args)
{
DirectoryInfo folderInfo = new DirectoryInfo("C:\\Windows");
FileInfo[] files = folderInfo.GetFiles();
int mainMenuChoice=0;
while ( mainMenuChoice != 1 || mainMenuChoice!= 2 || mainMenuChoice!= 3 || mainMenuChoice!= 4)
{
Console.WriteLine("What would you like to do?");
Console.WriteLine("1. Full File Listing.");
Console.WriteLine("2. Filtered File Listing.");
Console.WriteLine("3. FolderStatistics.");
Console.WriteLine("4. Quit.");
mainMenuChoice = int.Parse(Console.ReadLine());
if (mainMenuChoice == 1)
{
Option1();
}
if (mainMenuChoice == 2)
{
Option2();
}
if (mainMenuChoice == 3)
{
Option3();
}
if (mainMenuChoice == 4)
{
}
else
{
Console.WriteLine("you didnt enter a valid input! try again.");
}
}
Change the reading from the command line to
if(Int32.TryParse(Console.ReadLine(), out mainMenuChoice))
{
if (mainMenuChoice == 1)
Option1();
else if (mainMenuChoice == 2)
Option2();
else if (mainMenuChoice == 3)
Option3();
else if (mainMenuChoice == 4)
Option4();
else
Console.WriteLine("you didnt enter a valid input! try again.");
}
else
{
Console.WriteLine("you didnt enter a valid input! try again.");
}
and repeat the warning message for your user in the else part of the TryParse if.
Int32.TryParse return false when the characters on the command line cannot be converted to an integer and assigned to the out parameter mainMenuChoice.
Use int.TryParse instead:
if (!int.TryParse(Console.ReadLine(), out mainMenuChoice))
{
Console.WriteLine("That's not a number!");
}
...
But in fact, you're never actually using the input as a number, so there's no real need to parse it. You could just leave it as a string:
bool retry;
do
{
retry = false;
Console.WriteLine("What would you like to do?");
Console.WriteLine("1. Full File Listing.");
Console.WriteLine("2. Filtered File Listing.");
Console.WriteLine("3. FolderStatistics.");
Console.WriteLine("4. Quit.");
string mainMenuChoice = Console.ReadLine();
switch(mainMenuChoice)
{
case "1":
Option1();
break;
case "2":
Option2();
break;
case "3":
Option3();
break;
case "4":
break;
default:
Console.WriteLine("You didn't enter a valid input! Try again.");
retry = true;
break;
}
} while(retry);
Also, although this is pretty clear and easy to ready, you don't actually need the retry variable. Although it's a lot less obvious how this works (and I would probably avoid it for that reason), you can structure your loop like this:
do
{
Console.WriteLine("What would you like to do?");
Console.WriteLine("1. Full File Listing.");
Console.WriteLine("2. Filtered File Listing.");
Console.WriteLine("3. FolderStatistics.");
Console.WriteLine("4. Quit.");
string mainMenuChoice = Console.ReadLine();
switch(mainMenuChoice)
{
// same as above
default:
Console.WriteLine("You didn't enter a valid input! Try again.");
continue; // goes back to beginning of the loop
}
break; // exits the loop
} while(true);
while(true)
{
int menuChoice;
string userInput = Console.Readline();
if(Int32.TryParse(userInput, out menuChoice))
{
if(menuChoice >= 1 && menuChoice <= 4)
RunCommand(menuChoice);
else
Console.WriteLine("Enter a number between 1-4");
}
else
Console.WriteLine("A number between 1-4 is required!");
}
Use the TryParse method on Int (details here).
For example:
int menuChoice;
if(!int.TryParse(Console.Readline(),out menuChoice){
Console.WriteLine("The menu choice you made was invalid.");
} else {
//do the rest of your code here
}

Categories