So what I'm attempting to do is have this program ignore a user's letter case when entered. I see how to use .ToLower(); however I'm not understanding how to do this the right way.
Here's what I have now, am I close? I've read a bunch of tutorials online however they are mostly just standalone programs that convert user input to lower. Is there a way to enable this globally?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Choose_Your_Color
{
class Program
{
enum Color
{
red,
orange,
blue,
black,
white,
green,
purple,
yellow
}
static void Main(string[] args)
{
Color favorite;
while (true)
{
Console.WriteLine("What color do you choose?");
if (Enum.TryParse(Console.ReadLine(), out favorite))
if (string.compare(favorite , Enum , true) == 0){
Continue;
}
{
switch (favorite)
{
case Color.red:
Console.WriteLine("You chose red!");
break;
case Color.orange:
Console.WriteLine("you chose orange!!!!!!");
break;
case Color.blue:
Console.WriteLine("YOU CHOSE BLUEEEE!!");
break;
case Color.black:
Console.WriteLine("you chose black");
break;
case Color.white:
Console.WriteLine(" you chose white!");
break;
case Color.green:
Console.WriteLine("you chose green!!!!!");
break;
case Color.purple:
Console.WriteLine("you chose purple!!");
break;
case Color.yellow:
Console.WriteLine("you chose yellow!!!");
break;
}
}
else
{
Console.WriteLine("That's not a color!");
}
}
}
}
}
You just need to do:
if (Enum.TryParse(Console.ReadLine().ToLower(), out favorite))
You don't need that nested if, you can just remove it.Also you have to add a break to the end of your if block, so it will break your loop after user type a valid value otherwise the loop will never end.
Enum.TryParse accepts a parameter to ignore case:
Enum.TryParse(Console.ReadLine(), true, out favorite);
Just change this;
if (Enum.TryParse(Console.ReadLine(), out favorite))
to
if (Enum.TryParse(Console.ReadLine().ToLower(), out favorite))
Console.ReadLine() returns a string, this will call to lower on that value ensuring that all the input is lower cased.
Why do you have this line?
if (string.compare(favorite , Enum , true) == 0){
Continue;
}
I don't think there is any reason for it. Enum.TryParse should either return false meaning the input wasn't one of the enums and you won't go into the switch statement OR favorite will be one of the enum values and you'll go into one of the cases in your switch statement.
Note that this overload of TryParse allows you to ignore the case of the input string, so you could just write this as:
if (Enum.TryParse(Console.ReadLine(), true, out favorite))
String.ToLower() will return the string value as lowercase.
if (Enum.TryParse(Console.ReadLine().ToLower(), out favorite))
Related
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)
};
}
I'm making a project and I have a question. I have 3 enum states like this:
enum GameLevel
{
Level1,
Level2,
None,
}
There's a part in my code where I want to check if there's any level selected or none, so I wanted to do something like:
case !GameLevel.None
or
case GameLevel.Level1 || GameLevel.Level2
Is This Possible?
Various options:
Use switch with a default:
switch (level)
{
case GameLevel.None:
// Whatever
break;
default:
// Do something else
// break
}
Use switch with explicit cases:
// Note: if you add a Level3, you'd need to change this...
switch (level)
{
case GameLevel.Level1:
case GameLevel.Level2:
// Whatever
break;
}
Use an if statment:
if (level != GameLevel.None)
{
...
}
Switch is not used to get a "its not the case"-case. However you can use the default: case, which always executes, when the other cases are "false".
For your !GameLevel.None better use an if case. if(selectedGameLevel != GameLevel.None) { }
I believe the choice of assignment should be based on how many levels you plan on implementing. For less levels (as shown in your example), I would use if and else if as opposed to using switch. Switch only works better if there are more options, as it is then performed differently for faster execution. Jon Skeet's answer will guide you on how to implement the choice you make.
This question already has answers here:
Control cannot fall through from one case label
(8 answers)
Closed 7 years ago.
I am having trouble with the following code it seems that the break statement is good but I could not be seeing something.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Switch
{
class swtich
{
static void Main(string[] args)
{
string input; int num;
Console.WriteLine("Enter a number from 0-6: ");
input = Console.ReadLine();
num = int.Parse(input);
switch (num)
{
case 0:
Console.WriteLine("Sunday");
break;
case 1:
Console.WriteLine("Monday");
break;
case 2:
Console.WriteLine("Tuesday");
break;
case 3:
Console.WriteLine("Wednesday");
break;
case 4:
Console.WriteLine("Thursday");
break;
case 5:
Console.WriteLine("Friday");
break;
case 6:
Console.WriteLine("Saturday");
break;
default:
Console.WriteLine("Invalid input");
}
}
}
}
this is the error I am getting
Control cannot fall through from one case label ('default:') to another
Put a break; after your default: case.
...
case 6:
Console.WriteLine("Saturday");
break;
default:
Console.WriteLine("Invalid input");
break;
}
The default case isn't required to be at the end, so you have to include a break just like everywhere else to avoid this warning.
Unlike the switch statements in C, C++ or Java, C# does not allow case statements to fall through, This includes the default case statement. You must add break after your default case.
default:
Console.WriteLine("Invalid Input");
break; // this is required
As #AlexeiLevenkov pointed out, break isn't necessarily required, however, some kind of statement that prevents reaching the end of the construct is required, such as return, break or goto case.
For a school assignment I'm supposed to create a menu kind of like an ATM.
My professor gave us this code to use:
string choice = null;
do
{
Console.Write("[O]pen Account [I]nquire [D]eposit [W]ithdraw [Q]uit: ");
choice = Console.ReadLine();
choice = choice.ToUpper();
switch (choice)
{
case "O": // open an account
case "I": // inquire
case "D": // deposit
case "W": // withdraw
default: break;
}
} while (choice != "Q");
Here is what I did:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string choice = null;
string CustomerName;
Console.WriteLine("Welcome to Fantasy Bank");
Console.Write("Please enter your name:");
CustomerName = Console.ReadLine();
do
{
Console.WriteLine("What can I do for you");
Console.Write("[O]pen Account [I]nquire [D]eposit [W]ithdraw [Q]uit: ");
choice = Console.ReadLine();
choice = choice.ToUpper();
double CurrentBalance = 0;
switch (choice)
{
case "O": // open an account
Console.Write("Name of account holder:");
Console.WriteLine(CustomerName);
Console.Write("Initial Deposit:");
CurrentBalance = Convert.ToDouble(Console.ReadLine()); // i get a major error if someone types in a letter instead of a number
Console.Write("You have succesfully opened an account with an initial deposit of ");
Console.Write(CurrentBalance);
Console.WriteLine(" at an imaginary bank. Congratulations");
break;
case "I": // inquire
Console.Write(CustomerName);
Console.WriteLine("'s Bank Account");
Console.WriteLine(CurrentBalance);
break;
I did a little bit more, but the problem starts here in case "I". CustomerName is getting replaced by what the user types, like it's supposed to be. But CurrentBalance does not change, and I have to set it equal to something otherwise I get an error.
I start to get the feeling that it may be impossible to change a switch variable inside a switch. I looked in my book for passing references/values, but it doesn't include switch in that section.
If y'all could give me a hint what I'm doing wrong or could show me what could fix my problem, that would be great. I'm not expecting code from you, just a little push in the right direction.
Your problem is the placement of your declaration of CurrentBalance.
Currently you have this:
do
{
double CurrentBalance = 0;
switch (choice) {
/* the rest of your code */
}
}
Should be
double CurrentBalance = 0;
do
{
switch (choice) {
/* the rest of your code */
}
}
Now, the next iteration of your do loop does not reset CurrentBalance to 0
Every iteration of the loop you reset CurrentBalance to 0. Move the line double CurrentBalance = 0; :
string choice;
string CurrentName;
double CurrentBalance = 0;
// ...
do
{
// ...
//double CurrentBalance = 0; NOT HERE
switch( ... )
{
}
}
You should initialize all your variables before going into the loop, not in the loop, or else the variable is re-initialized (cleared to 0) every iteration.
double CurrentBalance = 0;
// other code...
do { // ...
I should mention it doesn't have anything to do with changing variables within a switch. Changing variables within a switch is perfectly permissible.
I have the following code :
do{
Console.Write("Please Input a Value: ");
userInput = Console.ReadLine();
v = userInput.ToString().Substring(0, 1);
amount = Convert.ToInt32(userInput.ToString().Substring(1, 1));
switch(v)
{
case "a": mother.incr1(amount);
case "s": mother.incr10(amount);
case "d": mother.incr100(amount);
case "f": mother.incr1000(amount);
case "=": Console.WriteLine("The total amount is: {0} \n", mother.current);
case "r": mother.current = 0;
}
}while(mother.overflow() != true);
when I added the do while, it returned an error "control cannot fall through from one case label #caselabelname# to another" on all the case lines
You need to put a "break;" between each statement
switch(v)
{
case "a":
mother.incr1(amount);
break;
case "s":
mother.incr10(amount);
break;
etc.etc.
}
Since v can only be a single character at a time, there is no reason to allow the case to fall through. You should put a break at the end of each case.
C# inherited the switch statement from the C language. Which has case statement fall through, an incredibly fertile source of hard to diagnose bugs. In your code, fall through will always leave mother.current set to 0.
The C# language requires you to terminate a case statement explicitly to avoid this trap. You must either use break to let code resume at the statement following the switch statement. Or use goto case to direct it to resume execution into another case statement. The break keyword is clearly the appropriate choice here.