InfoCode

C++ · Control structures

Multi-level nesting

Trace C++ nested loops with multiplication-table and execution-count examples, then use braces to clarify nested if and else.

Written by InfoCode · Technical references below

Practice this topic in the app Read the lesson in the app

Inner loops, outer loops and nested branches

Imagine a class has 3 rows of students, with 4 people in each row, and you need to call names one by one—first call the 1st person in row 1, then the 2nd person in row 1... after finishing row 1, then call row 2... this is the scenario of a double loop.

The outer loop controls the "row", and the inner loop controls the "column"; each time the outer loop executes once, the inner loop executes a full round.

Number of executions: outer loop m times × inner loop n times = m×n executions in total.

break only exits the nearest loop level, and cannot exit all levels at once.

Nested if is the same: there is another if inside an if; use indentation to make the levels clear, and use braces to clarify the scope.

Branch nesting: within one branch, continue to test another condition; it is suitable for rules of "first determine the major category, then subdivide". Each level's condition is tested only when execution reaches that level. Use braces to make clear which else each belongs to; you cannot rely on indentation to change C++ semantics.

Nested loops: trace i, j and output

Each entry into the outer loop body initializes j to 1 again. Predict the number of printed lines, then check their order.

#include <iostream>
int main() {
    for (int i = 1; i <= 2; ++i) {
        for (int j = 1; j <= 3; ++j) {
            std::cout << i << " " << j << "\n";
        }
    }
}
Print orderijOutput line
1111 1
2121 2
3131 3
4212 1
5222 2
6232 3

When j becomes 4, the inner loop ends. When i becomes 2, a fresh inner j starts at 1. Finally i becomes 3 and the outer loop ends; neither i=3 nor j=4 is printed.

Check your understanding: If the upper bound for i becomes 3, how many lines print? What is line 7?

There are 3×3=9 lines. Line 7 is 3 1 because the next inner loop initializes j again.

Nested loop time complexity: rectangles and triangles

With constant work per inner iteration and no early exit, n outer iterations and m inner iterations each give n×m steps and O(nm) time. If m is fixed at 3, time grows as O(n). Two nested loops do not automatically mean O(n²).

for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= i; ++j) {
        // constant work per iteration
    }
}

The inner counts are 1, 2, …, n, totaling n(n+1)/2: Θ(n²) for n≥1. With n=3, this is 1+2+3=6 steps, rather than 3×3=9. These examples use a fixed number of counters and O(1) auxiliary space, excluding output storage.

break exits the nearest enclosing loop. An inner continue skips the rest of that inner iteration, then performs the inner for update; it does not skip the remaining outer body. Insert if (j == 2) break; before the print statement in the first example: only j=1 prints for each i, giving 1 1 and 2 1. Replace break with continue: the output is 1 1, 1 3, 2 1, 2 3 on separate lines.

Check your understanding: If the inner loop always runs five times and the outer loop runs n times, what is the time complexity?

The body runs 5n times. With constant work per iteration, this is O(n), rather than O(n²).

Execution counts and else association

Example 1: print the multiplication table

#include <iostream>
using namespace std;
int main() {
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= i; j++) {
            cout << j << "*" << i << "=" << i*j << " ";
        }
        cout << endl;
    }
    return 0;
}

The outer i goes from 1 to 9 and controls the rows; the inner j goes from 1 to i and controls the columns; a total of 1+2+...+9=45 multiplications are executed, outputting the standard 9×9 multiplication table.

Example 2: double loop counts the total number of executions

#include <iostream>
using namespace std;
int main() {
    int cnt = 0;
    for (int i = 1; i <= 3; i++) {
        for (int j = 1; j <= 4; j++) {
            cnt++;
        }
    }
    cout << cnt << endl;
    return 0;
}

Outer 3 times × inner 4 times = 12 executions in total, output 12. This is the basic method for calculating the number of executions of nested loops.

Example 3: first determine whether it is passing, then determine whether it is excellent

#include <iostream>
using namespace std;
int main() {
    int score = 85;
    if (score >= 60) {
        if (score >= 90) cout << "excellent" << endl;
        else cout << "pass" << endl;
    } else {
        cout << "retry" << endl;
    }
}

Output pass. The outer layer determines whether it is passing; after entering, the inner layer then determines whether it is excellent; the outer else only handles not passing.

Example 4: use parentheses to make clear which level the else belongs to

#include <iostream>
using namespace std;
int main() {
    bool registered = false, paid = true;
    if (registered) {
        if (paid) cout << "ready" << endl;
    } else {
        cout << "register first" << endl;
    }
}

Output register first. The else corresponds to the outer if; if the outer braces are removed, it may instead match the inner if, and when not registered it would not output the prompt.

Tips

Prerequisites

Technical references

Scope note

This lesson is written by InfoCode and is not an official syllabus; the reference level is a site mapping and does not represent official levels, certification or eligibility. Practice records do not establish mastery or eligibility.

Reference level: GESP Level 2 (site mapping)

See contest pathways