I'm beginner to c++ and writing a program that accepts user choices and acts according to it...my only problem is when the user enters Uppercase choice...the program treats it as it's a wrong choice...like if 'e' was a choice for entering a number..if the user entered 'E' the program won't display the "enter the number" message..how can i fix it ? i tried my best but i can't get it working.. Oh , and how can i add the Uppercase in Switch cases ?
This is the part of the code that's responsible of taking user's choice and act according to it.
#include <iostream>
#include <cstring>
using namespace std;
int main(){
char choice ;
for(;;){
do{
cout << endl ;
cout << "(e)nter." << endl ;
cout << "(d)isplay." << endl;
cout << "(u)pdate." << endl ;
cout << "(r)eset. " << endl;
cout << "(q)uit." << endl;
cout << endl;
cout << "Choose one : " ;
cin >> choice ;
if( !strchr("edurq",choice) && (choice>=97&&choice<=122) ){
cout << "Enter e,d,u or q " << endl;}
else if( !strchr("EDURQ",choice) && (choice<97&&choice>122) ){
cout << "Enter E,D,U or Q " << endl;}
}while( !strchr("edurqEDURQ",choice) );
switch (choice) {
case 'e' : enter(); break ;
case 'd' : display(); break ;
case 'u': update() ; break ;
case 'r' : reset() ;break;
case 'q' : return 0;
}
}
}
Use the tolower function to convert your input to lowercase and then you will only need to worry about the lowercase options.
If you don't break for a case in a switch statement that matches it will continue on to the next one. If you put the capital cases before each lower case choice it will fall through.
switch (choice) {
case 'E' :
case 'e' : enter(); break ;
case 'D' :
case 'd' : display(); break ;
case 'U' :
case 'u': update() ; break ;
case 'R' :
case 'r' : reset() ;break;
case 'Q' :
case 'q' : return 0;
}
The other option is to apply a string function to the user input to change it to lower case, in which case your existing switch statement would work.
This is a perfect time to use fall through in case statements.
switch (choice)
{
case 'E':
case 'e':
enter();
break;
// etc.
}
Uppercase and lowercase characters use different character codes. So, if you use just lowercase cases in your switch, you will be testing just one type of cases.
You should either improve your switch statement tests, as other exemplified, or convert your choice character to lowercase. This way making sure you are providing the expected case for your switch tests.
Hack it
switch (choice | 0x20) {
...
Related
So I've been learning how to use the "switch" statement recently. I decided to do some practice exercises. The code I show in my sample code below is one I came up with myself as a solution for a "Cola Machine" beginner exercise I found on a website "cplusplus". The exercise problem text can be found as a multi-line comment at the top of my code. Though, I did decide to try to make my code do more than what was required of the exercise.
For the most part, this code works exactly how I want it to. At first I even struggled to figure out how to get the code to repeat the user input in the line switch (cin.get()), if they had entered an invalid answer, but I solved this issue by nesting the "switch" statment inside of a "for" statement, for (int x = 0; x < 1; x++), and having the invalid answers decrement the counter ( x--; ). Not sure if that's a practical solution, but it's the one I came up with.
The only time my program doesn't run as intended is when a multiple character input that contains both valid answers and invalid answers is entered into the program (i.e. "-1" or "17"). The latter example outputs the statement for only the valid part of the answer, the statement for case '1', where as the former example outputs the statements for invalid answers and valid answers, so the default case and case '1'. Example for input "-1"
I'm wondering if that's just a problem that is inherent to using using "switch" statements in general, or if there's a practical solution I've yet to learn. I'm using a book to learn how to code, "C++ How To Program" by H.M. Deitel/P.J. Deitel, and they had given me a sample code for a letter grade counting program that can be found in my previous question on here. And I found that this same problem occurs in that sample code.
I'd be happy to hear any and all solutions, thank you ! :)
/* Write a program that presents the user w/ a choice of your 5 favorite beverages (Coke, Water, Sprite, ... , Whatever).
Then allow the user to choose a beverage by entering a number 1-5.
Output which beverage they chose.
>> Modify the program so that if the user enters a choice other than 1-5 then it will output "Error. choice was not valid, here is your money back." */
#include <iostream>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::string;
int main()
{
string drink1 = "Water", drink2 = "Coke", drink3 = "Pepsi",
drink4 = "Orange Juice", drink5 = "Powerade";
string choose_text = "\n\nChoose your preferred drink: ", chosen_text = "\nYou have chosen: ";
cout << "1.) " << drink1.append(17 - drink1.length(), ' ') << "2.) " << drink2.append(17 - drink2.length(), ' ')
<< "3.) " << drink3.append(17 - drink3.length(), ' ') << "4.) " << drink4.append(17 - drink4.length(), ' ')
<< "5.) " << drink5.append(17 - drink5.length(), ' ') << choose_text;
for (int x = 0; x < 1; x++) {
switch (cin.get()) {
case '1':
cout << chosen_text << drink1 << endl;
break;
case '2':
cout << chosen_text << drink2 << endl;
break;
case '3':
cout << chosen_text << drink3 << endl;
break;
case '4':
cout << chosen_text << drink4 << endl;
break;
case '5':
cout << chosen_text << drink5 << endl;
break;
case '\n': case ' ':
x--;
break;
default:
cout << "\nError. Choice was not valid.\nPlease enter an option 1 - 5." << choose_text;
x--;
break;
}
}
return 0;
}
You can do this:
int answer;
cin >> answer;
That will retrieve an integer value from the user instead of a single character. That solves part of your problem.
Now, let's look at your loop. Ick. Let's try this:
bool keepWorking = true;
do {
keepWorking = false;
int answer;
cin >> answer;
switch (answer) {
...
set keepWorking to true on the bad answers
}
} while (!cin.eof() && keepWorking);
I'm having a problem with a program I've built.
It should take input from the user and check whether it's 'P' or 'M'.
The problem is that I only want it to work if you enter 'P' or 'M', as it is now it accepts as 'M' anything you type as long as it starts with an 'M' (eg. if you type "morse" it will accept it as 'M').
I'm not a programmer and don't have much knowledge of c++, I just made it for fun. An example of how it is:
int main(){
std::cout << "Enter 'M' or 'P'\n";
char slction;
Inputrror:
std::cin >> slction;
switch (slction) {
case 'M':
goto Morse;
break;
case 'm':
goto Morse;
break;
case 'P':
goto Text;
break;
case 'p':
goto Text;
break;
default:
std::cout << "Please only enter 'M' or 'P'\n;
goto Inputrror;
break;
}
Morse:
std::cout << "Morse\n;"
return 1;
Text:
std::cout << "Text\n;"
return 1;
}
EDIT: I tried to read the input as a string like it was suggested and it now works properly. The correct version:
int main() {
std::cout << "Enter 'M' or 'P'\n";
std::string slction;
Inputrror:
std::cin >> slction;
if (slction == "M" || slction == 'm') {
goto Morse;
}
else if (slction == "P" || slction == 'p') {
goto Text;
}
else {
std::cout << "Please only enter 'P' or 'M'\n";
goto Inputrror;
}
Morse:
std::cout << "Morse\n";
return 1;
Text:
std::cout << "Text\n";
return 1;
}
One comment before I answer:
Instead of
case 'M':
goto Morse;
break;
case 'm':
goto Morse;
break;
you could use
case 'M':
case 'm':
goto Morse;
break;
break stops the block so as long as you don't use it you can nest one after another. You can even do stuff like:
case 'M':
cout << "CAPITALIZED";
case 'm':
goto Morse;
break;
Now, to your question: you are reading a char, meaning it will only take the first letter you input. Use a string instead if you want to be able to read words too:
string slction;
cin >> slction;
PD: remember to change the case 'M' and other options' quotes to double quotes (for strings)
PD2: you can't use switch with strings, so you will have to use if/else blocks
With what was said in the first answer, additionally you could use #include <cctype> toupper() function to remove extra cases. As well as validate your input with if statements.
example validation function:
char isValid(char &selection){
std::cin >> selection;
selection = toupper(selection); // ctype.h for toupper changes all to uppercase characters
//checks to see if more than 1 character is inputed
if (std::cin.get() != '\n'){
std::cin.ignore(256, '\n'); //ignores 256 chars until newline('\n')
std::cin.clear(); // clears the input
selection = '\0'; // sets selection to null
}
return selection;
}
DEMO
My first program in C++ is a command line survival game. I have a switch statement in a while loop, but it always goes through once and runs the default choice before getting the users input. Here's the relevant code:
int menu() {
while (true) {
char choice = getChoice();
switch(choice) {
case 'p':
{
system("clear");
Arena arena(player, difficulty);
arena.play();
}
break;
case 'u':
{
system("clear");
player.save();
player.init();
}
break;
case 'd':
{
system("clear");
changeDifficulty();
}
break;
case 'q':
{
system("clear");
return 0; // return menu(); in main()
}
default:
{
system("clear");
cout << nInvalid option! Press a key to choose: p, u, s, or q\n\n";
break;
}
}
}
}
getChoice Function
char getChoice() {
cout << " Main Menu\n";
cout << "---------------------\n";
cout << "p - play game" << endl;
cout << "u - change user" << endl;
cout << "d - change difficulty" << endl;
cout << "q - quit\n" << endl;
char choice = getchar();
return choice;
}
Everything works fine after it goes through once and runs the code from the default option. Here's what I get every time the program re-enters this loop:
Invalid option! Press a key to choose: p, u, s, or q
Main Menu
---------------------
p - play game
u - change user
d - change difficulty
q - quit
Thanks for any help in advance!
Assuming you use the standard getchar function.
The problem is most likely that when you enter your "choice" you enter the 'p' (for example) and then press the Enter key. That Enter key will also be in the input as a newline '\n'. So the next time you call getChoice (and it calls getchar) you read that newline.
There are basically four ways to solve it:
The C way, using scanf instead of getchar, and ask scanf to read and discard leading whitespace (like newlines):
char choice;
scanf(" %c", &choice);
// Note space in front of the %c, which tells scanf to discard leading whitespace
Read the character, and then read and discard everything else until the newline.
Read the whole line into a string, and the parse out the character.
Use std::cin and the normal formatted input operator >>, as that will skip leading whitespace.
I really recommend the last (number 4) method.
I have a do while loop which consists of two switch statements, some output code and some nested while loops to check for input errors. The thing is I want to break the switch statement when the user inputs 'Q' for quit and skip the rest of the code. So I've essentially got two problems.
If i use a do while, then it turns into being a return 0 and a boolean flag while(true) which logically goes against itself.
if i drop the do while and only use return 0, the code can't be executed multiple times.
I've come to terms with this being a flow problem rather than a syntax problem and was wondering how I should structure the flow to make it "clean code".
A quick example:
do {
char answer;
cout << "Type answer: ";
cin >> answer;
switch (answer) {
case A:
cout << "hello";
break;
case B:
cout << "more weird output";
break;
case Q:
cout << "Goodbye";
return 0;
}
cout << "more useless output that I want to skip";
cout << "how does this even work";
} while (run);
Here I've a return 0 which completely negates the need for a while(run) flag. This is bad coding practice I've been told, so I was wondering how one would go about structuring this in a good manner?
Here I think i fixed the code. Make sure you are typing a capital Q not lowercase. Also you forgot ' ' around your chars. Your logic was right - just small errors :) Goodluck!
#include <iostream>
using namespace std;
int
main ()
{
bool run = true;
do
{
char answer;
cout << "Type answer: ";
cin >> answer;
switch (answer)
{
case 'A':
cout << "hello";
break;
case 'B':
cout << "more weird output";
break;
case 'Q':
cout << "Goodbye";
return 0;
}
cout << "more useless output that I want to skip";
cout << "how does this even work";
}while (run);
return 0;
}
Look at this code please:
char o,t; cin >> o >> t;
switch (o,t)
{
case 's','g': cout << "Finish"; break;
default: cout << "Nothing";
}
as you can see switch is set for two values, but in case command I can not check for both of them at the same time. What should I do? is there any way?
it's not proper syntax use instead
case 's':
case 'g':
cout << "Finish"; break;
You can't switch on multiple values in C++.
switch (o,t)
uses the comma operator (it looks a lot like a pair would in some other languages, but it isn't).
The comma operator evaluates its left operand (o), ignores the value of that, and then returns the value of its right operand (t).
In other words, your switch only looks at t.
There is no way around this.
Your particular case is better written as
if (o == 's' && t == 'g')
{
cout << "Finish";
}
else
{
cout << "Nothing";
}
You cannot do switch for two expressions at the same time. The switch part only compiles because there is a comma operator (which simply evaluates to the second value, in this case t).
Use plain old if statements.
char o,t; cin >> o >> t;
switch (o,t)
{
case 's':
case 'g': cout << "Finish"; break;
default: cout << "Nothing";
}
In switch when matched case is found, all operator after that are executed. That's why you should write break; operator after case-es to exit switch. So if you want to do the same in several cases you should just put them one after another.
You have some syntax error, the correct code is
char o,t; cin >> o >> t;
switch (o)
{
case 's':case 'g': cout << "Finish"; break;
default: cout << "Nothing";
}
switch (t)
{
case 's':case 'g': cout << "Finish"; break;
default: cout << "Nothing";
}