Skip to content

6. Loops

What & why

Loops repeat work: process every item in a list, retry until input is valid, count from 1 to 100. C++ has four loop forms; you'll use the range-based for and the classic for most.

The classic for loop

for (int i = 0; i < 5; ++i) {
    std::cout << i << ' ';
}
// 0 1 2 3 4

Three parts, separated by ;:

  1. init — runs once: int i = 0
  2. condition — checked before each iteration: i < 5
  3. step — runs after each iteration: ++i

Variations:

for (int i = 10; i > 0; --i) { ... }        // count down
for (int i = 0; i < 100; i += 5) { ... }    // step by 5
for (int i = 0, j = 10; i < j; ++i, --j) { ... }   // two variables

The range-based for loop

Iterate over every element of a container:

#include <vector>

std::vector<int> scores{90, 72, 85};

for (int s : scores) {
    std::cout << s << '\n';
}

std::string word = "hello";
for (char c : word) {
    std::cout << c << '-';
}
// h-e-l-l-o-

Three ways to take each element:

for (auto x : v)         // copy — fine for ints and chars
for (auto& x : v)        // reference — lets you MODIFY the elements
for (const auto& x : v)  // const reference — read-only, no copy (use for strings/objects)
for (auto& s : scores) {
    s += 5;              // modifies the vector
}

This is the loop to reach for first. It can't go out of bounds.

while

Repeat while a condition holds — when you don't know the count in advance:

int n = 27;
int steps = 0;
while (n != 1) {
    n = (n % 2 == 0) ? n / 2 : 3 * n + 1;
    ++steps;
}
std::cout << "Collatz steps: " << steps << '\n';

do / while

Like while, but the body runs at least once. Perfect for input validation:

int age = 0;
do {
    std::cout << "Enter age (1-120): ";
    std::cin >> age;
} while (age < 1 || age > 120);

break and continue

for (int i = 1; i <= 10; ++i) {
    if (i % 2 == 0) {
        continue;         // skip the rest of this iteration
    }
    if (i > 7) {
        break;            // leave the loop entirely
    }
    std::cout << i << ' ';
}
// 1 3 5 7

break exits only the innermost loop. To leave nested loops, move them into a function and return.

Reading input until it runs out

int value;
int total = 0;
while (std::cin >> value) {     // stops at end of input or on a non-number
    total += value;
}
std::cout << "sum: " << total << '\n';

Test it with echo "1 2 3" | ./sum, or type numbers and press Ctrl+D (Ctrl+Z then Enter on Windows).

Reading line by line:

std::string line;
while (std::getline(std::cin, line)) {
    std::cout << line.size() << '\n';
}

Handling bad input

If std::cin >> number gets abc, the stream enters a fail state and every later read fails instantly — a common infinite loop. Recover like this:

#include <limits>

int n;
while (!(std::cin >> n)) {
    std::cout << "Not a number, try again: ";
    std::cin.clear();                                                   // reset the fail state
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // discard the bad line
}

Nested loops

for (int row = 1; row <= 3; ++row) {
    for (int col = 1; col <= 3; ++col) {
        std::cout << row * col << '\t';
    }
    std::cout << '\n';
}

Common mistakes

  • Off-by-one: for (int i = 0; i <= v.size(); ++i) reads one past the end. Use <, or better, a range-for.
  • Infinite loops: forgetting to update the variable in a while, or a std::cin fail state.
  • Modifying a copy: for (auto x : v) x *= 2; changes nothing. Use auto&.
  • Signed/unsigned comparison: v.size() is unsigned; comparing to int i gives a warning. Use std::size_t i, or std::ssize(v) (C++20).
  • Adding/removing elements from a vector while range-looping over it — undefined behavior.
  • Semicolon after the header: for (int i = 0; i < 5; ++i); loops over an empty statement.

Exercises

  1. Print the numbers 1–100, but print "Fizz" for multiples of 3, "Buzz" for multiples of 5, and "FizzBuzz" for both.
  2. Read integers until end-of-input and print the count, sum, minimum, maximum, and average.
  3. Number guessing game: pick a random number 1–100 (lesson 3), let the user guess with "higher"/"lower" hints, and count the guesses. Handle non-numeric input.
  4. Print a right triangle of * of height N using nested loops.
  5. Print all primes below 100 using a nested loop (try dividing by every number up to √n).
  6. Read a line of text and print it reversed, using an index loop that counts down. Watch out: what happens with std::size_t i = s.size() - 1; i >= 0; --i?

Recap

  • Classic for (init; cond; step) when you need an index or a custom step.
  • Range-for (for (const auto& x : v)) for "every element" — the safest default.
  • while for unknown counts; do/while when the body must run once.
  • break leaves the innermost loop; continue skips to the next iteration.
  • while (std::cin >> x) reads until input ends; clear() + ignore() recovers from bad input.

Next: Arrays & vectors →