Search code examples
c++loopswhile-loopcurly-braces

Using curly braces to segregate a variable that I want to use multiple times in C++


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.


Solution

  • 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.