while (playerMove != "SCISSORS" || playerMove != "PAPER" && playerMove != "ROCK" || string.IsNullOrEmpty(playerMove))
{
Console.WriteLine("Please enter a valid command!");
playerChoice = Console.ReadLine().ToUpper().Trim();
continue;
}
Can someone explain to a beginner programmer why this code doesn't work.
The way I read this code myself is:
While playerMove isn't "SCISSORS" or "PAPER" and isn't "ROCK" or Empty, do this...
How do I make this work?
If you enter "PAPER", then playerMove != "SCISSORS" is true, so your while-condition is true, because only one part of a logical OR has to be true.
You want all of the !="XYZ" to be true, OR the string to be empty:
while((playerMove != "SCISSORS" && playerMove != "PAPER" && playerMove != "ROCK") || string.IsNullOrEmpty(playerMove))
That said, there are probably easier ways to check this.
You could define a list of acceptable strings, for instance, and check against that:
using System.Linq;
...
var acceptedString = new List<string> {"ROCK", "PAPER", "SCISSORS"};
...
while (!acceptedStrings.Contains(playermove)
{
// error message
}
Actually checking for an empty string is useless, since an empty string never has an accepted value.
Another option, as mentioned in a comment, is to extract your condition to a method. This is almost always a good idea for complicated conditions:
while (!IsValid(playermove)){...}
...
private static bool IsValid(string move)
{
return move == "ROCK"
|| move == "PAPER"
|| move == "SCISSORS";
}
Alternatively you can rewrite that to
while (!IsValid(playermove)){...}
...
private static bool IsValid(string move) =>
move == "ROCK" || move == "PAPER" || move == "SCISSORS";
I feel so dumb right now, i only just noticed i broke my head over this code for no reason.
I noticed in the loop i asked to set a new value to "playerChoice", instead of playerMove. hence why it didnt run the way i wanted it to.
while ((playerMove != "SCISSORS" && playerMove != "PAPER" && playerMove != "ROCK") || string.IsNullOrEmpty(playerMove))
{
Console.WriteLine("Please enter a valid command!");
playerMove = Console.ReadLine().ToUpper().Trim();
continue;
}
Including answer into the conditions aswell.
Related
I have a list of existing products presented in a datagridview. User can add new product using this window
Some of the fields can be accepted as empty. The text field must have char only and the int fields must have positive int only. ID, price, playtime and status must be positive ints. The rest must be chars, when they aren't empy that is. The code i have works but only when every field that could be empty is empty. It doesn't work if some are and others aren't.
It would also be nice if you could solve the issue of accepting empty int fields.myint.ToString().Length; is not getting the job done seems like. Maybe the answer is easy but I'm sorta new to C# and .Net.
Here is the code i wrote
if (!plist.type.Any() || !plist.author.Any() || !plist.genre.Any() || !plist.format.Any() || !plist.language.Any() || !plist.platform.Any())
{
if (plist.id != Math.Abs(plist.id) || plist.price != Math.Abs(plist.price)
|| plist.playtime != Math.Abs(plist.price) || plist.status != Math.Abs(plist.price))
{
DialogResult = DialogResult.No;
}
else if (plist.type.Any(char.IsDigit) || plist.name.Any(char.IsDigit)
|| plist.author.Any(char.IsDigit) || plist.genre.Any(char.IsDigit)
|| plist.format.Any(char.IsDigit) || plist.language.Any(char.IsDigit) || plist.platform.Any(char.IsDigit))
{
DialogResult = DialogResult.No;
}
else
{
DialogResult = DialogResult.OK;
}
}
else
{
DialogResult = DialogResult.OK;
}
Let me know if there is anything left to clear up.
I appreaciate any suggestions you got for me!
Assuming that type, author, genre, format, language and platform are mandatory fields, you should be setting DialogResult to DialogResult.No instead of OK in your bottom most else statement. Otherwise, you will be skipping your logic and returning the wrong result.
if (!plist.type.Any() || !plist.author.Any() || !plist.genre.Any() || !plist.format.Any() || !plist.language.Any() || !plist.platform.Any())
{
if (plist.id != Math.Abs(plist.id) || plist.price != Math.Abs(plist.price)
|| plist.playtime != Math.Abs(plist.price) || plist.status != Math.Abs(plist.price))
{
DialogResult = DialogResult.No;
}
else if (plist.type.Any(char.IsDigit) || plist.name.Any(char.IsDigit)
|| plist.author.Any(char.IsDigit) || plist.genre.Any(char.IsDigit)
|| plist.format.Any(char.IsDigit) || plist.language.Any(char.IsDigit) || plist.platform.Any(char.IsDigit))
{
DialogResult = DialogResult.No;
}
else
{
DialogResult = DialogResult.OK;
}
}
else
{
DialogResult = DialogResult.No;
}
As for the empty integer length issue, make sure that you are not trying to turn a null value to a string. Consider using a numericUpDown instead of a textbox as the numericUpDown is designed to work with numbers. You can even set limits to you numbericUpDown, like a lower number limit to prevent negative numbers.
https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.numericupdown?view=windowsdesktop-7.0
I have following code:
var dateFrom = DateTime.Parse(string.Format(string.Format("01.04.{0}", dateProperty.Value.AddYears(-1).Year))
if (object.nullablebool.HasValue ? object.nullablebool.Value : false
&& (string == "V" || string == "N")
&& someDate.HasValue && object.SomeOtherDate.HasValue
&& someDate.Value.Date > dateFrom.Date)
{
>> Code
}
I have tested adding .Date or even specifiing exact year from the DateTime struct, but nothing worked.
When executing the code, even if
someDate.Value.Date > dateFrom.Date
equals 1700 > 2018, the code executed as if it was true, even though the debugger says it´s false.
When I removed this part from the condition, following code:
someDate.HasValue && object.SomeOtherDate.HasValue
When I made someDate null, so someDate.HasValue is false, the if statement still executes as true.
What did it fix? Taking these two conditions to another if:
var dateFrom = DateTime.Parse(string.Format(string.Format("01.04.{0}", dateProperty.Value.AddYears(-1).Year))
if (object.nullablebool.HasValue ? object.nullablebool.Value : false
&& (string == "V" || string == "N"))
{
if (someDate.HasValue && object.SomeOtherDate.HasValue
&& someDate.Value.Date > dateFrom.Date)
{
>> Code
}
else
{
>> Code
}
}
The code works, but it´s way too ugly. I'm running on Visual Studio 2017 Pro.
Any ideas why it behaves like that? Executing false statements?
Thanks
Your if statement performs different then expected, because it is parsed different as you wouls expect.
object.nullablebool.HasValue ? object.nullablebool.Value : false && ... is parsed as object.nullablebool.HasValue ? object.nullablebool.Value : (false && ...). So if object.nullablebool has a value, thats the result of the condition. To fix this you have to add parenthesis like this:
if ((object.nullablebool.HasValue ? object.nullablebool.Value : false )
&& (string == "V" || string == "N")
&& someDate.HasValue && object.SomeOtherDate.HasValue
&& someDate.Value.Date > dateFrom.Date)
{
// if body
}
Let's brush up your code (please, get rid of names like string, object; change them into meanful names):
// You don't want any formatting but a simple constructor
var dateFrom = new DateTime(dateProperty.Value.Year - 1, 4, 1);
// object.nullablebool == true - if object.nullablebool has value and the value is true
if (object.nullablebool == true && (string == "V" || string == "N")) {
// if someDate.Value is null the result will be false
// All we have to do is to propagate the null: ?. in someDate?.Date
if (someDate?.Date > dateFrom.Date && object.SomeOtherDate.HasValue) {
// Code
}
else {
// Code
}
}
This question already has answers here:
Control cannot fall through from one case label
(8 answers)
Closed 9 years ago.
I am trying to convert an if statement to switch cases (for readability)
1) I've read switch statements are aweful in general - Is that true?
https://stackoverflow.com/questions/6097513/switch-statement-inside-a-switch-statement-c
2) The statement goes like this:
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
case Display.NonExpense:
if (expected.EXPENSE == true)
break;
case Display.All:
//Code
break;
}
Error is:
Control cannot fall through from one case label ('case 1:') to another
This is the original if statement:
if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
First off, I notice that you forgot to ask a question in your second point. So I'm going to ask some questions for you addressing your second point:
What is the meaning of the "can't fall through" error?
Unlike C and C++, C# does not allow accidental fall-through from one switch section to another. Every switch section must have an "unreachable end point"; it should end with a break, goto, return, throw or (rarely) infinite loop.
This prevents the common bug of forgetting to put in the break and "falling through" accidentally.
You've written your code as though fall-through is legal; my guess is that you're a C programmer.
How can I force fall-through in C#?
Like this:
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
else
goto case Display.All;
case Display.NonExpense:
if (expected.EXPENSE == true)
break;
else
goto case Display.All;
case Display.All:
//Code
break;
}
Now the reachability analyzer can determine that no matter which branch of the "if" is taken, the switch section endpoint is unreachable.
Is this good style?
No. Your original code was a lot more readable.
I've read switch statements are aweful in general - Is that true?
Opinions vary. Switch statements are very useful when there is a small number of very "crisp" alternatives whose behaviours do not interact in complex ways. Some people will tell you that switched logic should instead be handled by virtual methods or visitor patterns, but that can be abused as well.
Should I use a switch in this particular case?
I wouldn't.
How would you improve my code?
if ((Show == Display.All) ||
(expected.EXPENSE == true && Show == Display.Expense) ||
(expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
First off, don't name things IN ALL CAPS in C#.
Second, don't compare Booleans to true and false. They're already Booleans! If you want to know the truth of statement X you would not say in English "is it true that X is true?" You would say "Is X true?"
I would likely write:
if (Show == Display.All ||
Show == Display.Expense && expected.Expense ||
Show == Display.NonExpense && !expected.Expense)
{
//Code
}
Or, even better, I would abstract the test away into a method of its own:
if (canDisplayExpenses())
{
//Code
}
Or abstract the whole thing away:
DisplayExpenses();
The compiler will not understand what you mean here.
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
// missing break here
case Display.NonExpense:
The compiler will not connect the dots and understand that the break; statement inside your if statement is linked to the switch statement. Instead it will try to link it to a loop, since break; statements on their own can only be used with loops, to break out of it.
That means that your case block is missing its break statement to complete it, and thus the compiler complains.
Instead of trying to wring the necessary code out of a switch statement, I would instead break up your original if statement.
This is yours:
if ((Show == Display.All) || (expected.EXPENSE == true && Show == Display.Expense) || (expected.EXPENSE == false && Show == Display.NonExpense))
{
//Code
}
This is how I would write it:
bool doDisplayExpected =
(Show == Display.All)
|| (Show == Display.Expense && expected.EXPENSE)
|| (Show == Display.NonExpense && !expected.EXPENSE);
if (doDisplayExpected)
{
// code
}
You don't have to pack everything on one line.
Also, I would try to name properties so that they're easier to read, I would rename the EXPENSE property to IsExpense so that the above code would read like this:
bool doDisplayExpected =
(Show == Display.All)
|| (Show == Display.Expense && expected.IsExpense)
|| (Show == Display.NonExpense && !expected.IsExpense);
if (doDisplayExpected)
{
// code
}
Then, ideally, I would refactor out the sub-expressions to methods:
bool doDisplayExpected =
ShowAll()
|| ShowExpense(expected)
|| ShowNonExpense(expected);
if (doDisplayExpected)
{
// code
}
public bool ShowAll()
{
return Show == Display.All;
}
public bool ShowExpense(Expected expected)
{
return Show == Display.Expense && expected.EXPENSE;
}
public bool ShowNonExpense(Expected expected)
{
return Show == Display.NonExpense && !expected.EXPENSE;
}
Then you can put the expression back into the if-statement:
if (ShowAll() || ShowExpense(expected) || ShowNonExpense(expected))
{
// code
}
This should be easier to read, and change later on.
Use if statements and extract complex conditions into methods, e.g
if (ShowAll() || ShowExpense())
{
}
Remember about OOP and polymorphism every time you write such 'switch', adding another
case to that code will be a nightmare
see this and similar (C++) instructions about converting switches
P.S if you are interested in making your code clean and readable, consider reading Smalltalk Best Practice Patterns by Kent Beck and/or Clean Code by Uncle Bob
I really enjoyed both of them, highly recommend.
If you want readability, just throw away your syntax trash:
if (Show == Display.All || expected.EXPENSE && Show == Display.Expense || !expected.EXPENSE && Show == Display.NonExpense)
{
//Code
}
Provide the else part for each of them so it will not throw error, however as others say, you actually don't need switch in this case.
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
// do what you want
break;
else
// do what you want
break;
case Display.NonExpense:
if (expected.EXPENSE == true)
// do what you want
break;
else
// do what you want
break;
case Display.All:
//Code
break;
}
The reason why you get this error is that you are not defining break statements.
You defined the break conditionally.
switch (Show)
{
case Display.Expense:
if (expected.EXPENSE != true)
break;
// Note that the break above is in scope of you if statement, and will
// result in a compiler error
case Display.NonExpense:
...
}
Either make sure every case statement has its own break or group the case statements as follows.
switch (Show)
{
case Display.Expense:
case Display.All:
// do stuff
// Expense and All have the same behavior
}
Refactor out the if statements so you can express it like so:
if (isDisplayAll() || isExpense(expected) || isNonExpense(expected))
{
// Code
}
The extracted logic:
private bool isDisplayAll()
{
return (Show == Display.All);
}
private bool IsExpense(Expected expected)
{
return expected.EXPENSE && (Show == Display.Expense);
}
private bool IsNonExpense(Expected expected)
{
return !expected.EXPENSE && (Show == Display.NonExpense);
}
Agree with Dennis, you don't want a switch case for this problem.
Although probably less readable, you can also use shorter:
if (Show == Display.All || (expected.EXPENSE == (Show == Display.Expense)))
{
//Code
}
I'm working on a simple password storage console application in c#.
I'm having a bit of a problem on a section that asks if the user would like to mask all password entries from that point on.
This is the section of code:
bool tryagain = true;
while(tryagain == true)
{
Console.WriteLine("Would you like to mask all other password entiries?(Y,N)");
string input = Console.ReadLine();
if (input == "y" | input == "Y")
//Something wrong, always passes to Your awnser was invalid
{
maskpass = true;
tryagain = false;
}
if (input == "n" | input == "N")
{
maskpass = false;
tryagain = false;
}
else
{
Console.WriteLine("Your awnser was invalid, would you like to try again?");
string yesno = Console.ReadLine();
if (yesno == "y" | yesno == "Y")
{
tryagain = true;
}
if (yesno == "n" | yesno == "N")
{
Environment.Exit(0);
}
}
}
The problem is when I run the code it always runs to the else statement.
I'm certain the mistake is very simple and I'm just being ignorant but anyone have any idea on whats going on here?
Use || instead of single |. The || mean or conditional, but single | is binary or.
I assume that the logic of your code says:
if input=='y' OR input=="Y", do something.
Another suggession yet. If my assumption right, you can achiev that with simple String.Equals overload:
if(input.Equals("y", StringComparison.InvariantCultureIgnoreCase)
{
//do something/
}
You can either use || or you can use the method of the String class String.equals. Since it is a String you are reading as input better use the String.equals method
I don't know if it is just me being thick but I have a bit of validation code to check for a yes or no answer.
I can't seem to get it to work I have used the code in other places in my program and it works but I can't spot the error if there is one. The code runs through the while anyway no mater what the input character is.
string correctDestenation = Console.ReadLine().ToLower();
while (correctDestenation != "y" || correctDestenation != "n")
{
Console.WriteLine(
"Oops! You must enter a 'y' for yes and a 'n' for no");
correctDestenation = Console.ReadLine().ToLower();
}
Your logic is incorrect. You want to use && instead of ||.
while (correctDestenation != "y" && correctDestenation != "n")
or, you can use De Morgan's Law and look at it the other way, which is equivalent:
while (!(correctDestenation == "y" || correctDestenation == "n"))
That condition will always be satisfied, as a character will not be equal to 'y' or equal to 'n'. Use && instead of ||.
How about you use the AND operator
while (correctDestenation != "y" && correctDestenation != "n")
{
Console.WriteLine("Oops! You must enter a 'y' for yes and a 'n' for no");
correctDestenation = Console.ReadLine().ToLower();
}