C++ · Beginner
Loops in C++: for, while and do-while
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
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 loopAny 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.
#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: 4 ↵ 18.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.
#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.
#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
| Loop | Use when | Passes |
|---|---|---|
| for (init; cond; step) | the number of passes is known or driven by a counter | zero or more |
| while (cond) | you repeat until something happens and may not need to start at all | zero or more |
| do { } while (cond); | the body must run before the condition can be judged | one or more |
| for (auto x : container) | you want every element and do not need an index | one per element |
| while (std::cin >> x) | input of unknown length | one 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< nis the C++ convention because array indexes start at 0.C++ · fixfor (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 updatesattempts.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++ · fixint 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.
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.whiletests before each pass and may run zero times;do-whiletests after and runs at least once.while (std::cin >> x)reads until the input ends or a value fails to parse.breakleaves the innermost loop;continueskips 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.
#include <iostream>
int main() {
for (int i = 1; i <= 10; ++i) {
std::cout << i << "\n";
}
std::cout << "Done\n";
return 0;
}
10
7
4
1
Done#include <iostream>
int main() {
for (int i = 10; i >= 1; i -= 3) {
std::cout << i << "\n";
}
std::cout << "Done\n";
return 0;
}
Practise this
Exercises for this lesson are in the C++ practice set.
Related lessons
- Conditions in C++: if, else and switchHow C++ chooses between paths with if, else if and else, switch with break, the ?: operator and the C++17 if with an initialiser, with runnable examples.8 min
- Arrays in C++Declaring fixed-size C++ arrays, zero-based indexing, initialising, range-for loops, std::array, 2D arrays and why out-of-bounds access is undefined behaviour.10 min
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.
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.