c# loop until Console.ReadLine = 'y' or 'n' - c#

I'm fairly new to c#, and writing a simple console app as practice. I want the application to ask a question, and only progress to the next piece of code when the user input equals 'y' or 'n'. Here's what I have so far.
static void Main(string[] args)
{
string userInput;
do
{
Console.WriteLine("Type something: ");
userInput = Console.ReadLine();
} while (string.IsNullOrEmpty(userInput));
Console.WriteLine("You typed " + userInput);
Console.ReadLine();
string wantCount;
do
{
Console.WriteLine("Do you want me to count the characters present? Yes (y) or No (n): ");
wantCount = Console.ReadLine();
string wantCountLower = wantCount.ToLower();
} while ((wantCountLower != 'y') || (wantCountLower != 'n'));
}
I'm having trouble from string wantCount; onwards. What I want to do is ask the user if they want to count the characters in their string, and loop that question until either 'y' or 'n' (without quotes) is entered.
Note that I also want to cater for upper/lower case being entered, so I image I want to convert the wantCount string to lower - I know that how I currently have this will not work as I'm setting string wantCountLower inside the loop, so I cant then reference outside the loop in the while clause.
Can you help me understand how I can go about achieving this logic?

You could move the input check to inside the loop and utilise a break to exit. Note that the logic you've used will always evaluate to true so I've inverted the condition as well as changed your char comparison to a string.
string wantCount;
do
{
Console.WriteLine("Do you want me to count the characters present? Yes (y) or No (n): ");
wantCount = Console.ReadLine();
var wantCountLower = wantCount?.ToLower();
if ((wantCountLower == "y") || (wantCountLower == "n"))
break;
} while (true);
Also note the null-conditional operator (?.) before ToLower(). This will ensure that a NullReferenceException doesn't get thrown if nothing is entered.

If you want to compare a character, then their is not need for ReadLine you can use ReadKey for that, if your condition is this :while ((wantCountLower != 'y') || (wantCountLower != 'n')); your loop will be an infinite one, so you can use && instead for || here or it will be while(wantCount!= 'n') so that it will loops until you press n
char charYesOrNo;
do
{
charYesOrNo = Console.ReadKey().KeyChar;
// do your stuff here
}while(char.ToLower(charYesOrNo) != 'n');

Related

is there a way to instead of making double not freeze project and instead say invalid number?

