get user confirmation inside a loop - c#

After searching for a Solution with a do-while Loop, I'm now stuck and this point, and just cant figure out what I am doing wrong.
static void StartUp()
{
bool confirmChoice = false;
Console.WriteLine("Hey, Enter your Character Name!");
string name = Console.ReadLine();
do
{
Console.WriteLine("Is " + name + " correct? (y) or would you like to change it (n)?");
string input = Console.ReadLine();
if (input == "n")
{
Console.WriteLine("Allright, enter your new Name then!");
name = Console.ReadLine();
break;
}
else
{
confirmChoice = true;
}
}while(confirmChoice);
}

Your code is almost right - all you need to do is inverting the condition of your do/while loop to while (!confirmChoice)
However, you could do better than that: make a forever loop, and use break to exit it:
while (true) {
Console.WriteLine("Please, Enter your Character Name!");
string name = Console.ReadLine();
Console.WriteLine("Is " + name + " correct? (y) or would you like to change it (n)?");
string input = Console.ReadLine();
if (input == "y") {
break;
}
}
This is a common solution for situations when the decision to exit is made in the middle of the loop body.

you should change the termination condition for your loop
it should be while(!confirmChoice);
and you should change the break; line to continue;

Your Condition is wrong it should be while(confirmChoice==false) and don't use break;
static void StartUp()
{
bool confirmChoice = false;
Console.WriteLine("Hey, Enter your Character Name!");
string name = Console.ReadLine();
do
{
Console.WriteLine("Is " + name + " correct? (y) or would you like to change it (n)?");
string input = Console.ReadLine();
if (input == "n")
{
Console.WriteLine("Allright, enter your new Name then!");
name = Console.ReadLine();
}
else
{
confirmChoice = true;
}
}while(confirmChoice==false);
}

Related

c# do while loop exit even when the return is false

