C++ · Beginner

Loops in C++: for, while and do-while

9 min readUpdated September 24, 2026Every example verified

In short: A loop repeats a block while a condition stays true. C++ has for (counted repetition with an initialiser, a condition and a step), while (test first, possibly zero passes), do-while (run once, then test) and the range-based for (one pass per element of a container). break leaves a loop immediately and continue jumps to the next pass.

Repeating work

A for loop packs the three parts of counted repetition into one header: for (int i = 1; i <= count; ++i). The initialiser runs once, the condition is tested before every pass and the step runs after every pass. A variable declared in the header lives only for the loop, so the same name can be reused by the next loop without a clash. The condition is checked before the first pass too, which means a for loop with count equal to zero runs its body no times at all.

while (condition) is the simpler form: test, run the body, test again, until the condition is false. It suits situations where you do not know in advance how many passes are needed, such as reading values until a negative one appears. Something inside the body must eventually make the condition false, otherwise the loop never ends.

The idiom while (std::cin >> value) reads input until it runs out. The expression std::cin >> value returns the stream itself, and a stream converts to true while its last read succeeded and to false once a read fails, either because the input ended or because the next token was not a valid value. The loop body therefore only ever sees values that were actually read, which is exactly what you want for processing a file of unknown length.

do { } while (condition); tests after the body, so the body always runs at least once. That fits prompts that must be shown before you can check the answer: read a value, then decide whether to ask again. Note the semicolon after the closing parenthesis; it is part of the statement.

break ends the loop at once and continues with the statement after it. continue abandons the current pass and goes straight to the next test, or, in a for loop, to the step. Both are useful for handling special cases at the top of the body so the normal case can follow without extra nesting, but each one is a jump the reader has to trace, so use them where they simplify and nowhere else.

Loops nest: a loop inside a loop runs the inner one completely for every pass of the outer one, which is how you visit every cell of a grid. break and continue apply to the innermost loop only.

C++11 added the range-based for, for (int x : container), which walks over every element of an array, std::array, std::vector or std::string without an index. It is the right choice whenever you want each element and do not need its position. The arrays lesson uses it throughout.

Syntax

 C++ · syntax
for (initialiser; condition; step) {
    // body
}

while (condition) {
    // body, runs zero or more times
}

do {
    // body, runs at least once
} while (condition);        // note the semicolon

for (type element : container) {
    // one pass per element (C++11)
}

while (std::cin >> value) {  // until input ends or a read fails
    // use value
}

break;      // leave the innermost loop now
continue;   // skip to the next pass of the innermost loop

Any of the three parts of a for header may be empty: for (;;) is an endless loop that must be left with break or return.

A counted for loop over input

The first number says how many readings follow; the loop reads each one, prints it and keeps a running total and maximum.

 C++
#include <iostream>

int main() {
    int count;
    std::cin >> count;

    double total = 0;
    double highest = 0;
    for (int i = 1; i <= count; ++i) {
        double reading;
        std::cin >> reading;
        total += reading;
        if (reading > highest) {
            highest = reading;
        }
        std::cout << "Reading " << i << ": " << reading << "\n";
    }
    std::cout << "Average: " << total / count << "\n";
    std::cout << "Highest: " << highest << "\n";
    return 0;
}

Input given to the program: 418.5 21 19.25 22.5

Output

Reading 1: 18.5
Reading 2: 21
Reading 3: 19.25
Reading 4: 22.5
Average: 20.3125
Highest: 22.5

The header counts from 1 to count inclusive, which gives human-friendly numbering in the output. reading is declared inside the body, so a fresh variable is created for each pass and disappears at the end of it; total and highest are declared before the loop because they must survive across passes. total / count divides a double by an int, so the average keeps its fraction.

while until the input ends, with break and continue

Values are read until there are none left or a negative one appears; odd values are skipped.

 C++
#include <iostream>

int main() {
    int value;
    int accepted = 0;
    int sum = 0;
    while (std::cin >> value) {
        if (value < 0) {
            std::cout << "Stopping at " << value << "\n";
            break;                 // leave the loop entirely
        }
        if (value % 2 != 0) {
            continue;              // skip the rest of this pass
        }
        sum += value;
        ++accepted;
    }
    std::cout << "Accepted " << accepted << " even values, sum " << sum << "\n";
    return 0;
}

Input given to the program: 4 7 10 3 6 -1 8

Output

Stopping at -1
Accepted 3 even values, sum 20

The condition reads a value and is true as long as the read succeeded. 7 and 3 reach the continue, so the two lines after it never run for them. When -1 arrives, break ends the loop before the 8 is ever read. Without the sentinel, the loop would end on its own when the input ran out, because std::cin >> value would fail and the condition would become false.

Nested loops and do-while

A 3 by 4 multiplication grid, then a guessing loop that must run at least once.

 C++
#include <iostream>

int main() {
    for (int row = 1; row <= 3; ++row) {
        for (int col = 1; col <= 4; ++col) {
            if (col > 1) {
                std::cout << " ";
            }
            std::cout << row * col;
        }
        std::cout << "\n";
    }

    int attempts = 0;
    int guess;
    do {
        std::cin >> guess;
        ++attempts;
    } while (guess != 7);
    std::cout << "Found 7 after " << attempts << " attempt(s)\n";
    return 0;
}

