In the realm of C++ programming, control flow statements are indispensable tools that enable us to dictate the execution path of our code. They provide the means to make decisions, iterate over data, and manage the flow of execution based on specific conditions. In this post, I will delve into the intricacies of control flow statements in C++17, including if-else, switch-case, traditional loops (for, while, do-while), and the modern range-based for loop. Through detailed explanations and code examples, we will explore how these constructs function and how they can be effectively utilised in your code.


Table of Contents

  1. The if-else Statement
  2. The switch-case Statement
  3. Loops in C++
  4. The Range-Based for Loop
  5. Conclusion

The if-else Statement

The if-else statement is a fundamental control structure that allows us to execute code blocks conditionally. Based on a boolean expression, the program decides whether to execute a particular block of code.

Syntax:

if (condition) {
    // Code to execute if condition is true
} else {
    // Code to execute if condition is false
}

Example:

#include <iostream>

int main() {
    int number = 10;

    if (number % 2 == 0) {
        std::cout << number << " is even.\n";
    } else {
        std::cout << number << " is odd.\n";
    }

    return 0;
}

Explanation:

In this example, we check whether the variable number is even or odd by using the modulus operator %. If number % 2 equals 0, the condition is true, and the program outputs that the number is even; otherwise, it outputs that the number is odd.


The switch-case Statement

The switch-case statement offers a streamlined way to compare a variable against multiple constant values, executing different code blocks based on the matching case.

Syntax:

switch (variable) {
    case constant1:
        // Code block for constant1
        break;
    case constant2:
        // Code block for constant2
        break;
    // More cases...
    default:
        // Code block if no cases match
        break;
}

Example:

#include <iostream>

int main() {
    char grade = 'B';

    switch (grade) {
        case 'A':
            std::cout << "Excellent!\n";
            break;
        case 'B':
            std::cout << "Well done.\n";
            break;
        case 'C':
            std::cout << "Good.\n";
            break;
        case 'D':
            std::cout << "Need improvement.\n";
            break;
        case 'F':
            std::cout << "Failed.\n";
            break;
        default:
            std::cout << "Invalid grade.\n";
            break;
    }

    return 0;
}

Explanation:

Here, the program evaluates the character grade and matches it against the cases. Upon finding a matching case ('B' in this instance), it executes the corresponding code block and then breaks out of the switch statement to prevent fall-through (the unintended execution of subsequent cases).


Loops in C++

Loops are control structures that allow us to execute a block of code repeatedly based on a condition. C++ provides several looping constructs, each with its unique use cases.

The for Loop

The traditional for loop is commonly used when the number of iterations is known beforehand.

Syntax:

for (initialisation; condition; increment) {
    // Code to execute
}

Example:

#include <iostream>

int main() {
    for (int i = 1; i <= 5; ++i) {
        std::cout << "Iteration " << i << "\n";
    }

    return 0;
}

Explanation:

In this loop, we initialise i to 1, continue looping while i is less than or equal to 5, and increment i after each iteration. The program outputs the iteration number each time.


The while Loop

The while loop is ideal when the number of iterations is not known in advance and depends on a condition evaluated before each iteration.

Syntax:

while (condition) {
    // Code to execute
}

Example:

#include <iostream>

int main() {
    int count = 0;

    while (count < 3) {
        std::cout << "Count is " << count << "\n";
        ++count;
    }

    return 0;
}

Explanation:

This loop continues to execute as long as count is less than 3. The condition is evaluated before each iteration, ensuring that the code block is only executed when the condition holds true.


The do-while Loop

The do-while loop is similar to the while loop but guarantees that the code block is executed at least once because the condition is evaluated after the execution of the loop’s body.

Syntax:

do {
    // Code to execute
} while (condition);

Example:

#include <iostream>

int main() {
    int number = 5;

    do {
        std::cout << "Number is " << number << "\n";
        ++number;
    } while (number < 5);

    return 0;
}

Explanation:

Despite the condition number < 5 being false initially (number is 5), the code inside the do block executes once before the condition is checked. This is a key characteristic of the do-while loop.


The Range-Based for Loop

Introduced in C++11 and further refined in C++17, the range-based for loop provides a concise and readable way to iterate over elements in a container (such as arrays, vectors, or any class that provides begin() and end() methods).

Syntax:

for (element_type element : container) {
    // Code to execute with element
}

Example:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << "\n";

    return 0;
}

Explanation:

In this example, the range-based for loop iterates over each element in the numbers vector, allowing us to access each num directly without the need for indexing. This enhances code readability and reduces the potential for errors associated with traditional indexing.

C++17 Enhancements:

C++17 introduced structured bindings, allowing us to unpack elements while iterating. This is particularly useful when working with containers of pairs or tuples.

Example with Structured Bindings:

#include <iostream>
#include <map>

int main() {
    std::map<std::string, int> scores = { {"Alice", 90}, {"Bob", 85}, {"Charlie", 95} };

    for (const auto& [name, score] : scores) {
        std::cout << name << " scored " << score << "\n";
    }

    return 0;
}

Explanation:

Here, we use structured bindings to unpack the key-value pairs in the scores map directly into name and score variables within the loop. This feature enhances the expressiveness of the range-based for loop in C++17.


Conclusion

Understanding and mastering control flow statements is crucial for writing efficient and effective C++ programs. The if-else and switch-case statements empower us to make decisions based on conditions, while loops (for, while, do-while) allow us to execute code repeatedly under certain conditions. The range-based for loop, especially with C++17 enhancements like structured bindings, offers a more elegant and readable way to iterate over collections.

As we continue to develop more complex applications, these control structures become even more vital. They not only improve the logic and flow of our programs but also enhance maintainability and readability. I encourage you to experiment with these constructs and consider how they can be applied in your projects to write cleaner and more efficient code.


Note: All code examples have been tested with a C++17 compliant compiler. For further reading and more in-depth explanations, consider consulting the C++17 standard documentation and authoritative texts such as “The C++ Programming Language” by Bjarne Stroustrup.