Conditions and Loops

for Loops

A for loop encloses initialization, the condition, and an update in its header. The loop body simply takes care of the repeated work.

// Increment the value before the expression uses it
for (int i{0}; i < 5; ++i)
{
    std::cout << i << '\n';
}

Initialization is a statement that executes before the first iteration begins. The condition defines whether another iteration can begin. The update affects the controlling value after a completed iteration has executed.

Because of these traits, the for loop is useful when the number of repetitions is known or follows some common counting progression.

Initialization runs once when the loop begins. This often sets up the loop control variable. If declared there, it is local to the loop.

The condition is checked before each new iteration. A true value begins a new iteration. A false value causes the loop to terminate, with execution continuing at the next statement after the loop.

The update runs after each iteration. It changes the loop control value before the condition is evaluated again. It normally increments or decrements the variable, but it can also perform another operation to count down or change the interval between values.

All three pieces of code fit neatly into the header, so a reader can see exactly what controls the repetition.

Variables declared in the header of a for loop are only visible inside that loop. The loop variable no longer exists after the loop completes.

for (int n{10}; n > 0; --n)
{
    std::cout << n << '\n';
}

// n cannot be used here

This is desirable when the variable is needed only for controlling the loop. It prevents later code from accidentally using or modifying the same variable.

If the loop control variable must retain its value after the loop completes, declare it outside the loop.

int n{};

// Stop before the upper boundary is reached
for (n = 0; n < 5; ++n)
{
    std::cout << n << '\n';
}

std::cout << "Final value: " << n << '\n';

Not all of the loop control expressions need to be included in the header, although the semicolons remain required.

The initialization clause may be omitted if the controlling variable is initialized beforehand.

int k{0};

for (; k < 3; ++k)
{
    std::cout << k << '\n';
}

The update clause may be omitted if the body itself produces the change to the loop control variable.

for (int value{0}; value < 3;)
{
    std::cout << value << '\n';
    ++value;
}

A for loop with no condition will continue indefinitely unless it is exited from inside, for example with break or return.

for (;;)
{
    std::cout << "Running\n";
    // Leave the loop or switch immediately
    break;
}

Keeping all three sections in the header generally leads to a more readable loop definition.

A for loop can be nested inside another for loop. In this case, each iteration of the outer loop corresponds to one complete execution of all the inner loop's iterations.

for (int row{0}; row < 3; ++row)
{
    for (int column{0}; column < 2; ++column)
    {
        std::cout << row << "," << column << '\n';
    }
}

Use different names for the two loop control variables. Otherwise, it can become difficult to tell which loop a variable belongs to or which value is being changed.

Nested loops are useful when generating combinations from two sequences, where each item from the first sequence is paired with every item in the second sequence.

This is one of the most common loop errors. It occurs when the condition being tested does not describe exactly the range that we want.

For example, this loop executes six times because i takes the values 0 through 5:

// Include the upper boundary in this loop
for (int i{0}; i <= 5; ++i)
{
    std::cout << i << '\n';
}

If we wanted five iterations beginning at zero, the condition should use < 5:

for (int i{0}; i < 5; ++i)
{
    std::cout << i << '\n';
}

This is a classic off by one mistake that can occur when choosing between equality and inequality operators.

For example, a for loop may display the result for each number in a range.

It can also add each number without actually printing the loop variable.

The update clause does not always need to increment. It might multiply or divide the current value to produce a different progression.

A nested loop can create all possible combinations from two small ranges.

#include <iostream>

int main()
{
    for (int i{1}; i <= 5; ++i)
    {
        std::cout << "Square of " << i << " is " << i * i << '\n';
    }

    int total{0};

    for (int n{1}; n <= 10; ++n)
    {
        total += n;
    }

    std::cout << "Sum 1 to 10 is " << total << '\n';

    // Include the lower boundary while counting down
    for (int value{64}; value >= 1; value /= 2)
    {
        std::cout << value << '\n';
    }

    for (int outer{0}; outer < 2; ++outer)
    {
        for (int inner{0}; inner < 3; ++inner)
        {
            std::cout << outer << "-" << inner << '\n';
        }
    }
}

Whether nested or not, the loop header clearly shows how the number of repetitions is controlled, while the loop body expresses the statements that are executed during each repetition. This makes the for loop ideal when the required number of iterations is known or follows a clear pattern.

0 comments

No comments yet. Be the first.

Add a comment

About CppLearn

CppLearn is an interactive, free reference for modern C++. In each lesson, you'll find out how the language works, rather than just lines of code that you can copy and paste. We cover concepts starting from beginner lessons on fundamentals and proceed to templates, move semantics, smart pointers, and areas that usually trap or scare C++ learners.