I've read a book by Mark Lee, C++ absolute beginner, and one of the code snippet is :
while(true)
{
cout << description.c_str() << "\n\n";
int response = 0;
do
{
cout << "What would you like to do?\n";
if(enemy)
cout << "1) Attack the evil "
<< enemyName.c_str() << "\n";
else if(!enemy)
cout << " 1) Move to the next room.";
if(treasure)
cout << " 2) Pick up the "
<< treasureName.c_str() << "\n";
cin >> response;
}while(response < 1 || response > 2);
switch(response)
{
case 1 : if(enemy)
{
enemy = !enemy;
cout << "You slay the deadly "
<< enemyName.c_str() << "\n";
}
else if(!enemy)
return;
break;
case 2: treasure = !treasure;
cout << "You pick up the "
<< treasureName.c_str() << "\n";
break;
}
}
I think you can ignore about what this program intention is, but the question is, why the part of "while(true)" is exist ? I think, there are no ways out of the loop, right ? Because, I think the "true" value is always return 1, and the "while(true)" part is same with "while(true == 1)", so this loop is like infinity loop, am I wrong or ? Any help is appreciated.
Yes:
this loop is like infinity loop
You're correct in that while(true) is an instruction to loop forever.
However, there are a few other ways to exit loops:
A return statement will exit the function (and consequently also terminate the loop)
A break statement will exit the closest for, while or switch statement.
A goto statement might cause the code to jump to a label outside the loop
An exit() call will cause the whole program to terminate.
A throw statement will throw an exception that will break out to the nearest appropriate catch statement (which might be outside the loop).
In this case, the return; near the bottom of the loop causes the function to exit.
The break; statements do not cause the loop to stop, because they belong to the switch.
A caveat on the use of goto - many programmers consider it poor style, as it can lead to code that is difficult to follow. There is quite a bit of further discussion on this question. In C++, typically throw is more appropriate for situations where goto might be used.
However, there are situations in pure C where goto can be very useful. This answer provides an excellent overview of why goto is historically considered poor style, and even provides some examples of where it might be appropriate to use goto.
Of course, a good rule for beginners might be "pretend goto doesn't exist". Especially in C++.
If you look closely, there is a
return;
statement in the code. This will exit the loop and the function the loop is in.
(This is worth answering since it has fooled at least one 5,000 reputation user and therefore demonstrates the importance of writing code that is clear).
The return statement is the loop terminator. This will exit the function.
It's buried deep within the function. I'd criticise the code therefore for that style: it's hard to follow and difficult to debug.
The only exit from the while(true){...} is the return statement, which terminates the surrounding function.
I don't know the book, but I've never seen another suggestion of writing if statements this redundant way:
if(enemy)
{ ...
}
else if(!enemy)
{...
}
Redundancy is usually to be avoided since it makes maintenance more difficult.
And I very much dislike:
case 2: treasure = !treasure;
cout << "You pick up the "
<< treasureName.c_str() << "\n";
This will let you pick up the treasure, but you stay in the loop and can select '2' once more, telling you "You pick up the x" once more, but negating variable treasure once more. Hmm, let's hope this isn't a full quote from the book!
Related
Consider:
for(int i = 10; b >= i; i++){
if(i%2 == 0)
cout << "even" << endl;
else
cout << "odd" << endl;
}
for(int i = 10; b >= i; i++){
if(i%2 == 0){
cout << "even" << endl;
}else{
cout << "odd" << endl;
}
}
Both of these code work with the only difference being the curly brackets for the if else statement. When should I use curly brackets and when not?
They're called braces or curly brackets, not to be confused with the "curly arrow" in some languages, ~>.
In C, and by inheritance C++, these are optional on single-line if statements, but as many, many bugs have been created by omitting them you'd be advised to use them as a matter of principle even when they're redundant.
That is a mistake like this is easy to overlook:
if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
goto fail;
goto fail;
Where it seems like that goto is conditional, yet it's not, it just drops through. This is the huge OpenSSL bug that caught everyone by surprise, and if veteran developers can mess it up, so can you.
The second form is the most reliable, least ambiguous, especially when formatted according to typical conventions:
for (int i = 10 ; b >= i;i++) {
if (i%2 == 0) {
cout << "even" << endl;
}
else {
cout << "odd" << endl;
}
}
for is a statement, not a function, so the syntax is for (...) with a space. Functions have no space, like f(...). Omitting the space implies for is a function, which it absolutely is not. The same goes for if, while and so on.
It's worth noting that the original code can actually be reduced to:
for (int i = 10 ; b >= i;i++)
if (i%2 == 0)
cout << "even" << endl;
else
cout << "odd" << endl;
Since that if is a single statement, even with the else clause attached.
Again, this is not advised because the rules of what is and isn't a single statement can be confusing.
Google has a detailed C++ style guide that may help you. In particular, it says that
In general, curly braces are not required for single-line statements, but they are allowed if you like them; conditional or loop statements with complex conditions or statements may be more readable with curly braces. Some projects require that an if must always have an accompanying brace.
If the 'if', 'else' or 'for' structures have only one statement inside them, you can decide not to use the curly brackets. However, I would recommend to use them in order to improve the code readability.
I made a simple game program, and a requirement calls for a option for the player to undo a number of moves (undo n).
I have the user enter in a command (undo n) and it takes the back half and puts it into an int. Basically, I want the program to stop the user if they entered in anything but a number. So if the user typed in undo f it won't convert f into it's number form (or at least that's what I think it would do) but it'll cause an error. I searched for a while and couldn't find anything that worked or made sense to me.
try {
int undo;
istringstream is(userInput.substr(5, userInput.length()));
is >> undo;
for (int numOfUndos = undo; numOfUndos > 0; numOfUndos--) {
board.UndoLastMove();
}
moveValidated = true;
}
catch (exception &e) {
cout << "/-----------------------------/" << endl;
cout << e.what() << endl;
cout << "/-----------------------------/" << endl;
}
If possible, I would like to just use how I currently have it or with cin. Also, forgive me, but I'm still learning C++ and don't know many advanced techniques, so if there is a complex way to do this forgive me if it takes me a bit to understand.
Thanks for any help in advance.
This worked for me. Thanks again.
The game description is not really relevent to your problem: how to
convert a string into an integer and check if it failed. To do that,
if (is >> undo) { worked } else { failed } Does UndoLastMove throw an
exception? – Neil Kirk
I'm a beginner programmer in C++ (currently), and I've got a conceptual question.
I'm trying to filter a cin input to ensure that it is a one-or-two-digit integer between 01-04, and if it isn't, to produce an error and ask for a new input.
I'm also using map to give the user a list of options that, upon valid selection, routes inputs (integers) through any of several methods to produce a relevant result, but I'll ask a more specific version of this question elsewhere.
I found a snippet of code at http://www.cplusplus.com/forum/beginner/26821/ that is meant to validate an input. I sort of get it, except where the boolean condition is set inside the while loop. Because I don't understand it, it makes it very difficult to edit or make sure that I'm manipulating it right.
Here is the example code:
int main()
{
int num;
bool valid = false;
while (!valid)
{
valid = true; //Assume the cin will be an integer.
cout << "Enter an integer value: " << endl;
cin >> num;
if(cin.fail()) //cin.fail() checks to see if the value in the cin
//stream is the correct type, if not it returns true,
//false otherwise.
{
cin.clear(); //This corrects the stream.
cin.ignore(); //This skips the left over stream data.
cout << "Please enter an Integer only." << endl;
valid = false; //The cin was not an integer so try again.
}
}
cout << "You entered: " << num << endl;
system("PAUSE");
return 0;
And here is my code (the entire thing, to give context). I don't think it's complete, I just want to make sure I'm using the boolean right.
float _tmain(float argc, _TCHAR* argv[])
{
bool validInput = !true;
map<string,int> Operations;
Operations.insert(pair<string, int>("Addition", 01));
Operations.insert(pair<string, int>("Subtraction", 02));
Operations.insert(pair<string, int>("Multiplication", 03));
Operations.insert(pair<string, int>("Division", 04));
cout << "Welcome to OneOpCalc, what operation would you like to perform?" << endl;
for(map<string, int>::iterator ii=Operations.begin(); ii!=Operations.end(); ++ii)
{
cout << (*ii).second << ": " << (*ii).first << endl;
}
while (!validInput)
{
cin >> operatorSelection;
if (cin.fail() || operatorSelection < 4 || operatorSelection > 1)
{
cout << "Error: Invalid selection. Please choose a valid number." << endl << endl;
cin.clear();
cin.ignore();
}
}
}
Does while (!valid) mean "While valid is false"? In my head, it's saying "While valid is !valid", which obviously, would always be false.
EDIT: Thanks for the answers guys, I'm looking through them all. One answer I keep getting goes too general; I understand that ! is NOT, and I understand the concept of flipping the bool using it. However the implicit logical implications are what confuse me. In any given statement, I am used to thinking of !valid as a way of flipping the valid value; Not testing a condition. It's the syntax of using it to test a condition that tricks me. In other words, writing while(!valid) reads literally to me as while(NOTvalid), not while(valid==false). I can't get myself to understand why in this case, !valid reads as a condition and not just a bit-flip.
Loops (and ifs) are controled by an expression of type bool.
In while ( !valid ), the expression is !valid, the operator
not applied to the value of the variable valid.
while ( !valid ) means (literally) while the expression
!valid (which means "not valid") is true.
For the rest, the code you're copying is pretty bad. I wouldn't
use it as an example if I were you.
As for your own code:
_tmain is very particular to Microsoft. You don't want to
use it. If your writing a console application, just use main.
(Same thing holds for _TCHAR, rather than char.)
Neither _tmain nor main can return a float. The return
type of main should always be int. I'm less familiar with
_tmain, but it's either int or void. (Probably int, if
you're in a console mode program.)
!true is false. Always. (Programming is different than
the real world. There are no maybes.) Why be more
complicated than necessary?
There's no need for the flag variable at all. You
can just write:
cin >> operatorSelection;
while ( !cin || operatorSelection > 4 || operatorSelection < 1 ) {
// ...
}
In case of error, you currently only ignore a single
character. You probably want to ignore up to and including the
end of line.
(std::cin.ignore( std::numeric_limits<std::streamsize>::max() );.
And the condition in your if will always be true. (See my
version above.) Where do you expect to find a number which is
neither less than for nor greater than one?
In your code, inside the loop, just add:
else
validInput = true;
after the if closing bracket.
You want to get out of it once the user has typed a correct value.
You want to run the loop "while there is not a valid input". Remove the non-bold words, and translate to C++.
Of course, the second case is not working, because nothing changes validInput inside the loop, so it stays "invalid", and the loop continues forever (And if you want to set something to false then bool validInput = !true; is more convoluted than bool validInput = false; - the compiler will do the same thing, but someone reading the code will have to think to see what it does - it is a good thing to think when reading code, but it's not a good thing to write code that is more complicated than necessary...).
A while loop has a condition and a body, the body is executed as long as the condition evaluates to true.
From the C++ standard:
6.5.1 The while statement
In the while statement the substatement is executed repeatedly until the value of the condition (6.4) becomes
false. The test takes place before each execution of the substatement.
A while loop can have one of the following forms
while ( condition ) statement
while ( condition )
{
statement(s)
}
The ! operator is a logical not and this is how you should read it: while not valid. You could have also written that as:
while(valid == false)
or
while(valid != true)
Note that here, again, != is equivalent to not equal.
nijansen forgot to add the most elegant one
while(!valid)
which is the same as the 2 others
Before you start wasting your time on me, please keep in mind that this question is more about knowing if this shutdown is legit enough.
Alright.
I read all kinds of ways to shut down a program. I KNOW that it's always best to shut down the program, at the end! So as i said, i read all kinds of topics, but i couldn't really find one that i understood correctly. So i kinda came up with my own way. I just want to make sure it's an okay method.
int main()
{
cout << "Welcome to my fantastic program!" << endl;
cout << "You're the first one to experience my command program!" << endl;
cout << "Let's try with a simple command. Try typing help" << endl;
while (running == 1) {
commands();
if (running == 0) {
exit(0);
}
}
return 0;
}
So i want you to focus on the while loop. This is my method.
void commands()
{
cin >> command;
if (command == "help")
{
cout << "-------------------------------" << endl;
cout << "-this is the <HELP> section----" << endl;
cout << "-exit (exits the program.)" << endl;
cout << "-Stay tuned for more commands--" << endl;
cout << "-------------------------------" << endl;
}
else if (command == "exit")
{
running = 0;
}
else
{
cout << "The command does not exist: " << command << endl;
}
}
And this is my command function. As you see, this changes "running" to 0 (or false). I hope i made this understandable enough.
Thanks.
EDIT: All i want to know is, if this is an okay method :)
FINAL EDIT: Alright! I changed "exit(0);" to "return(0);". So i guess this is a okay good method! Thanks for your help! :)
Using exit() in a program is legal. Though it's generally a bad idea. But if the program is stuck without a way back for some weird reason, you can do it.
Using exit in main() is rude: I just can't think of a sane reson not to use return instead.
The difference between exit() and return from main is that the former will leave all local objects in stack frames from main to the call point hanging, destructor not called. Only the static/global objects get proper shutdown. It may surprise some portions of the code, and leave important things not done.
As C++ has fine exceptions, I'd consider it preferable to replace exit() with throwing something that manages up to main, where regular return happens.
The if (running == 0) but is pointless!
while (running == 1) {
commands();
}
return 0;
Does exactly the same - once running is 0 it falls out the bottom of the loop, and main returns. The whole idea of the global running is getting into side effect programming, which is a bad thing!
Given the boundary conditions in the question exit() does what you want it to. It terminates the process normally, performing the regular cleanup for terminating programs (atexit(), destroying objects without automatic storage etc).
You don't really want to use a global running, so I would rather suggest checking the return parameter of commands().
say
int commands()
{
if(wanna_exit)
return 1;
else
return 0;
}
And if you for some reason cannot just let commands() break the while loop (For example by checking the return parameter and setting running to 0 if it is 1), and you want to exit the program instantly rather than finishing evaluating the rest of the while loop then exit() is ok (although in this particular case return is better (since you are in main in the example) ). Just try to avoid having running as global - might seem innocent right now, but can turn mean later :).
I have a variable which holds a score for a game.
My variable is accessible and correct outside of an if statement but not inside as shown below
score is declared at the top of the main.cpp and calculated in the display function which also contains the code below
cout << score << endl; //works
if(!justFinished){
cout << score << endl; // doesn't work prints a large negative number
endTime = time(NULL);
ifstream highscoreFile;
highscoreFile.open("highscores.txt");
if(highscoreFile.good()){
highscoreFile.close();
}else{
std::ofstream outfile ("highscores.txt");
cout << score << endl;
outfile << score << std::endl;
outfile.close();
}
justFinished = true;
}
cout << score << endl;//works
EDIT:
have realised my problem, when I was printing out it looped through many times so I did not see that all of them for the first loop didn't work, hence I thought the others were working when in fact they were not for the first iteration.
This is not a problem relating to the scope of the variable.
It could be several things:
Memory corruption somewhere
Multi threading relating problem
Something else...
Are you sure you are looking at the same iteration where the score value works before and after but not inside? Maybe put some more detailed logging instead of simply outputting the score itself.
Try printing cout << score << "#" << &score << endl; each place you currently print score. This will let you check if you're actually looking at the same variable.
If the addresses are different, you're accidentally shadowing your score variable somewhere - gcc has -Wshadow to catch that.
If the addresses are the same then the variable is getting corrupted somehow. Most debuggers have a memory breakpoint feature, so you can set the debugger to break when the memory in score changes and find the culprit.
With the amount of code you have attached there is nothing to indicate there is a problem in the code. As Brian says it is something else
Can you try this in your debugger and see what happens ? The idea is to simplify the problem as much as possible and try to get the minimal amount of code that replicates the problem.
What does this do ?
cout << score << endl; //works
if(!justFinished)
{
cout << score << endl; // doesn't work prints a large negative number
}
cout << score << endl; //works