Programming constructs in C++

Apart from using and defining functions, there are three basic programming constructs in C++ that everyone needs to know: the if statement, the while loop and the for loop. This page covers these three, with some advice on each, and finishes with some hints at some additional constructs that may be regarded as "optional". But we start with something that is very basic and important.

1. Curly brackets

The construct { ... } is so simple it might easily be overlooked, but is very useful. It combines several statements into a single statement. You can use it anywhere, but it is most commonly used with the other constructs defined below.

The statements inside { ... } should be terminated with semicolons as usual. A semicolon is rarely required after the }.

There is one nice feature of C++ with this construct that's not in older versions of C: this is that any variable declared inside the curly brackets is local to that region of the code inside the brackets. This means you can write things like curlybrackets.cpp which contains,

  a = 1;
  bool b = true;
  {
    int b = 2;
    b = b*a + 7;
    a = 9*b;
  }
  {
    double b = 1.0;
    b = b + a + 7.0;
    cout << b;
  }

(This is just for illustration. The actual code here does nothing useful as far as I know.) The point is that the b in the first set of curly brackets is not the same as the b in the second set, and both of these "hide" the b outside. These variables "live" in their own bit of code and do not interfere with each other. They are local or have bounded scope. Restricting the scope of variables as far as possible in this way is very good practice and will help reduce the likelihood of bugs. It is recommended and all good programmers will do this as far as possible.

Note that doing so accidentally (e.g. putting a type such as int or double in front of a variable name inside a block will make a new variable and "hide" any variable with that name outside the block. This is occasionally doen by beginners: very very careful that it is what you actually want.

Curly bracket blocks like this form a "compound statement", i.e. a single statement formed from many individual statements.

2. If statements

The general form of the if statement is

if (expr) {
  ...
} else {
  ...
}

This is computed as follows:

Variations:

Possible pitfalls.

  • Do not put a semicolon after the ) ending the expression, as in "if (n > 0); { n--; }". The compiler will interpret the empty statement between ) and ; as the statement to be performed if the condition is true and will always do the following statement. Most compilers will not notice the error even with warnings enabled.
  • Any "else" block matches the nearest possible "if". Indentation and any other formatting is completely ignored to decide what statement goes with what "if".

To illustrate the second of these points, consider

if (x > 0) 
  if (y == 1) z = 0;
else w = 1;

Note that I have omitted curly brackets. Sometimes this helps readability, but it can be a problem. In this particular case the indentation hides the fact that the syntax rules match else w = 1 with if (y == 1). In other words, with curly brackets, the above is equivalent to

if (x > 0) {
  if (y == 1) { 
    z = 0;
  } else {
    w = 1;
  }
}

It is unlikely that the programmer who indented the program in the first way actually intended this, and it is unlikely that the compiler would spot the problem.

3. While loops

While loops are perhaps one of the most straightforward loops in C++ to understand. Their syntax is a little like if statements:

while (expr) {
  ...
} 

This time, if the expression expr comes out true the body of the statement is executed and then the test is repeated. Thus the body is executed repeatedly as long as the expression comes out to be "true". If the expression is false (even on the very first try) the body of the loop is passed over and skipped.

Possible pitfall.

Do not put a semicolon after the ) ending the expression, as in while (n > 0); { n--; }. As with "if", the compiler will interpret the empty statement between ); as the statement to be performed if the condition is true, and if it attempts this statement the value of the condition controlling the loop is unlikely to change so the computer "gets stuck in a loop".

Variations.

  • The statement "break;" exits the smallest enclosing "while" loop (or "for" loop, see below). It is a useful way of quitting a loop in a different or unusual way. Of course, to be useful a "break" will always be part of the body of an "if" statement inside the loop or the corresponding "else".
  • The statement continue; quits the body of the smallest enclosing "while" loop (or "for" loop, see below) but restarts the loop, doing the test again. Thus "continue" says "finish this time round the loop but see if you can go around again", whereas "break" says "finish the loop completely". Most programmers find that "continue" is not so useful but occasionally it is just what is needed. Again, "continue" will always be part of the body of an "if" or "else".

