Step 1 of 5 · Reading · ~4 min
Learn
Control Flow
Loops
By the end of this lesson you can repeat work with for, while and do-while, choose a start, a boundary and a step on purpose, and keep a running total in a type big enough to hold it.
for: init, condition, step
for (int k = 20; k > 0; k -= 5) {
printf("%d ", k);
}
/* prints: 20 15 10 5 */
for (init; condition; step) runs init once, tests the condition before every pass (false means stop, so the body may run zero times), and runs the step after every body. The step is any expression: k++ counts by one, k -= 5 counts down by five, k *= 2 doubles. Declaring k inside the parentheses limits it to the loop.
The boundary: < or <=
Counting multiples of 4 up to a limit of 20:
for (int m = 0; m <= 20; m += 4) /* 0 4 8 12 16 20 */
for (int m = 0; m < 20; m += 4) /* 0 4 8 12 16 -- 20 is lost */
< stops before the limit, <= includes it. The two only disagree when the loop variable lands exactly on the limit, so a test with a limit the step never hits (say 18) cannot tell them apart. Array walks use i < n because the last index is n-1; counting "up to and including n" uses <=.
The accumulator, and its type
An accumulator is a variable declared before the loop, given a starting value, and updated each pass. Here it is a product, 1 x 2 x ... x 13:
int small = 1;
long long fact = 1;
for (int j = 1; j <= 13; j++) {
small *= j;
fact *= j;
}
printf("%d\n", small); /* 1932053504 -- wrong, int overflowed */
printf("%lld\n", fact); /* 6227020800 -- right */
The true answer is over 2.1 billion, so int overflows. The program compiles, runs and prints a plausible-looking wrong number; nothing warns you. The fix is the type of the accumulator, chosen before the loop, printed with %lld. The starting value matters as much: a sum starts at 0, a product at 1, and an accumulator you forget to initialise starts at whatever garbage the memory held.
while and do-while
while suits loops whose count you do not know in advance. Peeling the digits of 4096:
int x = 4096, digits = 0;
while (x > 0) { /* 4096 -> 409 -> 40 -> 4 -> 0 */
x /= 10;
digits++;
}
/* digits == 4 */
do { ... } while (cond); tests at the bottom, so the body always runs at least once, even when the condition is false from the start. Note its closing semicolon.
break, continue, and empty loops
break leaves the innermost loop; continue skips to the next pass. while (1) and for (;;) (every clause empty, condition taken as true) both loop forever until a break. One trap goes the other way: for (int k = 0; k < 3; k++); with a semicolon after the parenthesis has an empty body. It spins three times doing nothing, and the block below runs once. gcc -Wall warns about it.
Common mistakes
<instead of<=: the last value is dropped whenever the limit is itself one of the values visited. It looks right on every input the step skips over, and wrong on the rest.- Wrong start or step: starting at 0 or stepping by 1 visits numbers you were not asked for, and the total comes out too large.
intaccumulator: correct for small inputs, silently wrong once the total passes 2,147,483,647. Uselong longand%lld.- Uninitialised or misplaced accumulator: declared without
= 0, or reset inside the loop, so the total is garbage or only the last value.
Your exercise
Read N and print the sum of the odd numbers from 1 up to N (N itself counts if it is odd). The starter reads N; you write the loop and the print. The likeliest wrong answer is off by the final odd number because the boundary excluded N, and large N needs a long long total.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…