Repeating work with loops
C has three loops and a reason to pick each one: for when you count, while when you wait, and do while when the body must run once.
The counting loop
A for loop packs everything about counting into one line: where to start, when to stop, and how to step. for (i = 0; i < 5; i++) starts at zero, runs while i is under five, and adds one each pass.
Starting at zero is the convention in C because the first position of an array is position zero. Five passes of that loop visit positions zero through four.
The waiting loop
A while loop checks its condition before each pass and stops the moment the condition turns false. It is the right loop when you are not counting but repeating until something changes.
The loop that runs once first
A do loop checks its condition after the body, so the body always runs at least once. That is exactly what you want when the first pass produces the value the condition then tests.
One thing to watch in all three: make sure something inside the body moves the program toward the condition going false. A loop that never changes its condition runs forever.
The three parts of a for loop
A for header has three slots separated by semicolons: the initialiser runs once, the condition is checked before every pass, and the step runs after each pass. The body sits between the braces. Writing the order down once makes off-by-one errors much easier to spot.
Two statements change the flow from inside the body. break leaves the loop immediately, and continue skips the rest of the current pass and jumps to the step. Both are useful, but a loop that needs many of them is often clearer as a function with early returns.
How many passes, exactly
A for loop count is not always the number you first read. It follows from three things: where the counter starts, which comparison ends the loop, and how far each step moves it. From 0 while i < 5 stepping by one is five passes; from 1 while i <= 5 is also five, but the values differ. Write the first two and the last two values under the header before you run it.
The fastest check is to shrink the numbers. A loop that should print ten lines will print two if you change the bound to two, and the shape of the mistake is the same. Print the counter as the first thing in the body when a bound is in doubt; the output names the values the loop really used, which is more reliable than reasoning about it.
Nested loops and where break goes
In a nested loop the inner loop runs to completion for every single pass of the outer one. Three outer passes and three inner passes make nine lines, not six. The outer variable changes slowest, so it names the row and the inner one names the column.
break leaves only the loop it is written in. Inside the inner loop it ends that row and lets the outer loop continue with its next value. To leave both, set a flag the outer condition checks, or move the search into a function and return from it. A return is cleaner because it carries the answer out with it, and reaching for the flag is often a sign the nesting is too deep.
A semicolon after the for header — for (i = 0; i < 5; i++); — makes the loop body empty, and the statement below it runs once. An off-by-one bound is the other classic: i <= 5 runs six times when you meant five.
Counting up
#include <stdio.h>
int main(void) {
int i;
for (i = 1; i <= 3; i++) {
printf("Count %d\n", i);
}
return 0;
}Choosing the right loop
Use for when the number of passes is known or the loop is driven by a counter, while when it ends on a condition, and do while when the first pass has to happen before the test. The choice is less about syntax than about which shape makes the loop’s invariant obvious to the next reader.
Nested loops multiply: a 3-by-3 grid is nine passes, and a 100-by-100 grid is ten thousand. Keep the inner work small, and move anything that does not change with the loop variable outside it.
Try these next
- Print the numbers 10 down to 1 with a
forloop and a decrementing step. - Print a 3-by-3 multiplication table with two nested loops.
- Use
continueto skip the even numbers andbreakto stop at the first number over 20.
All three loops
Run it to see a counting for loop, a counting down while loop, and a do loop that runs before it checks. Then change the bounds.
Skip one, stop at five
Run it and count the lines. Then change the `continue` to a `break` and predict what disappears before you run it again.
Change the loop bounds and guess the number of lines before you run. Counting the passes in your head is the skill these loops are really teaching.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
Which loop is built for counting a known number of passes?
