First, I realize that from a performance perspective, the design of this switch statement is slow because cout is being called several times in certain cases. That aside, is this style of writing a switch statement not good coding practice. In other words, would it be better to handle each case individually and break or is the fall-through better?
int main(void)
{
int number;
cout << "Enter a number between 1 and 10 and I will display its Roman numeral equivalent." << endl
<< "> ";
cin >> number;
cout << "Roman numeral: ";
switch (number)
{
case 3:
cout << "I";
case 2:
cout << "I";
case 1:
cout << "I";
break;
case 4:
cout << "I";
case 5:
cout << "V";
break;
case 6:
cout << "VI";
break;
case 7:
cout << "VII";
break;
case 8:
cout << "VIII";
break;
case 9:
cout << "I";
case 10:
cout << "X";
break;
default:
cout << "Error!\nYou did not enter a number between 1 and 10";
}
cout << endl;
return 0;
}
Switch statements aren't slow, they're usually optimised to jump-tables by the compiler. And if you're sure that switch statement works as expected, it's fine and is a pretty cool way of doing it.
That said, you'd have the same number of cases if you handled each one individually. If that's all you're doing, I'd probably change it to handle each one seperately and not do fall through. It's more comprehendable and easily maintained that way:
switch (number)
{
case 1:
cout << "I";
break;
case 2:
cout << "II";
break;
case 3:
cout << "III";
break;
case 4:
cout << "IV";
break;
case 5:
cout << "V";
break;
case 6:
cout << "VI";
break;
case 7:
cout << "VII";
break;
case 8:
cout << "VIII";
break;
case 9:
cout << "IX";
break;
case 10:
cout << "X";
break;
default:
cout << "Error!\nYou did not enter a number between 1 and 10";
}
And like #paxdiablo suggested, to enhance readability you can put the case, statement, and break all on the same line if it looks better to you:
case 1: cout << "I"; break;
case 2: cout << "II"; break;
// etc.
It's such a simple case, it's hard to say it's really "bad." I've heard differing opinions on lettings cases fall through into other cases. And I'm sure at some point, we've all done that. (I usually document it quite clearly with something like /* FALL-THROUGH */ so the next person reading the code knows I meant to do that.)
I think a more complex example would demonstrate it's not such a great idea. But not really because a fall-through itself is a bad thing. But because a better design wouldn't warrant it. In object oriented design, a case statement might indicate that you've got a "code smell" -- that you're not letting the object do what it needs to based on type rather than based on some other piece of information.
Now, if someone really wanted to get picky about your admittedly simple example, one could say you're mixing controller, model, and view together in bad ways. Your controller should simply get the input. Your model would have better ways of obtaining the alternate representation of the input (a map, or heck, a case statement, I dunno), and your view logic would not be scattered in and around your controller logic. By actually adhering to some other design concepts, the switch statement might vanish entirely. That might happen with other examples, too.
In short, I think if your design is sound, you might find that if a switch statement IS even in fact necessary, then the concern about a fall-through case statement isn't a big deal.
I tend not to use that style since it's often difficult to figure out the flow of control at a single glance. This is one reason why goto is generally considered a bad idea (though some people take that as gospel without understanding why - it's actually quite handy in some circumstances provided it doesn't render the code unreadable).
In other words, I prefer each case to be independent. If they have commonality, I will tend to break that out into separate functions and call those functions from each case.
That doesn't cover situations where the code is identical for different cases, where I just use something like (pseudo-code, obviously):
case 1: case 2: case 3:
print "It's one, two or three"
For your specific use case, I would probably just use a table lookup like:
char *roman[] = {"I", "II", "III", "IV", ... "X"};
if ((n < 1) || (n > 10))
cout << "Urk! I only have ten fingers!";
else
cout << roman[n-1];
just to keep the (source) code compact.
Using the Break for each case should be the perferred option. Using "Fall-Through" will move on to the code for the next case, which could cause errors and hinder performance.
You are right in that calling the '<<'-operator several times incurs a certain amount of overhead. However, you're talking about two statements here so this is probably not the point to optimize.
If you want to optimize the code, why not use a static array of strings containing the roman numbers? Like roman[0] = "I", roman[1] = "II", etc. I doubt this representation will cost you more memory than the above function and you get rid of the bloated switch statement.
That is very clever, and this will be plenty fast. But if you want to improve performance ...
In each switch statement, add the string you are couting to a running string buffer. Then, after the switch statement, cout the buffer.
This is a little confusing to read/understand. Simply handling each of the 10 cases individually would be simpler and would perform better (though using a minuscule amount more memory).
Switch statements can be optimized into jump tables by the compiler, so they're not always slow. And they're definitely better than writing a bunch of if - else if statements. I personally like fall through because it allows you to do some cool stuff in certain cases without having to repeat code; but in general, they are frowned upon because they can be harder to understand than handling each case individually.
As for your example, if you're worried about multiple calls to cout, you can always store the intermediate strings in a stringstream and print the final string. However, output to cout is buffered, so I don't know whether this will have any significant performance improvement.
#include <iostream>
#include <ios>
#include <sstream>
int main(void)
{
using namespace std;
int number = -1;
cout << "Enter a number between 1 and 10 and I will display its Roman numeral equivalent." << endl
<< "> ";
cin >> number;
ostringstream oss( "Roman numeral: ", ios_base::ate );
switch (number)
{
case 3:
oss << "I";
case 2:
oss << "I";
case 1:
oss << "I";
break;
case 4:
oss << "I";
case 5:
oss << "V";
break;
case 6:
oss << "VI";
break;
case 7:
oss << "VII";
break;
case 8:
oss << "VIII";
break;
case 9:
oss << "I";
case 10:
oss << "X";
break;
default:
cout << "Error!\nYou did not enter a number between 1 and 10";
return -1;
}
cout << oss.str() << endl;
return 0;
}
Related
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;
}
I'm using a switch statement to process through some code, which I will create a function in my main to call. I'm having trouble with the switch quantity with my switch statement. Also, how would I create a function for these 10 cases? Very confused, any help greatly appreciated! Thanks! Here is my current code:
#include <iostream>
using namespace std;
void constitution(); // the function that will call my amendments in my main function
// how will i create this will 10 possible amendments to choose from?
// There are 4 pirates and they will vote either yes or no,
int main()
{
cout << "Below is a list of the 10 amendments that the two pirates will vote on according to the ships constitution" << endl;
string amendments = 0;
cin >> amendments; // selecting the amendment
switch (amendments)
{
// for outputting the amendment(s) voted on, which will
// be passed on to a function in main to call
case 1: cout << "What does the fox say? Whatever WE tell it to"; //case 1-10 are the 10 amendments to be voted on
break;
case 2: cout << "From now on the annual Cinco de Mayo party will be held on March 8th ";
break;
case 3: cout << "Beginning this year, sharks shall have a week dedicated to us";
break;
case 4: cout << "Pirates are now allowed to talk about fight club";
break;
case 5: cout << "When in Rome, the Romans will do as WE do.";
break;
case 6: cout << "Our mothers will immediately get tattoos that say SON";
break;
case 7: cout << "From now on the President will take our birthdays off.";
break;
case 8: cout << "If we say something costs an arm and a leg, it does";
break;
case 9: cout << "Freemasons are ordered to learn OUR secret handshake.";
break;
case 10: cout << "If a tree falls in the forest and no one is around, it will make a sound only with our permission ";
break;
default: cout << "This won't be used since a amendment will always be voted on, thus never be shown or checked I believe.. (Please correct me) ";
break;
}
return 0;
}
The only thing you need to change is making amendments an integer, as switch expects an int.
int main()
{
cout << "Below is a list of the 10 amendments that the two pirates will vote on according to the ships constitution" << endl;
int amendments = 0;
cin >> amendments; // selecting the amendment
switch (amendments)
{
...
}
If you want to use amendments as a String, I am afraid you are not going to be able to check it via switch. Instead, you should use if/else if statements:
if(amendments == '1') {
...
} else if (amendments == '2') {
...
}
I've been trying to use switch statements to access different functions in my program and when I compile the code it keeps showing up the default option, regardless of what I input. Am I missing something really obvious here?
All the functions (all voids) are declared in the class. Is this maybe because I am implementing the other 'menu' functions underneath this one?
void bookshop::menu_searchtype() {
std::cout << "Welcome to Hal's Book Emporium!\n\n";
std::cout << "You can search for a book by its:\n";
std::cout << "1. Identification number\n";
std::cout << "2. Title\n";
std::cout << "3. Author\n\n";
std::cout << "Which would you like to use?\n\n";
std::cin >> choice_menu;
int menu_searchtype_no;
switch (menu_searchtype_no) {
case '1':
menu_id();
break;
case '2':
menu_title();
break;
case '3':
menu_author();
break;
default:
std::cout << "We seemed to have run into a problem. Please try again\n\n";
break;
}
}
You are reading values into choice_menu and not menu_searchtype_no which you didnt even initialized.
Your case statement looks like you are comparing for characters. Remove quotes (if you are reading integers and choice_menu is of integer type) and that should let you move further.
You never set menu_searchtype_no, so it has an unspecified value. On very rare occasions this may "equal" '1', '2' or '3' (which is 49, 50 or 51 respectively, if you're using ASCII), but far more likely it'll be some random-looking higher value which will trigger the default case.
I guess you meant to write:
switch (choice_menu) {
and
case 1:
etc.
I'm starting to grasp c++ but there is one thing that confuses me and it's using break and select case. I know how to do this but what I would like to understand is why this certain operation happens.
Say if i have
switch (Tasty)
{
case true:
cout << "yum" << endl;
break;
case false:
cout << "erch" << endl;
break;
}
Now that does it correctly and prints out what I want, but if I do
switch (Tasty)
{
case true:
cout << "yum" << endl;
case false:
cout << "erch" << endl;
}
Why does it print both "yum" and "erch"?
The cases in a switch statement are best thought of as labels. After the statement
cout << "yum" << endl;
finishes running, the next one simply starts running,
cout << "erch" << endl;
unless you explicitly break out of the switch statement.
The answers here are good, I just want to give you an example where omitting break is actually useful:
In a case you can't check for multiple values, like 1 || 2 || 3, so if you want to perform the same function for more than one value your option would be to repeat code, something like this:
switch (a)
{
case 1:
Foo();
break;
case 2:
Foo();
break;
case 3:
Foo();
break;
case 4:
Bar();
break;
}
unless you omit the break and you can write:
switch (a)
{
case 1:
case 2:
case 3:
Foo();
break;
case 4:
Bar();
break;
}
Code repetition is something to always be avoided if possible so this actually comes in handy.
If you don't use break keyword, the program will keep executing the following instructions. Sometimes this comes in handy, but most of the times it's just a pain in the ass.
In your case, if Tasty is true, both words will be printed. If false, only the second one.
a break is needed in most case(s) of the switch *unless you specifically want the switch to go into other cases.
The switch moves down line by line regardless of break or not.
Some languages like C# will automatically catch these and prevent compilation. C++ will let you call the shots however, so you need to be careful to add those in.
switch(Tasty)
{
case true:
cout << "yum" ;
break; /*<--- don't forget the break!*/
case false:
cout << "not yum";
break;
}
In switch statement cases are executing up until one is true (and then next are executing also unless you break from switch) or until all conditions have been tested.
Examine this example:
int Tasty = 1;
switch (Tasty)
{
case 1:
qDebug() << "yum" << endl;
case 2:
qDebug() << "erch" << endl;
}
output:
yum
erch
int Tasty = 1;
switch (Tasty)
{
case 2:
qDebug() << "yum" << endl;
case 1:
qDebug() << "erch" << endl;
}
output:
erch
According to Cplusplus.com
"
It works in the following way: switch evaluates expression and checks if it is equivalent to constant1; if it is, it executes group-of-statements-1 until it finds the break statement. When it finds this break statement, the program jumps to the end of the entire switch statement (the closing brace)."
So, if you don't put break statement, it will automatically go to next case and it will keep going till it finds break statement. Follow this link for more info.
http://www.cplusplus.com/doc/tutorial/control/
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;
}
}