i am new in stack overflow, but i've ran into a problem.
what i want to do exactly is an advanced calculator, but can't find out a way to give an error message (then i will add a retry option) instead of making the console freeze.
Console.Write("Type A Number: ");
double num1 = Convert.ToDouble(Console.ReadLine());
//detects numbers
if (num1 != "1")
Console.WriteLine("invalid number!");
//detects numbers
Console.Write("Type An Operator: ");
string op = Console.ReadLine();
Console.Write("Type Another Number: ");
double num2 = Convert.ToDouble(Console.ReadLine());
//the operator logic system!!!
the operator logic system detects if the operator (+ - x/* / etc) is valid, but I can't find out for number. after that, I am going to make a game, but I can't find out for this one now.
Try this:
Console.Write("Type A Number: ");
if (!double.TryParse (Console.ReadLine(), out double num1))
Console.WriteLine("invalid number!");
TryParse returns false if the entered text is not a valid double. If it is valid it returns true and puts the number into num1.
This code is going to cause you issues if the user enters an unexpected value. E.g. They enter a string instead of a number. So you need to also look for and account for that.
Best is to create different methods which will check the input and only return a valid result, otherwise to prompt the user. So you have something like this;
The main method calls submethods, so is relatively simple.
You call GetValidNumber to return the number inputs for bother number 1 and number 2
GetValidOperator to return the valid operator, which itself calls IsValidOperator to check the input is valid (as there is more to check).
Double.TryParse(...) is the main check if the double number entered is valid or not. But using TryParese it will not through an exception if the user enters an non-valid number, but rather just return false. So it is a safe way of checking user input in this case.
The code might need refining and error checking improved, but it should put you on the right course.
static void Main(string[] args)
{
double number1 = GetValidNumber("Enter first number");
string op = GetValidOperator();
double number2 = GetValidNumber("Enter second number");
Console.WriteLine($"Operation is {number1} {op} {number2}");
//Add code to perform your operation
}
private static double GetValidNumber(string message)
{
Console.WriteLine(message);
string input = Console.ReadLine();
double output;
while (!Double.TryParse(input, out output) )
{
Console.WriteLine("Invalid number! Please try again");
input = Console.ReadLine();
}
return output;
}
private static string GetValidOperator()
{
Console.WriteLine("Enter an operator + - * / ");
string input = Console.ReadLine();
while (!IsValidOperator(input))
{
Console.WriteLine("Invalid Operator! Please try again");
input = Console.ReadLine();
}
return input;
}
private static bool IsValidOperator(string input)
{
bool result = false;
if (String.IsNullOrWhiteSpace(input))
return false;
if (input.Length != 1)
return false;
if (input[0] == '+' || input[0] == '-' || input[0] == '/' || input[0] == '*')
return true;
else
return result;
}
Well, you can use Double.Parse instead of Convert.ToDouble. It will throw exception on failed conversion and you will be able to handle that.

Parsing and looping on user Yes/No console input in C#

I'm writing a method that I will use in another code so I'm writing it separately first.
The code returns a boolean based on the first char of the input (yes, Yes, y, yeah, No, ...). But when the input is different from Y or N it starts acting up. In eg3 It stays in the loop until The Console.Read encounters a Y or an N or there are no chars left. In the last case, it will ask again for input.
Am I using the Console.Read wrong or is there another error in my code?
Thanks in advance
EDIT: Is the solution, in the end, an efficient one?
eg1:
Yes or No?
YeahIthinkso <--my input
True
eg2:
Yes or No?
Negative <--my input
False
eg3:
Yes or No?
Idontknow <--my input
You can only answer with Yes or No
Yes or No?
You can only answer with Yes or No
Yes or No?
You can only answer with Yes or No
Yes or No?
False
The Code:
static void Main(string[] args)
{
char YN = 'x';
bool ans = false;
while (YN == 'x')
{
Console.WriteLine("Yes or No?");
YN = char.ToUpper(Convert.ToChar(Console.Read()));
switch (YN)
{
case 'Y':
ans = true;
break;
case 'N':
ans = false;
break;
default:
Console.WriteLine("You can only answer with Yes or No");
YN = 'x';
break;
}
}
Console.WriteLine(ans);
Alternate solution based on #StuartLC's answer:
bool ans = true, loop = true;
do
{
switch (Console.ReadLine().ToUpper().FirstOrDefault())
{
case 'Y':
ans = true;
loop = false;
break;
case 'N':
ans = false;
loop = false;
break;
default:
Console.WriteLine("You can only answer with Yes or No");
break;
}
} while (loop==true);
Console.WriteLine(ans);
As per #Lasse's comment - if the user types in multiple characters, you'll loop on each character in the string typed in by the user, resulting in the printing a new line of output for each character the user typed. Instead, use of ReadLine will parse the input as a single string, and then the Linq extension FirstOrDefault() will safely obtain the first char in the string:
YN = char.ToUpper(Console.ReadLine().FirstOrDefault());
As an aside, instead of starting a while loop with a forced false condition, C# also supports a do-while loop syntax which fits your requirement better, i.e. at least one iteration through the loop, with a check at the end of the loop:
do
{
Console.WriteLine("Yes or No?");
YN = char.ToUpper(Console.ReadLine().FirstOrDefault());
switch (YN)
{
case 'Y':
ans = true;
break;
case 'N':
ans = false;
break;
default:
Console.WriteLine("You can only answer with Yes or No");
YN = 'x';
break;
}
}
while (YN == 'x');
Re OP's follow up question
Can I now remove the 'YN' completely and put a switch (Console.ReadLine().FirstOrDefault().ToUpper()) in the beginning and a while (ans == true || ans ==false) in the end?
Not quite - since ans is a boolean, it can only have two states (true or false), and you need to model at least 3 states (true, false, and invalid). Although you could use a nullable boolean (bool?) to model the 3 states (where null = invalid), I personally dislike using null to indicate something isn't known, as this invariably leads to the NullReferenceException abyss, and C# hasn't (yet) opted for the "Option" type / Monad (like Java's Optional).
If you're OK with C#8 pattern matching and tuples, you could possibly make the code a bit more concise and refactored as follows, by splitting out the concerns of 'is the input valid' and 'what is the valid input value'?. You could also refactor the switch expression into it's own method to split out the concerns of 'UI' from the parsing logic, which is always a good idea.
static void Main(string[] args)
{
bool ans;
bool isValid;
do
{
Console.WriteLine("Yes or No?");
(ans, isValid) = ParseInput(Console.ReadLine());
if (!isValid)
{
Console.WriteLine("You can only answer with Yes or No");
}
}
while (!isValid);
Console.WriteLine(ans);
(bool ans, bool isValid) ParseInput(string input) =>
char.ToUpper(input.FirstOrDefault()) switch
{
'Y' => (true, true),
'N' => (false, true),
_ => (default, false)
};
}

Unorthodox approach to checking if a string is a palindrome

I'm attempting to create an unorthodox approach to working out if a string is palindrome or not. I am aware of the current .Reverse() method that you can use but this is the way that I am trying to do it:
The user will enter the string and then the program will check the first and last letters of the string. If they are the same, it will keep checking. If they are not (at the start or at any particular point) then the program will declare that it is not a palindrome. Once the program stops checking and sees that no letters are not the same, it will declare that it is a palindrome.
Here is my current code below:
using System;
using System.Collections.Generic;
namespace tasks
{
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Enter a message and I will check if it is a palindrome: ");
string message1 = Convert.ToString(Console.ReadLine().ToLower());
char[] message = message1.ToCharArray();
int i = 0;
int j = message.Length - 1;
if (message[i] == message[j])
{
do
{
i++;
j--;
if (message[i] == message[j])
Console.Write("This is a palindrome");
else if (message[i] != message[j])
Console.Write("This is not a palindrome");
break;
} while (message[i] == message[j]);
}
else if (message[i] != message[j])
{
Console.WriteLine("This is not a palindrome");
}
}
}
(Sorry about the indentation).
If I was to type in 'haegah', the program would say that this is a palindrome. When it is clearly not. My question is, what is causing my program to do this and how can I fix it?
You've neglected to wrap { and } around Console.Write("This is not a palindrome"); break;. When you do this, only the first expression becomes conditional. The break; isn't encapsulated inside of the else branch, and will execute unconditionally thus terminating your loop in the first iteration.
This explains what I think is causing one of your problems, and how you can fix it. However, there are other problems.
By incrementing&decrementing your counters before you compare the characters, you're skipping two characters (the ones at the start and end). You can perform the incrementation & decrementation simultaneously in your loop condition with a comparison like: message[i++] == message[j--]...
Even if you fix these, your loop won't terminate sanely; the two variables will overlap, and then you'll continue until one is negative and the other is out of bounds (well, technically, they're both out of bounds)... In addition to your loop executing while message[i] == message[j], it should also only execute while i < j.
But wait, there's another problem! What do you suppose will happen when the string is an empty string? You need to guard against that condition before your loop, or use a while (...) { ... } loop.

why does my loop work with the "&&" operator but not "||" or "^"?

The code asks the user whether he/she has eaten something or not. Then it loops the question until a valid input (such as "nothing" or "something") is entered. My problem is that when I use the "||" operator, the loop continues no matter what is inputted. To my understanding, the loop should end when the user inputted string is equal to "nothing", "something", or both based on the operator I'm using. But this result only occurs when I use the "&&" operator, which confuses me as that would mean that the user would have to input a string value equal to "nothing" AND "something". So my question is why does my loop work with the "&&" operator but not "||" or "^" operator ? Thanks in advance.
struct multivar
{
public int userInt;
public string userText;
}
class Program
{
static void Main(string[] args)
{
multivar structHolder;
string shrinkRay = "";
while ((shrinkRay != "nothing") || (shrinkRay != "something"))
{
Console.WriteLine("What did you eat today?\n1)Nothing?\n2)Something?");
structHolder.userText = Console.ReadLine();
shrinkRay = structHolder.userText.ToLower();
if ((shrinkRay != "nothing") || (shrinkRay != "something"))
{
Console.WriteLine("Please input a valid response such as \"Nothing\" or \"Something\".");
}
}
your logic:
str != 1 || str != 2
can be rewritten as
!(str == 1 && str == 2)
its obvious one of the inner statements must be false, so the whole inner statement will be false. The negation will make the statement true, always. You need to alter your logic as others have said.
The user cannot enter both "nothing" and "something" so, your || is always going to be true. It simply is the correct logic to use &&.
Is either
(shrinkRay != "nothing" && shrinkRay != "something")
Or
!(shrinkRay == "nothing" || shrinkRay == "something")
See De Morgan's laws

Using a letter as a valid user input (console project)

I'm writing an app where the console asks the user a question that has five possible answers (these being a)b)c)d)e) answers). I'm trying to find a way to make the console recognise the letter that the user is inputing and then tell the user whether the answer is correct or incorrect. Here's what I have so far, although it doesn't seem to work. Any help would be appreciated.
Console.ReadLine ();
Console.WriteLine ("Q9: Of the following, which is greater than one half?");
Console.WriteLine ("A: 2/5");
Console.WriteLine ("B: 4/7");
Console.WriteLine ("C: 4/9");
Console.WriteLine ("D: 5/11");
Console.WriteLine ("E: 6/13");
string ans9;
Console.ReadLine ();
if (ans9 == b) {
Console.WriteLine ("Correct");
} else if (ans9 != b) {
Console.WriteLine ("Incorrect");
The Console reads the line as a string so you need to check it with:
if (ans9 == "b")
But you might want to also thing about casing. What happens if the user enters B?
if (ans9.ToLower() == "b")
You're also not assigning the value of ReadLine to ans9:
string ans9 = Console.ReadLine();
Another edit: instead of checking if ans9 is equal to "b" and then checking that its not equal to "b" you can just use an else:
if (ans9 == "b") {
Console.WriteLine("Correct");
}
else {
Console.WriteLine("Incorrect");
}

Categories