Input given to the program: 3 9 7 2

Output

1 2 3 4
2 4 6 8
3 6 9 12
Found 7 after 3 attempt(s)

For each of the 3 values of row, the inner loop runs through all 4 values of col, so the body runs 12 times. Printing the separator before every element except the first avoids a trailing space at the end of each line. The do loop reads a guess before it can test anything, which is why do-while fits: the condition depends on a value the body produces. The trailing 2 in the input is never read.

Choosing a loop

LoopUse whenPasses
for (init; cond; step)the number of passes is known or driven by a counterzero or more
while (cond)you repeat until something happens and may not need to start at allzero or more
do { } while (cond);the body must run before the condition can be judgedone or more
for (auto x : container)you want every element and do not need an indexone per element
while (std::cin >> x)input of unknown lengthone per value read

Common mistakes

  • Off by one in the condition

    Why it goes wrong: for (int i = 1; i < n; ++i) runs n - 1 times when n passes were wanted; for (int i = 0; i <= n; ++i) runs n + 1 times. Both compile and both produce quietly wrong totals.

    Fix: Decide whether the counter starts at 0 or 1, then pick < or <= to match. Counting from 0 with < n is the C++ convention because array indexes start at 0.

     C++ · fix
    for (int i = 0; i < n; ++i) {   // exactly n passes: 0, 1, ..., n - 1
    }
  • A while loop whose variable never changes

    Why it goes wrong: while (attempts < 3) { std::cout << "try\n"; } prints forever because nothing inside updates attempts.

    Fix: Make sure something in the body moves the condition toward false, and test the loop with input that should end it immediately.

  • A semicolon after the loop header

    Why it goes wrong: for (int i = 0; i < 3; ++i); is a loop with an empty body that runs three times; the block below it then runs once, after the loop.

    Fix: Never put a semicolon between the closing parenthesis and the opening brace.

  • Reading with while (!std::cin.eof())

    Why it goes wrong: The end-of-file flag is set only after a read fails, so the body runs one extra time with a stale value and the last item is processed twice.

    Fix: Put the read in the condition: while (std::cin >> value) runs the body only for values that were actually read.

     C++ · fix
    int value;
    while (std::cin >> value) {
        total += value;
    }

Where you use this

Almost every program that reads a file or a stream is one loop. A weather station logs a temperature per line; a program that reports the average, the highest and the number of frost readings is a while (std::cin >> t) loop with three variables updated inside it and a print afterwards. The loop does not need to know how long the file is, handles an empty file gracefully (the body never runs, and you check the count before dividing), and stops on its own. Nested loops appear as soon as the data is two-dimensional: every seat in every row, every cell in every line of a grid, every pair of items in a list.

 C++ · in practice
double t;
int days = 0;
int frostDays = 0;
while (std::cin >> t) {
    ++days;
    if (t < 0) {
        ++frostDays;
    }
}
if (days > 0) {
    std::cout << frostDays << " of " << days << " days below zero\n";
}

Key points

  • for (init; condition; step) is for counted repetition; the counter declared in the header lives only in the loop.
  • while tests before each pass and may run zero times; do-while tests after and runs at least once.
  • while (std::cin >> x) reads until the input ends or a value fails to parse.
  • break leaves the innermost loop; continue skips to its next pass.
  • Nested loops run the inner loop fully for each pass of the outer one.
  • Range-based for (C++11) visits each element of a container without an index.
  • Off-by-one errors come from mismatching the start value with < or <=; count from 0 with < n.

Try it yourself

The loop counts from 1 up to 10. Change the header so it counts down from 10 in steps of 3, printing 10, 7, 4 and 1 on separate lines before Done.

Your program
#include <iostream>

int main() {
    for (int i = 1; i <= 10; ++i) {
        std::cout << i << "\n";
    }
    std::cout << "Done\n";
    return 0;
}
Expected output: 10 7 4 1 Done

Practise this

Exercises for this lesson are in the C++ practice set.

Open the C++ playground

Frequently asked questions

How do I read input until the end in C++?

Put the read inside the loop condition: while (std::cin >> value) { ... }. The extraction returns the stream, and the stream converts to false once a read fails, which happens at end of input or on a token that is not a valid value. For whole lines use while (std::getline(std::cin, line)) in the same way.

Is there any difference between ++i and i++ in a for loop?

For an int counter, none: both add 1 and the value of the expression is discarded. ++i is the conventional spelling because, for iterator types you meet later, the postfix form must make a copy of the old value and can be slower.

How do I break out of a nested loop in C++?

break only leaves the innermost loop. The cleanest way out of both is to put the loops in a function and return from it when the target is found. Alternatives are a bool flag tested in the outer loop's condition, or goto to a label after the loops, which is legal but rarely seen in modern code.

Progress is stored only in this browser.

How this page was checked. Every program on it was run with GCC 13 (C++17) at build time by the publishing checks, and the output shown is what it printed. Running C++ inside the browser is not available yet, so the Run button is absent rather than pretending; copy the code and run it with GCC 13 (C++17) locally.