As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
How could I explain how and when to use an if-statement vs. a switch statement in a "Choose Your Own Adventure" game?
The game is basically structured that if you put in a certain answer, it changes the flow or direction of the game. I've usually used if-statements with functions, but is that the most efficient and simple way to teach?
Thanks!
Edit: Wow, thank you SO much for so many great answers!! Just one last note: if you were a 13-year-old trying to grasp this concept without any previous knowledge of programming, how would you try to go about to understand it? Seriously, thanks so much for the help!!
There are (give or take) five different solutions to "I've received this input, what do I do now".
If/else if/else ... chain. Advantage is that you can use any expression that can be made into true or false. Disadvantage is that it can get pretty messy when you have a long chain of them.
Switch - great for "there are lots of almost similar things to do". Drawback is that the case labels have to be integer values (or char values, but not strings, floating point values, etc).
A table which makes the long if/else into a much simpler if(table[index].something) ...
Function pointers - sort of a table pointer variant - store a pointer to the function that does whatever you want to do if you move in that direction.
Objects using virtual functions. Again, a variant on the table solution, but instead of storing function pointers, we store objects with some member function that we can use to "do whatever you need to do".
The correct solution in this case is perhaps a combination/variation on one of the latter 3 - in my opinion, at least.
In this very scenario you've described an if statement is pretty much your best option since the code needs to compare an answer provided by the user with some pre-defined options.
Those options will most likely be strings. switch statements in C++ cannot work on strings. Thus a series of if statements will probably be simpler.
A switch statement can be used when the answer only consists of a number or a single character.
For example, the code piece for the game's main menu could look like this:
Console output:
Please select an action:
1) Start a new game.
2) Go to options screen.
3) Quit game.
code:
int userChoice = getUserInput();
switch(userChoice){
case START_NEW_GAME: //1
startGame(); break;
case OPTIONS: //2
showOptions(); break;
case QUIT: //3
exit(); break;
}
Use a switch statement when you're identifying cases of numeric or ordinal values.
switch (number)
{
case 1: DoSomething();
break;
case 2: DoSomethingElse();
break;
}
Use if, elseif and else for more complex conditions, like numeric ranges.
if (number > 0 && number <= 100)
{
DoSomething();
}
else if (number > 100 && number <= 1000)
{
DoSomethingElse()
}
else
{
NotifyOutOfRange();
}
switch statements are for speed. That's why they are only numeric. The compiler will attempt to make a lookup table for non-sparse (i.e. contiguous) value ranges which can improve performance significantly when the code is constantly being executed. This is because it only needs to do 1 comparison for a contiguous range to determine what piece of code to execute.
switch statements potentially can cause hard to find bugs since at the end of each case you need to specify a break or the execution will fall through to the next case.
if/else if/else statements are for more general use. They are in general, slower than an equivalent switch statement if there are many comparisons against the same value. However if that if chain of statements is not executed a lot and the chain is not that long, the performance improvement is negligible.
For more general usage, if is the way to go. In a CYOAG, you will not be needing speed. The slowest part of the game is the user.
To explain this to a 13 year old:
If you think that you will be executing a comparison on a single
integer (whole number) value over 1,000,000 or more times all at once and you need
it to be done as quickly as possible, use a switch statement.
Otherwise, doesn't matter. Just be careful when using a switch, because if you
don't have a break at the end of each case you will be scratching you head
trying to figure out what just happend? when two or more cases are executed.
You can use switch statements if you have too many "else if" statements :)
More seriously, if a player has many different choices (like picking from 26 different options (a-z), then switch is the way to go).
Well, you can't really put strings into switch/case. That leaves you with if. or you'll need to implement parser that reads strings, maps them to some enum type, and then uses said enum within switch/case.
However a better (more extensible) way would be to use map of function callbacks.
Something like this:
#include <map>
#include <string>
#include <iostream>
typedef void(*ActionCallback)();
typedef std::map<std::string, ActionCallback> ActionMap;
static bool running = true;
void leftAction(){
std::cout << "\"left\" entered" << std::endl;
}
void rightAction(){
std::cout << "\"right\" entered" << std::endl;
}
void quitAction(){
std::cout << "game terminated" << std::endl;
running = false;
}
int main(int argc, char** argv){
ActionMap actionMap;
actionMap["left"] = leftAction;
actionMap["right"] = leftAction;
actionMap["quit"] = quitAction;
while(running){
std::string command;
std::cout << "enter command. Enter \"quit\" to close" << std::endl;
std::cin >> command;
ActionMap::iterator found = actionMap.find(command);
if (found == actionMap.end())
std::cout << "unknown command " << command << std::endl;
else
(*found->second)();
}
return 0;
}
The big advantage of this approach is that you can change commands at runtime. Add new commands, remove them, etc. You could even go a bit further and add lisp/python/lua binding and make it even more extensible.
Related
I am currently reading "A tour of C++" from Bjarne Stroustup, and I saw the following example:
bool accept()
{
cout << "Do you want to proceed (y or n)?\n"; // write question
char answer = 0; // initialize to a value that will not appear on input
cin >> answer; // read answer
if (answer == 'y')
return true;
return false;
}
I thought using multiple return statements wasn't recommended. Wouldn't it be better practice in this case to create a bool variable, initialize it to 0 and then modify it in the if condition, to finally return the value of this boolean variable? Or I am just making things up.
No, you're not entirely making things up, and no there is no recommendation of such that I know of.
Snippet According to your recommendation:
Int accept()
{
Int result=0;
cout << "Do you want to proceed (y or n)?\n"; // write question
char answer = 0; // initialize to a value that will not appear on input
cin >> answer; // read answer
if (answer != 'y')
result=1;
return result;
}
Looking closer you will notice no difference between the snippet above and the one you found in the book, they book use validation, the difference is the data-type used.
Now, it will be more easy to use a boolean if you need to simple use the function accept like below:
if(accept()) /*do something*/;
Rather than:
if(accept()==0) /*do something*/
Either way, you're good to go.
Another thing to consider is the size of your data-type, boolean is just 1bit while int is 4bytes so comparison time complexity will obviously be different but you will most likely never notice the difference.
Edit:
In java boolean is 1bit as said above but since it's c++, because of the issue of 1bit not addressable, it only make more sense to make it 8bit and then it can be given an address in the memory.
So, in C++ boolean is also 1byte or 8bit, and so the comparison time difference is not a thing to consider.
Both approaches are possible, but you will usually see the version using multiple return values. Take a look how this part of the code works:
if (answer == 'y')
return true;
return false;
At first you may see two branches in which the executed code can go, based on the value of answer. First one is connected with y choice, and the other one with anything else. This code could also look like this:
if (answer == 'y')
return true;
else
return false;
But it makes the program a bit more complicated - there is one more jmp instruction in assembly code, which means that the code is just a bit more complex, but its functionality is exactly the same as of the previous version.
Now, we can add the bool variable and let's see how it will look like:
bool is_answer_positive = false;
if (answer == 'y')
is_answer_positive = true;
else // we can get rid of this statement
is_answer_positive = false; // as we have defined variable earlier
return is_answer_positive;
The first thing which makes the code a bit more complex is a new variable, which does not add any vital value to the code, I would say it makes it only more complicated. This is the first instruction which makes the code bigger, but not better. Then if/else works similarly to the second version, but you also assign some values to the is_answer_positive, which also makes the code bigger, but not better. At the end, you return the value you got from if/else statement and the code is done. We can get rid of else statement, as is_answer_positive was initialized to be false, but this is still not the best solution.
Comparing those three possibilities: first version is the most used one, it is clear and probably the simplest, second version adds extra jump, which is unnecessary at all, and the third version adds extra variable, which makes the code a bit harder to read.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 6 years ago.
Improve this question
I am very new to C++. My objective is to write the following logic:
if a = yes then print "ok", else return 0
Here is my code so far:
int a;
cin>>a;
if (a = "Yes") { // Error right here
cout<< "ok"; << endl;
}else{
return 0;
}
First of all, what do you want your program to do?
You need to distinguish assignment and equal to operator.
Please note that you need to understand the basics before proceeding to perform conditional statements.
A reasonable program should go like this:
int a;
cin>>a;
if (a == 5) { // 5 is an integer
cout<< "You entered 5!" << endl; // no semicolon after "
}
return 0; // must be out of the else statement
= assigns things.
Use == to compare, however you are comparing an int with a string.
If you are not careful, you compare the address of a char * with a number when dealing with strings.
Use a std::string instead.
#include <string>
//.... some context I presume
std::string a;
cin >> a;
if (a == "Yes") { // Error right here
cout<< "ok"; << endl;
}else{
return 0;
}
There are multiple errors in this code.
You need to use the comparison operator in your condition. This is denoted by the double equal sign "==". Your code is using assignment "=" which tries to assign the value "Yes" to the variable a. This is a common error in C/C++ so you need to be careful whenever you compare things.
The other error is that you have declared the variable a to be an integer, so you will get a type mismatch error when you try to compile because "Yes" is a string.
Your code is incorrect in terms of data types. You have a variable 'a' of type int which you are comparing to string "yes". Try to see it from a logical point of view; you can compare:
2 numbers (for example, 2 is greater than 1)
2 strings (for example, "food" is not the same word as "cat")
Etc...
In your case, you are comparing a number inputted(let's assume 5) to a word "yes". When you try to input a letter for var a, you will get a compilation error. Therefore, simply change the following:
string a;
Another problem with your code is when the if-then loop checks the condition; a comparison operator is 2 equal signs next to each other instead of a single equal sign. A single equal sign assigns the item on the right to the item on the left. For example, in:
int num = 5;
The variable num is assigned 5. But you want to make a comparison, not assign the variable its own condition!
Your loop is always true because you set the variable to the condition it is supposed to meet. You also need to do the following:
if (a == "yes")
This compares the value stored in var a to the value on the right side of the == .
Just some advice, I would recommend you to get some good books on c++. Search them online. You can also take online programming courses on edx, course record, etc... . There are a lot of other free learning resources online too which you can make use of. You may also want to dive into a simpler programming language; I would recommend scratch. It gives you a very basic idea about programming and can be done in less than a week.
** Note that I feel this is the simplest way; however, you can also set type of a to a char, accept input and then convert it back to a string. Good luck!
So I have a general question about the do/while loop. I'm learning C++ and I know that you can write something like that:
do{
....
} while(a<10 && cout<<"message");
The point is, that i know this is possible in c++, but do we really do that? I mean, the "cout" thing inside the while?
Your while loop is equivalent to
do {
...
cout << "message";
while(a < 10 && cout);
because cout << ... returns cout again.
Then, the question is, what does it mean to write statements like
while( cout );
or
if (cout) ...
The cout object has a conversion to boolean which is used here. It's implementation is checking !fail(), so
if (cout) ...
is equivalent to
if (!cout.fail()) ...
and
do { ... }
while(cout);
is equivalent to
do { ... }
while(!cout.fail());
Finally, fail returns true if the stream failed to produce output.
The fact is some people do this (i.e. run a function as part of the condition evaluation). It makes sense in a shell script, but if you're not using a shell script, it's sometimes not clear what the return value is for some functions. I couldn't tell you what cout<<"message" returns offhand, but I do know that if you write it inside the loop body, it would do what I want, and it would 'throw away' the return value if I don't use it.
To write cleaner code that others including your future-self can understand, I would only evaluate conditions which obviously return true/false as opposed to "0/not-0", or "0/1" which may different in different languages.
Bottom line is, let the compiler make things more efficient for you, and code for other people, not for the compiler.
If you want to perform the output after testing the condition, you would need to either do that or add another condition test inside the loop and maintain both of them, which is a bug waiting to happen.
do {
if (a < 10)
cout << "message";
} while (a < 10);
It's rare to see cout << by itself in any condition though, as you can usually assume that it will succeed unless your machine is on fire.
On the other hand the extraction operator, >>, usually belongs inside a condition;
while (cin >> x)
is idiomatic C++.
I'm trying to solve this problem as few lines of code as possible.
problem statement:
someone managed to say hello if several letters can be deleted from the typed word so that it resulted in the word "hello"... I'm testing if he could or not
#include <iostream>
int main() {
char c;
int i=0;
while(i!=5 && (cin>>c) && c!='\n'){
if(c=="hello"[i])
i++;
}
cout<<((i==5)?"YES":"NO");
}
There's a bug when it should print "NO". The program waits for more input. I think the loop doesn't finish until i==5 but it never finishes when c=='\n'.
Before you pack your program to minimize the LOC (and I assume that you have a really good reason to care about this because otherwise it is a foolish thing to do) make it right!
Try putting the i != 5 test BEFORE the cin >>c test. Otherwise you read one extra character when you do get a "hello"
Edit: Just to be clear, the code in the question has now been modified to incorporate this suggestion.
You have a while loop there
while(i!=5 && (cin>>c) && c!='\n')
{ ... }
...which you can rewrite for easier debugging. In general, instead of any loop...
while (X)
{ Y }
...you can also write...
while (true)
{
if (!X) break;
Y
}
For your loop, that would be this code:
while (true)
{
if (!(i!=5 && (cin>>c) && c!='\n'))
break;
...
}
Now, I assume you are aware of the short circuit evaluation of the logical AND operator. If not, search the web for that term! With that knowledge, you can rewrite your loop like this:
while (true)
{
if (!(i!=5))
break;
if (!(cin>>c))
break;
if (!(c!='\n'))
break;
...
}
Of course, you can still simplify a few double negations there, but the idea should be clear. This change now allows you to e.g. step through this in a debugger to evaluate each loop exit condition separately. This is important, because the second loop condition also has side effects! In addition, you could e.g. add some debug output that tells you the reason why the loop was exited. Further, for the check that has side effects, you can inspect the intermediate state (or output the state, if you prefer that way), which will give you further insight on the issue.
Lastly, all >> operators on istreams by default skip whitespace, which includes spaces, tabs and newlines, so your last check will never cause the loop to exit. You can tell the stream to not skip whitespace though, if that's what you want. How to do that should be really simple to find out using another websearch. ;)
I'm learning C++ and I encountered 2 different types of writing a piece of code, and I wanted to know what the difference is.
Is there any difference between:
if(z==true)
{
cout << "Yes";
}
else
{
cout << "NO";
}
and:
if(z==true)
cout << "YES";
else
cout << "NO";
Technically no, but one is IMO better practice. If you omit the brace only the next line is executed, as opposed to executing everything within the brace. You can see how a quick change of code could raise problems.
Say you have
if(z==true)
cout << "YES";
else
x = 47;
and you modify it to
else
x = 47;
y = 99;
y = 99; is executed unconditionally. It's best to avoid these gotchas and just use the braces.
No, there is no difference between those two. The {} are only needed if there are multiple statements, but some people argue that always having them reduces the risk for strange bugs if more statements are added later.
This code behaves in the same way. So this is only a stylistic issue.
Many programmers prefer the first since it's more robust. It's easy to change the second one in a way that doesn't work as expected. The {} are necessary if there are multiple statements(or no statement). So changes to the second one can easily result in code where one thinks that a part is conditional/unconditional where it's not. Especially when being sloppy with indentation.
Personally I think if you have a good IDE that can auto format code the risk is small.
There is no difference at all, the first example has a block of code instead of a single statement, its just a block with a single statement in it. The former is generally considered safer to write.