Loops
Learn how for, while, and do-while let a C++ program repeat work, and how break, continue, and nesting control that repetition.
Loops allow a C++ program to execute a block of code repeatedly while a condition is satisfied or while iterating through a sequence of values. The main loop constructs in C++ are for, while, and do-while. C++ also provides range-based for loops, which are covered separately as a modern form of iteration.
1. Why Loops Are Used
Without a loop, repeating an operation requires writing the same code multiple times.
Printing the same line five times by repeating the statement by hand.
A loop makes the repetition explicit.
The same five-line output produced by a single loop instead of five repeated statements.
Conceptually, every loop initializes, checks a condition, executes a body, updates, and checks again.
std::cout << "Hello\n";
std::cout << "Hello\n";
std::cout << "Hello\n";
std::cout << "Hello\n";
std::cout << "Hello\n";for (int i = 0; i < 5; ++i)
{
std::cout << "Hello\n";
}Start
|
v
Initialize
|
v
Check condition
/ \\
false true
| |
v v
Exit Execute body
|
v
Update
|
+------> Check condition2. The for Loop
The for loop is commonly used when the iteration process has a clear initialization, condition, and update.
The general syntax of a for loop.
Prints the values 0 through 4, one per line.
Output: 0 1 2 3 4
for (initialization; condition; update)
{
// loop body
}for (int i = 0; i < 5; ++i)
{
std::cout << i << '\n';
}3. Parts of a for Loop
Consider the same loop again. It contains three parts.
A for loop with initialization, condition, and update highlighted below.
The three parts of a for loop and what each one is responsible for.
The execution flow: initialize once, then repeatedly check, execute, and update.
for (int i = 0; i < 5; ++i)
{
std::cout << i << '\n';
}Part | Example | Purpose
Initialization | int i = 0 | Runs before the first iteration
Condition | i < 5 | Determines whether another iteration occurs
Update | ++i | Runs after each iterationi = 0
|
v
i < 5? ---- false ---> Exit
|
yes
|
v
Execute body
|
v
++i
|
+-----------> i < 5?4. Execution Order of for
Consider a loop that runs three times.
A three-iteration for loop.
The conceptual execution order: initialize once, then check-execute-update repeatedly until the condition fails.
The update expression runs after the body of each completed iteration.
for (int i = 0; i < 3; ++i)
{
std::cout << i << '\n';
}int i = 0
Check i < 3
↓
Execute body
↓
++i
Check i < 3
↓
Execute body
↓
++i
Check i < 3
↓
Execute body
↓
++i
Check i < 3
↓
false
↓
Exit5. while Loop
A while loop repeatedly executes a block as long as its condition is true.
The general syntax of a while loop.
Prints 0 through 4; the loop variable is initialized before the loop and updated inside the body.
Output: 0 1 2 3 4
while (condition)
{
// loop body
}int i = 0;
while (i < 5)
{
std::cout << i << '\n';
++i;
}6. How while Works
The condition is checked before every iteration.
Because the condition is checked first, a while loop can run zero times.
Therefore, a while loop can execute zero times.
The body is never executed because the initial condition (10 < 5) is false.
Start
|
v
Check condition
/ \\
false true
| |
v v
Exit Execute body
|
v
Repeat
|
+----> Check conditionint i = 10;
while (i < 5)
{
std::cout << i;
}7. do-while Loop
A do-while loop executes its body before checking the condition.
The general syntax of a do-while loop, including the trailing semicolon after the condition.
Prints 0 through 4; the body runs first, then the condition is checked.
Output: 0 1 2 3 4
do
{
// loop body
}
while (condition);int i = 0;
do
{
std::cout << i << '\n';
++i;
}
while (i < 5);8. Important Property of do-while
Unlike for and while, a do-while loop executes its body at least once.
Even though i < 5 is false from the start, the body executes once before the condition is ever checked.
Output: Executed
int i = 10;
do
{
std::cout << "Executed\n";
}
while (i < 5);9. for vs while vs do-while
The three loop constructs differ in when the condition is checked and how they are typically written.
A side-by-side comparison of the three loop forms.
Typical patterns matching each loop's common use.
Feature | for | while | do-while
Condition checked | Before iteration | Before iteration | After iteration
Can execute zero times | Yes | Yes | No
Initialization syntax | Built into loop | Usually before loop | Usually before loop
Update syntax | Built into loop | Usually inside body | Usually inside body
Common use | Count-controlled loops | Condition-controlled loops | At-least-once operationsfor (int i = 0; i < 10; ++i) { /* known/count-based repetition */ }
while (condition) { /* repeat while condition remains true */ }
do { /* execute at least once */ } while (condition);10. Infinite Loops
A loop becomes infinite when its termination condition never becomes false.
A while loop whose condition is always true.
An infinite for loop written with all three sections left empty.
Infinite loops can be intentional (e.g. while (true) { /* continue until an explicit exit condition */ }) or accidental — for example, a while loop whose condition variable is never updated inside the body never becomes false and never terminates.
while (true)
{
// Runs indefinitely
}for (;;)
{
// Runs indefinitely
}11. break
The break statement immediately terminates the nearest enclosing loop.
Stops the loop as soon as i reaches 5, so only 0 through 4 print.
Output: 0 1 2 3 4 The flow when break is reached.
break exits only the nearest enclosing loop or switch.
for (int i = 0; i < 10; ++i)
{
if (i == 5)
{
break;
}
std::cout << i << '\n';
}i = 5
|
v
condition true
|
v
break
|
v
exit loop12. continue
continue skips the remaining statements in the current iteration and proceeds to the next iteration.
When i == 2, the output statement is skipped, so 2 never prints.
Output: 0 1 3 4
for (int i = 0; i < 5; ++i)
{
if (i == 2)
{
continue;
}
std::cout << i << '\n';
}13. continue in a for Loop
For a for loop, continue transfers control to the loop's update expression, and then the condition is checked.
Even when continue fires, the update expression (++i) still runs before the condition is rechecked.
continue does not skip the update — it jumps to it.
This is different from simply jumping directly to the next body execution.
for (int i = 0; i < 5; ++i)
{
if (i == 2)
{
continue;
}
std::cout << i << '\n';
}Body
|
|-- continue
| |
| v
| ++i
| |
+-------+----> condition14. continue in a while Loop
With a while loop, continue moves to the next condition check. Therefore, the loop variable must still be updated correctly before the continue, or the loop can fail to progress.
A safer structure updates the loop variable before checking the skip condition.
i is incremented before the continue check, so every iteration still makes progress toward the loop's termination.
The important rule is: make sure every loop iteration can make progress toward termination.
int i = 0;
while (i < 5)
{
++i;
if (i == 2)
{
continue;
}
std::cout << i << '\n';
}15. Nested Loops
A loop can contain another loop.
The outer loop runs 3 times; for each outer iteration, the inner loop runs 4 times.
Three rows of four asterisks each.
The outer loop controls the rows. The inner loop controls the columns. For every outer-loop iteration, the inner loop completes its iterations.
for (int row = 0; row < 3; ++row)
{
for (int column = 0; column < 4; ++column)
{
std::cout << "* ";
}
std::cout << '\n';
}* * * *
* * * *
* * * *16. Multiple Expressions in a for Loop
The initialization and update sections can contain multiple expressions separated by the comma operator.
Two variables, i and j, are initialized and updated together in a single for loop.
i counts up while j counts down, in lockstep.
This can be useful when two loop-control variables need to progress together. However, avoid making the loop unnecessarily complicated.
for (int i = 0, j = 10; i < 5; ++i, --j)
{
std::cout << i << " " << j << '\n';
}0 10
1 9
2 8
3 7
4 617. Empty Parts of a for Loop
The three sections of a for loop are individually optional.
Initialization is left empty because i is already declared and initialized outside the loop.
Both initialization and update are left empty; the update is done manually inside the body instead.
This is valid but generally less clear than a normal for loop.
int i = 0;
for (; i < 5; ++i)
{
std::cout << i << '\n';
}int i = 0;
for (; i < 5;)
{
std::cout << i << '\n';
++i;
}18. Loop Control Using Boolean Conditions
A loop condition can directly use a Boolean variable.
The loop continues while running is true, and ends once something inside the body sets it to false.
This can make the termination condition easy to understand.
bool running = true;
while (running)
{
// work
running = false;
}19. Off-by-One Errors
An off-by-one error occurs when a loop executes one time too many or one time too few.
This executes 11 times, producing values from 0 through 10, because the boundary is inclusive (<=).
If exactly 10 iterations are required, the boundary should be exclusive instead.
This executes exactly 10 times: 0 through 9.
A useful pattern is for (int i = 0; i < count; ++i) when iterating count times.
for (int i = 0; i <= 10; ++i)
{
std::cout << i << '\n';
}for (int i = 0; i < 10; ++i)
{
std::cout << i << '\n';
}20. Pre-Increment vs Post-Increment in Loops
Both ++i; and i++; are commonly seen as the update expression of a loop.
For a simple integer loop counter, both normally produce the same final sequence of values.
The difference between prefix and postfix increment concerns the value of the increment expression itself. In ordinary loop-control code where that resulting expression value is not used, the practical result is usually the same.
for (int i = 0; i < 5; ++i) { /* ... */ }
for (int i = 0; i < 5; i++) { /* ... */ }21. Looping Backward
A loop can count downward.
Counts down from 5 to 1.
Output: 5 4 3 2 1 Be careful when using unsigned types for descending loops because unsigned values cannot become negative — a pattern such as for (std::size_t i = 10; i >= 0; --i) does not terminate as intended because std::size_t is unsigned.
for (int i = 5; i > 0; --i)
{
std::cout << i << '\n';
}22. Choosing the Appropriate Loop
A useful decision process helps pick the right loop construct for a given situation.
Choose for when there is a clear counter, while when a condition should be checked up front, and do-while when the body must run at least once.
Prefer for when iteration has a clear counter.
Prefer while when repetition depends primarily on a condition.
Prefer do-while when the operation must happen at least once.
Need repetition?
|
yes
|
Do you have a clear
counter/init/update?
/ \\
yes no
| |
for Condition checked
before each iteration?
/ \\
yes no
| |
while do-whilefor (int i = 0; i < 100; ++i) { /* ... */ }while (inputIsValid) { /* ... */ }do { /* operation */ } while (condition);23. Best Practices
A few habits keep loops clear, correct, and easy to maintain.
1. Use meaningful loop variables — simple counters like for (int i = 0; i < count; ++i); for nested loops, name them descriptively, such as row and column.
Descriptive loop-variable names make nested loops easier to follow than generic i and j.
2. Make termination obvious — prefer for (int i = 0; i < count; ++i) over unnecessarily complicated loop conditions.
3. Avoid accidental infinite loops — ensure the condition eventually becomes false unless an infinite loop is intentional, and make sure the loop variable is updated on every path through the body (including before any continue).
4. Use braces — even a single-statement body should be wrapped, as in while (condition) { doSomething(); }, so a later edit or a stray semicolon cannot silently create an empty loop body.
5. Keep loop bodies focused — if a loop becomes extremely large or complicated, consider restructuring the code.
6. Be precise about the loop boundary — decide deliberately whether the upper bound is inclusive (<=) or exclusive (<), since this determines exactly how many times the loop runs.
7. Be careful mixing unsigned counters with descending loops or with -- past zero, since unsigned types wrap instead of going negative.
8. Keep nesting shallow where possible — deeply nested loops can become difficult to understand and maintain.
for (int row = 0; row < rows; ++row)
{
for (int column = 0; column < columns; ++column)
{
/* ... */
}
}24. Complete Example
A complete program combining validation with a for loop.
Reads a number, validates it, and then uses a for loop to print every value from 1 up to that number.
Read number from the user.
If number is not positive, print an error and exit early.
Otherwise, loop from 1 through number inclusive, printing each value.
The validation decision and the loop's repetition are two distinct responsibilities in the program.
#include <iostream>
int main()
{
int number;
std::cout << "Enter a positive number: ";
std::cin >> number;
if (number <= 0)
{
std::cout << "Invalid number\n";
return 0;
}
std::cout << "Numbers from 1 to " << number << ":\n";
for (int i = 1; i <= number; ++i)
{
std::cout << i << ' ';
}
std::cout << '\n';
return 0;
}Input
|
v
Is number valid?
|
+---- No ----> Invalid
|
Yes
|
v
for loop
|
+--> 1
+--> 2
+--> 3
...
+--> number
|
v
Continue25. Quick Reference
A summary of the loop-related constructs covered in this topic.
Quick reference for every loop construct and control statement discussed in this topic.
Construct | Purpose
for | Count/control repetition with initialization, condition, and update
while | Repeat while a condition is true
do-while | Execute once, then repeat while condition is true
break | Immediately exit the nearest loop
continue | Skip the rest of the current iteration
Nested loop | Loop inside another loop
for (;;) | Intentional infinite for loop
while (true) | Intentional infinite while loop26. Mental Model
All three fundamental loops can be understood through condition + body + repetition.
for: initialize once, then repeatedly check the condition, run the body, and update.
while: check the condition first, every time, before running the body.
do-while: run the body first, then check the condition to decide whether to run it again.
The key difference is where the condition is checked.
What is the key behavioral difference between a while loop and a do-while loop in terms of how many times the body can execute?
A while loop checks its condition before the first iteration, so its body can execute zero times. A do-while loop checks its condition after the first iteration, so its body always executes at least once, even if the condition is false from the start.
In a for loop, what happens when continue is executed inside the body — does control jump straight back to the condition, or somewhere else first?
continue transfers control to the loop's update expression first (for example ++i), and only then is the condition checked again. It does not skip the update.
Why does for (std::size_t i = 10; i >= 0; --i) fail to terminate as a programmer might expect for a descending loop?
std::size_t is an unsigned type, so it can never become negative. When i reaches 0 and is decremented again, it wraps around to a very large positive value instead of going to -1, so the condition i >= 0 is always true and the loop never terminates.
How many times does for (int i = 0; i <= 10; ++i) execute, and what values of i does it print? How would you change it to execute exactly 10 times instead?
It executes 11 times, printing i from 0 through 10 inclusive, because the boundary condition is inclusive (<=). To execute exactly 10 times, change the condition to an exclusive boundary: for (int i = 0; i < 10; ++i), which prints 0 through 9.
What is the difference between break and continue inside a loop?
break immediately terminates the nearest enclosing loop (or switch) entirely, so no further iterations run. continue only skips the remaining statements in the current iteration and moves on to the next iteration (running the update and re-checking the condition, for a for loop).
What does this nested loop print?
00 01 02 10 11 12 — for each of the two outer iterations (row 0 and row 1), the inner loop runs completely through columns 0, 1, and 2 before the outer loop advances.
Write a program that repeatedly prompts the user to enter a number until they enter a positive number, using a do-while loop so the prompt appears at least once.
A do-while loop is appropriate here because the prompt must appear at least once regardless of what the user eventually enters; the condition (number <= 0) is checked only after each attempt, causing the loop to repeat until a positive number is given.
What does this while loop print, and why doesn't it get stuck when continue runs?
It prints "1 2 4 ". The loop variable i is incremented at the top of the body, before the continue check, so every iteration still makes progress toward the condition i < 4 becoming false — continue only skips the std::cout statement when i == 3, it does not skip the increment.
Write a for loop that counts down from a variable named start to 1 (inclusive), printing each value, using a signed int loop counter.
Using a signed int for the descending counter avoids the unsigned wraparound problem: the loop condition i > 0 correctly becomes false once i reaches 0, so the loop stops cleanly instead of wrapping to a huge value.
for
Initialize
↓
Condition
↓
Body
↓
Update
↓
Conditionwhile
Condition
↓
Body
↓
Conditiondo-while
Body
↓
Condition
↓
Bodyfor (int row = 0; row < 2; ++row)
{
for (int column = 0; column < 3; ++column)
{
std::cout << row << column << " ";
}
}
std::cout << '\n';int i = 0;
while (i < 4)
{
++i;
if (i == 3)
{
continue;
}
std::cout << i << ' ';
}