Using "break" and possibly also "continue", loops that start with while (true) { .. } become very useful. These can end at some position in the middle of the loop.

Remark.

C++ also allows a loop to start "do { ... } while (expr);". This kind of loop has its test at the end, and the body of the loop is always executed at least once. Generally speaking, these loops are rarely so useful, but can be just what you need at times. On the other hand the same effect can always be got with "while (true) { ... if (expr) { break; } }".

Remark.

Ideally you should try to limit the number of ways a loop can exit to as small a number of ways as possible. This will make the program easier to analyse and will reduce the possibility of bugs from actions not carried out because a loop exited early. Even better: try to make loop bodies small and easy to understand (using functions perhaps).

4. For loops

For loops have a very curious syntax taken from C. Until you understand them they are not easy to read. For loops can always be avoided, i.e. they they can always be replaced by while loops. However the syntax is compact and when you are used to them, "for loops" are usually easy and clear to read.

A for loop looks like,

for (startcommand ; condition ; eachloopcommand) {
  ...
} 

where startcommand and eachloopcommand are commands to be executed, and condition is an expression that evaluates to a bool. This is equivalent to the programming construct,

{
  startcommand;
  while (condition) {
    ...
    eachloopcommand;
  } 
}

so startcommand is carried out once, and the eachloopcommand is carried out just before the loop condition is re-tested. (The outside set of braces ensures that any variables declared in the startcommand is local to the for statement.)

For loops are almost always written in the following way.

for (n=0; n<100; n++) {
  ...
} 

This means that the body of the loop is carried out for each value of the int variable n from 0 to 99 inclusive. An alternative might be,

for (n=99; n>=0; n--) {
  ...
} 

where the body of the loop is carried out for each value of the int variable n from 99 down to 0 inclusive. I recommend you do not use "for" loops for anything much more complicated than this. (It certainly would be possible to do so if you put your mind to it.) If you need anything more complicated use "while" as your general purpose loops, and use "for" only in one of the two forms given.

Possible pitfall.

Do not put a semicolon after the ) ending the three expressions in the header to the "for", as in for (int n=0; n<100; n++); { ... }. The reasons are the same as for "if" and "while".

Remark.

One particularly useful form for "for" loops is

for (int n=0; n<100; n++) {
  ...
} 

The difference here is that the variable n is declared in the "for" loop and doesn't exist outside the loop, so can't be accidentally used elsewhere without the compiler picking up on the error. Provided you don't need the value of n when the loop was exited this form is to be highly recommended. In fact for this reason alone, "for" loops can be recommended instead of "while" when a new variable controls the loop.

Possible pitfall.

It appears to be a "game" played by experienced programmers of trying to put as many complicated calculations in the round brackets following for as possible to reduce the size of the body of the loop perhaps. Although C and C++ permit this, it also results in obscure code that is hard to read and debug. (The same applies to while and if too, of course.)

5. Other constructs

I have already mentioned do { ... } while (expr);. You can look this up, and use it if you want, but I see no reason to use it. I rarely need it and don't particularly like it.

C++ has a useful "switch" statement for programming by cases. The syntax is mildly tricky and there are some serious pitfalls for beginners, which is why I haven't given details on it here. It can always be replaced by nested "if" statements, and that it what I recommend beginners to do. When you have some confidence, the "switch" statement is rather more efficient and can sometimes be more elegant (though sometimes it isn't).

C++ also has "go to" statements. These are useful for code generated by computer programs but have no place in human-authored code.

Probably the most important omission to the list of control structures given here is try { .. } catch (..) { .. } and the associated throw. These statements really concern something quite different and somewhat more advanced - "exceptions" - and you can find out about them elsewhere. Suffice it to say that expert programmers will certainly need to know about exceptions, beginners that are programming numerics probably don't.