In the code below, I have a while statement used to make sure an input string is less than 10 characters. I've declared a bool
called cont
which I use to tell the while loop to stop once my conditions have been met.
#include "stdafx.h"
#include <iostream>
#include <string>
int main()
{
using namespace std;
cout << "Enter a string less than 10 characters long: ";
string teststring;
{
bool cont(false);
//if input is 10 or more characters, ask for input again until it is less
while (!cont)
{
getline(cin, teststring);
if (teststring.length() >= 10)
{
cout << "Too long, try again: ";
}
else
{
cout << "Thank you.\n\n";
cont = true;
}
}
}
return 0;
}
As you can see there, I've used a set of {}
s to separate the code out, giving the cont
variable a local scope within those braces. I did this so that if I ever wanted to use that variable name again, I could just re-declare it, and when I'm done with it, it's destroyed.
Is this an acceptable practice? Or is there a better way to do what I've done? I acknowledge that in this specific, basic scenario, the condition is simple enough that it's hardly necessary, but I may want to do this for more complex loops in the future.
This is a toy case obviously but this is a good practice and 'stand-alone' blocks are there for that purpose. I happen to believe they're a better way to structure long functions than breaking it down into members which (in many cases) have no separate purpose.
In such a case you can provide a faster, clearer, safer program particularly if there's a comment (possibly one line) introducing each block.
However in this case you might consider:
for ( bool cont(false);!cont;)
Which has the same effect. Variables declared in a for(.;.;.)
statement are confined to the scope of that statement.
In this case you can dodge the whole variable with:
for(;;) //<--- Canonical formulation for 'infinite' loop.
{
getline(cin, teststring);
if (teststring.length() >= 10)
{
cout << "Too long, try again: ";
}
else
{
cout << "Thank you.\n\n";
break; //<--- Escapes the loop.
}
}
Footnote (in response to comments):
You should regard a for
loop as 'syntactic sugar' on a while
loop. That is no different in their performance, etc. and just pick the one that reads best. for(;cond;)
just looks funny.
There may be a tiny (tiny) performance benefit to break
but I happen to think it's actually simpler and more readable in many cases.
If the code were more complex there might be more 'loop end' code so it becomes:
for(bool cont(false);!cont;) {
//Complex code with multiple 'exit' conditions...
if(!cont) {
//Go round again code that won't fit nicely in last term of for loop...
}
}
Whereas using break
just makes a 'swift exit' easier to understand.
They're not (widely) considered to have the 'bad karma' of goto
because they 'go to' a very clearly defined point of execution.