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";
}
Related
Basically I want to accept a particular character from a user and then using a switch case it passes the string related with that character case to another function .for eg.
case i:strcpy(str,"ice-cream");
other_function(str);
break;
If any default character got printed by the user then it should print default statement and again take character from user and check its case. I did this with goto, but is there any other option available to avoid or replace goto in this code.
p:
{
cout<<"Choose account type:-\n"<<"Enter\ns :-saving\nc :-current\nf :-fixed\nr :-recurring"<<endl;
char c;
cin>>c;
switch(c)
{
char t[20];
case 's':
strcpy(t,"saving");
a[i].setype(t);
break;
case 'c':
strcpy(t,"current");
a[i].setype(t);
break;
case 'f':
strcpy(t,"fixed");
a[i].setype(t);
break;
case 'r':
strcpy(t,"reccurring");
a[i].setype(t);
break;
default:
cout<<"Enter valid account type"<<endl;
goto p;
}
}
The whole switch should be hived off into a function, and its return value used to determine what happens to the loop next.
while (true) {
std::cout << "Choose account type:\n" << std::flush;
char c;
if (cin >> c)
{
const bool result = HandleUserInput(a[i], c);
if (result)
break;
else
std::cout << "Enter valid account type\n";
}
else
{
// Input error - you'll want to do something about that
}
}
And:
// Given a character representing an account type, sets
// the type of 'account' as appropriate. Returns false
// on failure.
bool HandleUserInput(Account& account, const char c)
{
switch (c)
{
case 's':
a[i].setype("saving");
return true;
case 'c':
a[i].setype("current");
return true;
case 'f':
a[i].setype("fixed");
return true;
case 'r':
a[i].setype("recurring");
return true;
default:
return false;
}
}
(Notice how I got rid of the strcpy, which doesn't appear to be necessary? Depends what setype [which is misspelled] does I suppose. Also, for a bonus point, consider using a map instead of the switch, if you don't care about a bit of a performance hit.)
Bathsheba's suggestion is a valid alternative, though I suggest that a return will look much clearer inside a switch than will a continue, since the latter has meaning within other kinds of control flow statements, whereas the former never does.
Also note that, if you decide not to use a function for some good reason, there's actually nothing particularly wrong with your goto, and don't let the cargo cultists tell you otherwise!
Yes there is. Since continue doesn't have a direct meaning in a switch block (cf. break), the presence of the former will apply to an appropriate outer loop control structure.
So something on the lines of
do {
// your code here, starting with "Choose account type".
...
default:
std::cout << "Enter valid account type" << std::endl;
continue; // back to the start of the do loop
} // close the switch
break; // fall out of the loop
} while (true);
will do it, and is fairly idiomatic C++.
Use a boolean flag:
bool isInputSuccessful = false;
while (!isInputSuccessful)
{
cout<<"Choose account type:-\n";
char c;
cin>>c;
isInputSuccessful = true;
switch(c)
{
char t[20];
case 's':strcpy(t,"saving");
a[i].setype(t);
break;
case 'c':strcpy(t,"current");
a[i].setype(t);
break;
case 'f':strcpy(t,"fixed");
a[i].setype(t);
break;
case 'r':strcpy(t,"reccurring");
a[i].setype(t);
break;
default:cout<<"Enter valid account type"<<endl;
isInputSuccessful = false;
}
}
Before inputting from the user, this code sets the success flag to true, and if unsuccessful, returns it to false.
Alternatively, it could just set it to true in each successful case.
I suggest dividing your code into a few functions. That will make it is easier to understand what each function is doing and how it is doing.
bool isValidAccountType(char c)
{
return ( c == 's' || c == 'c' || c == 'f' || c == 'r');
}
char getAccountType()
{
char c;
cout<<"Choose account type:-\n"<<"Enter\ns :-saving\nc :-current\nf :-fixed\nr :-recurring"<<endl;
while ( cin >> c )
{
if ( isValidAccountType(c) )
{
return c;
}
cout<<"Enter valid account type"<<endl;
}
// Wasn't able to get input.
// Exit out of the program.
exit(0);
}
void processAccount(char c)
{
char t[20];
switch(c)
{
case 's':strcpy(t,"saving");
a[i].setype(t);
break;
case 'c':strcpy(t,"current");
a[i].setype(t);
break;
case 'f':strcpy(t,"fixed");
a[i].setype(t);
break;
case 'r':strcpy(t,"reccurring");
a[i].setype(t);
break;
default:cout<<"Invalid account type"<<endl;
return;
}
// Rest of the function.
}
Use the following in main.
char c = getAccountType();
processAccount(c);
If you put this code into a function, you can use a return statement to exit the loop:
const char* enter() {
for (;;) {
std::cout << "Choose account type: ";
char ch;
std::cin >> ch;
switch(ch) {
case 's': return "saving";
case 'c': return "current";
case 'f': return "fixed";
case 'r': return "recurring";
}
std::cout << "Invalid input.\n";
}
}
Now you can call this function and use its result:
char t[20];
strcpy(t, enter());
a[i].set_type(t);
While all the other examples are very interesting, I usually stay away from true in the loop condition wherever it is possible.
In this case it would be correct to move the handling of the cases into a function by itself and use the returning result of the function to continue the actions.
First declare some predefined return results.
enum class Action_Result
{
Ok,
Error,
Invalid_account,
Quit
/*...*/
};
Next make the function return the predefined results. (Notice that instead of break in the case, return is used to break out the function and also return the action result.
Action_Result handle_account_type(char c /*...*/)
{
switch (c)
{
char t[20];
case 's':
strcpy(t, "saving");
a[i].setype(t);
return Action_Result::Ok;
case 'c':
strcpy(t, "current");
a[i].setype(t);
return Action_Result::Ok;
case 'f':
strcpy(t, "fixed");
a[i].setype(t);
return Action_Result::Ok;
case 'r':
strcpy(t, "reccurring");
a[i].setype(t);
return Action_Result::Ok;
default:
return Action_Result::Invalid_account;
}
}
Then in the main loop we can make a decision based on the result of the handling function. Notice how the loop condition is now easy to understand, why the loop will continue to execute, and when it will stop looping. Also all the input and output is in the main function, separate from the actions (adhering better to the Single Responsibility Principle) .
int main()
{
Action_Result account_handled_result = Action_Result::Error;
do
{
cout << "Choose account type:-\n"
<< "Enter\ns :-saving\nc :-current\nf :-fixed\nr :-recurring"
<< endl;
char c;
if (cin >> c)
{
if (c == 'q')
account_handled_result = Action_Result::Quit;
else
account_handled_result = handle_account_type(c);
}
else
{
account_handled_result = Action_Result::Error;
}
if (account_handled_result == Action_Result::Invalid_account)
cout << "Enter valid account type" << endl;
} while (account_handled_result != Action_Result::Quit);
}
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
I am using Windows 7 Ultimate. I am new to C++. Following is my exercise for switch statement.
void GradeBook::inputGrades()
{
int grade;
cout << "Enter Grade: " << endl;
while((grade=cin.get()) != EOF)
{
switch(grade)
{
case 'A':
case 'a':
aCount++;
break;
case 'B':
case 'b':
bCount++;
break;
case 'C':
case'c':
cCount++;
break;
case 'd':
case 'D':
dCount++;
break;
case 'F':
case 'f':
fCount++;
break;
case '\n':
case ' ':
case '\t':
break;
default:
cout << "Incorrect data. Re Enter" << endl;
break;
}
}
}
I run this inside netbeans, and I pressed all the combinations ctrl+c , ctrl+z, ctrl+d but it is not ending!! Why is that? Have I done something wrong? Please help!!
An EOF character is Ctrl+Z followed by a newline character on Windows platforms.
Presumably that will be the same for the console within Netbeans.
cin.get() is pretty low level. The code should use a higher-level interface. It's supposed to read a character at a time, so write it that way:
char grade;
while (cin >> grade)
The stream extractor will fail at end of file, and that will make the while loop terminate.
I may be over looking something but is there a simple way in C++ to group cases together instead of writing them out individually? I remember in basic I could just do:
SELECT CASE Answer
CASE 1, 2, 3, 4
Example in C++ (For those that need it):
#include <iostream.h>
#include <stdio.h>
int main()
{
int Answer;
cout << "How many cars do you have?";
cin >> Answer;
switch (Answer)
{
case 1:
case 2:
case 3:
case 4:
cout << "You need more cars. ";
break;
case 5:
case 6:
case 7:
case 8:
cout << "Now you need a house. ";
break;
default:
cout << "What are you? A peace-loving hippie freak? ";
}
cout << "\nPress ENTER to continue... " << endl;
getchar();
return 0;
}
AFAIK all you can do is omit the returns to make things more compact in C++:
switch(Answer)
{
case 1: case 2: case 3: case 4:
cout << "You need more cars.";
break;
...
}
(You could remove the other returns as well, of course.)
Sure you can.
You can use case x ... y for the range
Example:
#include <iostream.h>
#include <stdio.h>
int main()
{
int Answer;
cout << "How many cars do you have?";
cin >> Answer;
switch (Answer)
{
case 1 ... 4:
cout << "You need more cars. ";
break;
case 5 ... 8:
cout << "Now you need a house. ";
break;
default:
cout << "What are you? A peace-loving hippie freak? ";
}
cout << "\nPress ENTER to continue... " << endl;
getchar();
return 0;
}
Make sure you have "-std=c++0x" flag enabled within your compiler
No, but you can with an if-else if-else chain which achieves the same result:
if (answer >= 1 && answer <= 4)
cout << "You need more cars.";
else if (answer <= 8)
cout << "Now you need a house.";
else
cout << "What are you? A peace-loving hippie freak?";
You may also want to handle the case of 0 cars and then also the unexpected case of a negative number of cars probably by throwing an exception.
PS: I've renamed Answer to answer as it's considered bad style to start variables with an uppercase letter.
As a side note, scripting languages such as Python allow for the nice if answer in [1, 2, 3, 4] syntax which is a flexible way of achieving what you want.
You can't remove keyword case. But your example can be written shorter like this:
switch ((Answer - 1) / 4)
{
case 0:
cout << "You need more cars.";
break;
case 1:
cout << "Now you need a house.";
break;
default:
cout << "What are you? A peace-loving hippie freak?";
}
You can use like this:
case 4: case 2:
{
//code ...
}
For use 4 or 2 switch case.
Your example is as concise as it gets with the switch construct.
If you're willing to go the way of the preprocessor abuse, Boost.Preprocessor can help you.
#include <boost/preprocessor/seq/for_each.hpp>
#define CASE_case(ign, ign2, n) case n:
#define CASES(seq) \
BOOST_PP_SEQ_FOR_EACH(CASE_case, ~, seq)
CASES((1)(3)(15)(13))
Running this through gcc with -E -P to only run the preprocessor, the expansion of CASES gives:
case 1: case 3: case 15: case 13:
Note that this probably wouldn't pass a code review (wouldn't where I work!) so I recommend it be constrained to personal use.
It should also be possible to create a CASE_RANGE(1,5) macro to expand to
case 1: case 2: case 3: case 4: case 5:
for you as well.
gcc has a so-called "case range" extension:
http://gcc.gnu.org/onlinedocs/gcc-4.2.4/gcc/Case-Ranges.html#Case-Ranges
I used to use this when I was only using gcc. Not much to say about it really -- it does sort of what you want, though only for ranges of values.
The biggest problem with this is that only gcc supports it; this may or may not be a problem for you.
(I suspect that for your example an if statement would be a more natural fit.)
No, unless you want to break compatibility and your compiler supports it.
#include <stdio.h>
int n = 2;
int main()
{
switch(n)
{
case 0: goto _4;break;
case 1: goto _4;break;
case 2: goto _4;break;
case 3: goto _4;break;
case 4:
_4:
printf("Funny and easy!\n");
break;
default:
printf("Search on StackOverflow!\n");
break;
}
}
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) {
...