Control Flow Statements
In a program, it is rare to provide useful functionality by just executing a linear sequence of operations. Commonly, a program must be able to react in different ways in response to different situations or execute the same operation multiple times in different contexts.
We will now see the control flow statements C++ offers to the programmer to control the sequence of operations to be executed.
Selection Statement – if-else
C++ provides conditional execution support, where the if keyword indicates whether or not to execute the following statement or block, depending on the fulfillment of the condition provided:
if (condition) statement
If the expression named condition evaluates to true, then the statement is executed; otherwise, it will be ignored and the program will continue with the subsequent code.
The conditionally executed code can be a single statement or an entire block containing multiple ones. These statements needs to be enclosed in braces ({}) to form a block:
if (condition) { statement_1; statement_2; statement_N; }
Note
It is common to forget the brace brackets and write the control statement in the following manner:
if (condition) statement1 statement2
Note
In such a case, the compiler will not warn you, and it will execute statement1 depending on the condition, but always execute statement2. To avoid such a situation, it can be a good practice to always add the braces.
It is possible to specify what to execute instead when the condition evaluates to false. This is done through the else keyword, which is followed by a statement or a block.
The following syntax is used to indicate that statement1 should be executed if the case condition evaluates to true, and otherwise statement2 is executed:
if (condition) statement1 else statement2
Finally, we can concatenate on multiple if-else statements to produce a more complex branching logic. Let's examine the following example:
if (condition1) { statement1 } else if (condition2) { statement2 } else { statement3 }
With this generic structure, it is possible to check the unlimited number of conditions and execute only the corresponding statement or the final one contained in the else branch.
It is important to be aware that once one of the conditions is met, all of the ones that follow are discarded, for example:
if (x > 0) { // When x is greater than 0, statement1 is executed. // If that is not the case, the control jumps to the else block. statement1 } else if (x > 100) { statement2 }
The previous code will always execute statement1 for any positive x, regardless of whether it is greater than 100 or not.
An alternative way is to sequence several if keywords, as follows:
if (condition1) // If condition1 is true, statement1 is executed statement1 if (condition2) // if condition2 is true then statement2 is executed statement2 /* independently whether condition1 and condition2 is true or not, the statement3 will be executed */ statement3
Let's demystify the previous logic with the following example:
#include <iostream> int main() { int x = 10; if (x > 0){ std::cout << x << std::endl; } if (x > 11 ){ std::cout << x << std::endl; } else{ std::cout << x-1 << std::endl; } } Output: 10 9
In this way, all the conditions are evaluated independently and more than one statement can potentially be executed.
Note
As the else statement has no condition defined, after evaluating the if statement, the control comes to the else block to execute the statement.
Selection Statement – switch
Another selection statement, with similarities to the if-else concatenation construction, is the switch statement. It is limited to constant expressions and is mainly used to check for a value among a number of possible expressions:
switch (expression) { case constant1: group-of-statements-1; break; case constant2: group-of-statements-2; break; ... default: default-group-of-statements; break; }
The expression present in the parentheses following the switch keyword is evaluated against multiple cases, searching for the first equality between the expression and the constants. If none of the cases match, the default one (if it exists, since it is optional) is executed.
It is important to keep in mind that the order of evaluation is sequential, and as soon as one of the constants matches, the corresponding group of statements are executed. The break keyword prevents them from further execution. If the break keyword is not included, all statements following the case, including the ones under different labels, are also executed.
We will explore the break keyword more in the Jump statements – break and continue section.
Iteration Statement – for loop
The for loop is a construct that's used to repeat a statement a certain number of times. The syntax of the for loop is as follows:
for (initialization; condition; increase){ statement1; statement2; ... statementN; }
The for loop consists of two parts: the header and the body. The former controls how many times the latter is repeated. The header is the part enclosed by parentheses and it is formed by initialization, condition, and increase statements. The body can be a single statement or a block of multiple ones.
The initialization statement is typically (but not necessarily) used to declare a new variable, usually a counter, and to initialize it to a certain value. The initialization statement is executed only once, at the beginning of the loop.
Secondly, the condition statement is checked. This is similar to the condition that's checked for an if statement. If the condition is true, the body of the loop is executed, otherwise the program continues its execution with the instruction after the body of the for loop.
After the body executes, the increase statement is executed. This usually changes the counter of the initialization statement. The condition is then checked again and, if true, the steps are repeated. The loop ends when the condition evaluates to false.
The fields in the header of a for loop are optional and can be left blank, but the semicolons cannot be omitted. When the condition is omitted, it always evaluates to true. For example, the following corresponds to an infinite loop where the statement is executed unconditionally:
for ( ; ; ) statement;
Another variant of the for loop is called a range-based for loop, the syntax for which is as follows:
for ( declaration : range ) statement;
A range is a sequence of elements, like arrays, which are explained in the next section. This range-based for loop is used to iterate over all elements of these sequences. The range is the name of the sequence, and in the for declaration, the name is a temporary variable that's declared for every iteration of the loop. This is used to store the current element. The declaration needs to be the same type as the elements contained in the range.
Note
A range-based for loop is a good example where type deduction and the use of the auto keyword for the declaration makes the code more readable and helps the programmer find the right type to use.
A loop placed inside a loop is known as a nested loop. Let's look at the following diagram to understand what a nested for loop is:
Using the following example, let's explore how a nested for loop works and print a reverse half-triangle on the console:
#include <iostream> int main() { for (int x = 0; x < 5; x++){ for (int y = 5; y > x; y--){ std::cout << "*"; } std::cout <<"\n" ; } } Output: ***** **** *** ** *
Iteration Statement – while loop
Another iteration statement is the while loop. It is simpler than the for loop. The syntax for it is as follows:
while (condition) statement;
It repeats the statement until the condition is met. When the condition is not true anymore, the loop ends and the program continues its execution right after the loop:
Note
A while loop can always be expressed using a for loop.
Here is an example: for ( ; condition ; ) statement;
Iteration Statement – do-while loop
A similar loop is the do-while loop, where the condition is checked after the execution of the statement, instead of before. It uses the following syntax:
do statement while (condition);
It guarantees at least one execution of the statement, even though the condition never evaluates to true.
Jump Statements – break and continue
The break keyword is used to end a loop independently, regardless of whether it fulfils its condition. In the following program, when condition2 becomes true, the break statement will immediately terminate the while loop:
while (condition1){ statement1; if (condition2) break; }
Alternatively, the continue statement is used to skip the rest of the body's loop in the current iteration. In the following example, when condition2 evaluates to true, continue is called, causing the program to reach the end of the loop, skipping statement2 and continuing with the next iteration:
while (condition1){ statement1; if (condition2) continue; statement2; }
Note
The break and continue statements can be used in both for and while loops.