I have this C# program that, and this loop doesn't want to exit, it just becomes a blank row until the user answers yes? Not sure why or how this is happening.
https://dotnetfiddle.net/A6vJtd
using System;
namespace Assignment2
{
class FunFeatures
{
private string name = "";
private string email = "";
static void Main(string[] args)
{
Console.Title = "Strings, selection and interation in C#";
FunFeatures funObj = new FunFeatures();
funObj.Start();
ContinueToNextPart(); //call the method below
}
private static void ContinueToNextPart()
{
Console.WriteLine("\nPress enter to continue to the next part");
Console.ReadLine();
Console.Clear();
}
public void Start()
{
Introduce();
bool done = false;
do
{
//Call method to read a number 1 to 7 and display
//name of the day (1 = Monday, 7 = Sunday with a comment
PredictTheDay();
//Calculate the length of a given text
CalculateStrengthLength();
//Run again or exit
done = RunAgain();
} while (!done);
Console.WriteLine("Welcome back, " + name);
}
public void CalculateStrengthLength()
{
Console.WriteLine("\nLength of text: Write a text with a number of characters and press Enter");
Console.WriteLine("It will then calculate the number of chars included in the text");
Console.WriteLine("Give me a text of any length, or press Enter to exit!");
string str = Console.ReadLine();
int strLength = str.Length;
Console.WriteLine("\n"+ str.ToUpper());
Console.WriteLine("Number of chars = " + strLength);
}
private void Introduce()
{
Console.WriteLine("\nLet me know about yourself!");
ReadName();
Console.Write("Give me your email please: ");
email = Console.ReadLine();
Console.WriteLine("\nHere is your full name and your email.");
//split first name and last name
var names = name.Split(" ");
string fName = names[0];
string lName = names[1];
Console.WriteLine(lName + ", " + fName + " " + email);
}
public void PredictTheDay()
{
Console.WriteLine(); // blank row
Console.WriteLine("\nI am a fortune teller.");
Console.Write("Select a number between 1 and 7: ");
string str = Console.ReadLine();
int day = int.Parse(str);
switch (day)
{
case 1:
// Monday
Console.WriteLine("Monday: Keep calm my friend! You can fall apart!");
break;
case 2:
//Tuesday
Console.WriteLine("Tuesday and Wednesday break your heart!");
break;
case 3:
//Wednesday
Console.WriteLine("Tuesday and Wednesday break your heart!");
break;
case 4:
//Thursday
Console.WriteLine("Thursday, OMG, still one day to Friday!");
break;
case 5:
//Friday
Console.WriteLine("It's Friday! You are in love!");
break;
case 6:
//Saturday
Console.WriteLine("Saturday, do nothing and do plenty of it!");
break;
case 7:
//Sunday
Console.WriteLine("And Sunday always comes too soon!");
break;
default: // if user gives a number out of range
Console.WriteLine("Not in a good mode? This is not a valid date!");
break;
}
}
public void ReadName()
{
Console.WriteLine("Your first name please: ");
string firstname = Console.ReadLine();
Console.Write("Your last name please: ");
string lastname = Console.ReadLine().ToUpper();
name = firstname + " " + lastname;
Console.WriteLine("Nice to meet you " + firstname + "!");
}
//Ask user to whether to continue,
//return true if the user answers Y, y or any word beginning
//with these, or N, n or any word beginning with these.
//Otherwise, return false.
private bool RunAgain()
{
bool done = false; //true = y, false = n
Console.WriteLine(); //blankline
Console.Write("Run again? (y/n) ");
do
{
string str = Console.ReadLine();
//change str to uppercase letters to make comparison
//easier
str = str.ToUpper();
if (str[0] == 'Y') //str[0]is the first letter in the string
{
// continue wit
done = true;
}
else if (str[0] == 'N')
{
// do not continue with calculation
done = false;
}
} while (!done); //if (!done) is same as: if (done == false)
return done;
}
}
}
You need to distinguish 2 different things here:
The user wants to continue (which you have)
The user made valid input (which you don't have)
You are trying to achieve everything with a single boolean, which will not work.
There are several possibilities to make this work. At your level of understanding, I'd say let's introduce a second boolean:
private bool RunAgain()
{
Console.WriteLine();
Console.Write("Run again? (y/n) ");
bool done = false; //true = y, false = n
bool validinput = false; // no input is invalid input
do
{
string str = Console.ReadLine();
str = str.ToUpper();
if (str[0] == 'Y')
{
done = true;
validinput = true;
}
else if (str[0] == 'N')
{
done = false;
validinput = true;
}
} while (!validinput);
return done;
}
Note that you have inverse logic here: the method is called RunAgain(), and the variable name is called done, where my understanding of done is that I don't want to continue.
Let's fix that and make shorter code like
private bool RunAgain()
{
Console.WriteLine();
Console.Write("Run again? (y/n) ");
while(true) // yes, it's endless ...
{
string str = Console.ReadLine();
str = str.ToUpper();
if (str[0] == 'Y')
{
return // ... except if you jump out
false; // False = not run again
}
else if (str[0] == 'N')
{
return // ... except if you jump out
true; // True = run again
}
}
}
This loop here:
do
{
string str = Console.ReadLine();
//change str to uppercase letters to make comparison
//easier
str = str.ToUpper();
if (str[0] == 'Y') //str[0]is the first letter in the string
{
// continue wit
done = true;
}
else if (str[0] == 'N')
{
// do not continue with calculation
done = false;
}
} while (!done); //if (!done) is same as: if (done == false)
doesn't have a leaving mechanism when you input no. You are checking if they entered yes or no and if they entered no you are just looping over and over again, since while(!false) means while(true) which means once they enter no you are commanding to loop again. You can do something like:
do
{
string str = Console.ReadLine();
//change str to uppercase letters to make comparison
//easier
str = str.ToUpper();
if (str[0] == 'Y') //str[0]is the first letter in the string
{
// continue wit
done = true;
}
else if (str[0] == 'N')
{
// do not continue with calculation
done = false;
break;
}
} while (!done); //if (!done) is same as: if (done == false)
return done;
This part is also wrong
do
{
//Call method to read a number 1 to 7 and display
//name of the day (1 = Monday, 7 = Sunday with a comment
PredictTheDay();
//Calculate the length of a given text
CalculateStrengthLength();
//Run again or exit
done = RunAgain();
} while (!done);
You are receiving a false from RunAgain() when the user answers no which means you should stop the loop but since you again have while(!done) you are resolving !false to true. It should be
do
{
//Call method to read a number 1 to 7 and display
//name of the day (1 = Monday, 7 = Sunday with a comment
PredictTheDay();
//Calculate the length of a given text
CalculateStrengthLength();
//Run again or exit
done = RunAgain();
} while (done);

I dont press enter but ReadLine() says I did (accidently made it that you cant answer the old one so repost)

Fixed, but now it automatically presses enter when it gets to the Main(); thing and I can't actually input anything in time. Anyone know what's wrong?
using System;
using System.Linq;
namespace Bruh
{
class Program
{
static void Main()
{
int pog = 0;
int pog2 = 0;
Random r = new Random();
Console.WriteLine("Input a whole number");
string poggers = Console.ReadLine();
if (int.TryParse(poggers, out pog))
{
pog = int.Parse(poggers);
}
else
{
Console.WriteLine("ERROR: Not a number. Please input a number and not letters.");
Console.Read();
System.Environment.Exit(1);
}
Console.WriteLine("Input a number higher than the previous");
string poggers2 = Console.ReadLine();
if (int.TryParse(poggers2, out pog2))
{
pog2 = int.Parse(poggers2);
}
else
{
Console.WriteLine("ERROR: Not a number. Please input a number and not letters.");
Console.Read();
System.Environment.Exit(1);
}
int genRand = r.Next(pog, pog2);
Console.WriteLine("This number was randomly generated between " + pog + " and " + pog2 + " and we got: " + genRand);
Console.Read();
Console.WriteLine("Would you like to try again? Y/N");
ConsoleKeyInfo answer = Console.ReadKey();
if (answer.KeyChar == 'y' || answer.KeyChar == 'Y')
{
Console.WriteLine("\n");
Main();
}
else if (answer.KeyChar == 'n' || answer.KeyChar == 'N')
{
System.Environment.Exit(1);
}
else
{
Console.WriteLine("ERROR: Y/N not any other character");
Console.Read();
System.Environment.Exit(1);
}
}
}
}
I've reworked your code into something that is more C#-like :-) - find this below.
Highlights:
You use int.TryParse() correctly, but do the conversion again
inside the true code block, using int.Parse().
No need to call System.Environment.Exit(1); to terminate the program, just let it end.
The call main() is actually a recursive call - where a method (function) calls it self. Usable sometimes, but i often leads to a StackOverflow exception. In this case, you get some strange behaviour...
using System;
namespace Bruh2
{
class Program
{
static void Main()
{
bool tryAgain = true;
while (tryAgain)
{
int pog = 0;
int pog2 = 0;
Random r = new Random();
Console.Write("Input a whole number: ");
string poggers = Console.ReadLine();
while (!int.TryParse(poggers, out pog))
{
Console.WriteLine("ERROR: Not a number. Please input a number and not letters.");
poggers = Console.ReadLine();
}
Console.Write("Input a number higher than the previous: ");
string poggers2 = Console.ReadLine();
while (!int.TryParse(poggers2, out pog2))
{
Console.WriteLine("ERROR: Not a number. Please input a number and not letters.");
poggers2 = Console.ReadLine();
}
int genRand = r.Next(pog, pog2);
Console.WriteLine("This number was randomly generated between " + pog + " and " + pog2 + " and we got: " + genRand);
Console.WriteLine();
Console.WriteLine("Would you like to try again? Y/N");
//ConsoleKeyInfo answer = Console.ReadKey();
string answer = Console.ReadKey().KeyChar.ToString().ToLower();
while (answer!="y" && answer!="n")
{
Console.WriteLine("ERROR: Y/N not any other character");
answer = Console.ReadKey().ToString().ToLower();
}
if (answer == "n")
{
tryAgain = false; // terminate the loop (and thereby the program)
}
}
}
}
}

Going back/forward to a command in C#

Console.WriteLine('What is your name, traveler?');
string mainName = Console.ReadLine();
Console.WriteLine('So, your name is ' + mainName + ' ? y/n');
char ans = Console.ReadKey;
if (ans == y)
{
Console.WriteLine('Nice, let me introduce myself now.');
}
else if(ans == n)
{
}
else
{
Console.WriteLine('Please insert either y or n.');
}
In the code above, how can I make it so that the else if statement will return to the third line and the else statement will return to the first line of the code and continue running from there?
You can try to use do....While(true) loop
Console.WriteLine("What is your name, traveler?");
string mainName = Console.ReadLine();
Console.WriteLine("So, your name is " + mainName + " ? y/n");
do
{
var ans = Console.ReadKey(true).Key;
if (ans == ConsoleKey.Y)
{
Console.WriteLine("Nice, let me introduce myself now.");
break;
}
else if (ans == ConsoleKey.N)
{
break;
}
Console.WriteLine("Please insert either y or n.");
} while (true);
Note
I would use Console.ReadKey(true).Key to get keyboard input value,because it's enum.

C# Loop back to a previous part of code

//Gender Creation:
while (correct == 0)
{
do
{
Console.Clear();
Console.WriteLine("Please choose a gender from the options below: ");
Console.WriteLine("Male|Female|Random");
Console.Write("Input: ");
Gender = Console.ReadLine().ToUpper();
if (Gender == "MALE")
{
Console.WriteLine("Is this the gender you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
Input = Console.ReadLine().ToUpper();
if (Input == "YES")
{
correct = 1;
}
else if (Input == "NO")
{
correct = 0;
}
}
else if (Gender == "FEMALE")
{
Console.WriteLine("Is this the gender you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
Input = Console.ReadLine().ToUpper();
if (Input == "YES")
{
correct = 1;
}
else if (Input == "NO")
{
correct = 0;
}
}
else if (Gender == "RANDOM")
{
correct = 2;
}
else
{
Console.WriteLine("ERROR, Please try again.");
Gender = Console.ReadLine().ToUpper();
}
} while (correct == 0);
//Random Gender Creation:
if (correct == 2)
{
do
{
if (randgender == 1)
{
Console.WriteLine("The gender: MALE was randomly chosen");
Console.WriteLine("Is this the gender you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
Input = Console.ReadLine().ToUpper();
if (Input == "YES")
{
correct = 1;
Gender = "MALE";
}
else if (Input == "NO")
{
correct = 2;
}
}
else if (randgender == 2)
{
Console.WriteLine("The gender: FEMALE was randomly chosen");
Console.WriteLine("Is this the race you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
Input = Console.ReadLine().ToUpper();
if (Input == "YES")
{
correct = 1;
Gender = "FEMALE";
}
else if (Input == "NO")
{
correct = 2;
}
}
} while (correct == 2);
correct = 0;
}
break;
}
When correct = 2 then the gender is being randomly generated, if the user inputs no when being asked if they are happy with the gender the code will just loop the random gender generator over and over constantly saying that the random gender is the same every time as the random number is never changing however when correct = 0 the code will just proceed when no is inputted and when the gender is printed it is just printed as RANDOM as that is the option the user initially chose.
How can I make it go back to the first do while loop to ask the user what gender they want their character to be?
As theMayer suggested, you'll need to break down your app into smaller pieces. There are also a few concepts that you may need to tackle before you can write C#, as such.
This example might help you get a little further along, as it illustrates several ways of achieving better control flow:
static void Main(string[] args)
{
Console.Clear();
var choosenGender = "";
var wasChoiceConfirmed = false;
while (wasChoiceConfirmed == false)
{
choosenGender = PromptForGender();
switch (choosenGender)
{
case "RANDOM":
var randomGender = GenerateRandomGender();
wasChoiceConfirmed = PromptForGenderConfirmation(randomGender, true);
break;
case "MALE":
case "FEMALE":
wasChoiceConfirmed = PromptForGenderConfirmation(choosenGender);
break;
default:
Console.WriteLine("Error, please try again. \n");
break;
}
}
}
static string PromptForGender()
{
Console.Write(
"\nPlease choose a gender from the options below: \n" +
"Male|Female|Random \n" +
"Input:");
return Console.ReadLine().Trim().ToUpper();
}
static bool PromptForGenderConfirmation(string gender, bool wasRandom = false)
{
var randomVerbiage = wasRandom ? "randomly " : "";
Console.Write(
$"\nThe gender: {gender} was {randomVerbiage}chosen \n" +
"Is this the gender you wish your character to be? Enter Yes/No: \n" +
"Input: ");
var confirmed = Console.ReadLine().Trim().ToUpper();
return confirmed == "YES";
}
static string GenerateRandomGender()
{
var randomNumber = new Random();
return randomNumber.Next(0, 1) == 0 ? "FEMALE" : "MALE";
}
I refactored your code so it helps me understand it better. This gives you the result you want and you don't need all those nested loops.
public class Program
{
public static void AskFirstQuestion()
{
Console.Clear();
Console.WriteLine("Please choose a gender from the options below: ");
Console.WriteLine("Male|Female|Random");
Console.Write("Input: ");
var gender = Console.ReadLine()?.ToUpper();
if (gender == "MALE" || gender == "FEMALE")
{
HandleGenderSelection(gender);
}
else if (gender == "RANDOM")
{
HandleRandom();
}
}
private static void HandleRandom()
{
var randomGender = GenerateRandomGender();
Console.WriteLine($"The gender: {randomGender} was randomly chosen");
Console.WriteLine("Is this the race you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
var input = Console.ReadLine()?.ToUpper();
switch (input)
{
case "YES":
Console.WriteLine("OK");
break;
case "NO":
AskFirstQuestion();
break;
}
}
private static string GenerateRandomGender()
{
//Have you logic to randomly create gender
return "MALE";
}
private static void HandleGenderSelection(string gender)
{
Console.WriteLine("Is this the gender you wish your character to be? Enter Yes/No: ");
Console.Write("Input: ");
var input = Console.ReadLine()?.ToUpper();
if (input == "YES")
{
Console.WriteLine("OK!");
}
else if (input == "NO")
{
AskFirstQuestion();
}
}
static void Main(string[] args)
{
AskFirstQuestion();
}
}

Not all my code paths return a value.

I deliberately designed this code, and i can't use it. Can i override this fail-safe?
do // Checks if the chosen name is also the right name
{
string test;
Console.Write("Are you sure " + temp + " is the right name? (y/n)\n");
test = Console.ReadLine();
Console.Write("\n");
if (test.ToLower() == "y")
{
nameIsRight = true;
return temp;
}
else if (test.ToLower() == "n")
{
Console.Write("What is your name then?\n");
temp = Console.ReadLine();
}
Console.Write("\n");
} while (nameIsRight == false);
You should add return statement after this loop:
do // Checks if the chosen name is also the right name
{
//...
}while (!nameIsRight);
return something;
UPDATE: As #hvd stated, you always return from loop. So, possibly throwing exception is a better way here.
UPDATE2: I think best solution is to get rid of boolean flag and inner return statement:
do // Checks if the chosen name is also the right name
{
Console.Write("Are you sure " + temp + " is the right name? (y/n)\n");
key = Console.ReadKey().Key;
Console.Write("\n");
if (key == ConsoleKey.N)
{
Console.Write("What is your name then?\n");
temp = Console.ReadLine();
}
Console.Write("\n");
} while (key != ConsoleKey.Y);
return temp;
Just learn to write better readable (and maintainable) code.
// Ask what you have to ask before the loop
Console.Write("Enter the name: \n");
string result = Console.ReadLine();
while(true)
{
Console.Write("Are you sure " + result + " is the right name? (y/n)\n");
string test = Console.ReadLine();
Console.Write("\n");
if (test.ToLower() == "y")
{
// it will exit the loop
break;
}
// when loop is not exited, keep asking until user answers with "y"
Console.Write("What is your name then?\n");
result = Console.ReadLine();
Console.Write("\n");
};
// result will always contain the latest input, as it's not possible for the user to leave
// except closing the application
return result;
This way you will never get in such a situation and the code is more readable, because you clearly see the break when the loop leaves and you don't need any returns inside the loop at all and you don't need to manage a loop condition (while (nameIsRight == false)).
I would rather do something like this:
EDIT: Corrected code.
do // Checks if the chosen name is also the right name
{
string test;
Console.Write("Are you sure " + temp + " is the right name? (y/n)\n");
test = Console.ReadLine();
Console.Write("\n");
if (test.ToLower() == "y")
{
nameIsRight = true;
}
else if (test.ToLower() == "n")
{
Console.Write("What is your name then?\n");
temp = Console.ReadLine();
continue;
}
else
{
Console.WriteLine("Incorrect input!!!");
continue;
}
} while (nameIsRight == false);
return temp;
You should not be returning your variable from inside the loop, but only setting the condition to true or false.

Categories