8.2 Iteration: for, while, do … while, and repeat … until Loops
Key Takeaways
- A loop needs three things: initialize the loop variable, test it in the condition, and update it toward termination.
- for ( int i ← a; i < b; i ← i + 1 ) runs b − a times; changing < to ≤ adds one more iteration.
- Nested loops multiply: an outer loop of m passes and an inner loop of n passes run the inner body m × n times; an inner loop from 1 to i, for i from 1 to n, runs n(n + 1)/2 times.
- Repeated statements that differ only by a number can be replaced by a loop whose variable supplies that number.
- do … while ( c ) is equivalent to repeat … until ( not c ); both run their body at least once.
What this competency asks
Within the sequence, selection, and iteration competency, ETS lists tracing, identifying inputs for given outputs, describing purpose, supplying missing code, and identifying equivalent code. For loops specifically, you should be able to:
- Convert code that does not use iteration to equivalent code that uses iteration.
- Trace code with
for,while,do … while, and similar loops, and convert from one type of loop to another (a discussion question).
Anatomy of a loop
Every loop has three parts. A missing or wrong part causes most loop bugs.
- Initialization: set the loop variable, as in
int i ← 0. - Condition: decide whether to run the body again, as in
i < n. - Update: move toward ending, as in
i ← i + 1.
for ( int i ← 0; i < 5; i ← i + 1 ) // all three parts in the header
print i // print a space after the value
end for
int k ← 1 // initialization
while ( k ≤ 100 ) // condition
k ← k * 2 // update
end while
The for loop prints 0 1 2 3 4. The while loop doubles k through 2, 4, 8, 16, 32, 64, and 128, and stops with k = 128 after 7 passes.
Counting iterations
| Header | Values of i | Iterations |
|---|---|---|
for ( int i ← 0; i < n; i ← i + 1 ) | 0 … n − 1 | n |
for ( int i ← 1; i ≤ n; i ← i + 1 ) | 1 … n | n |
for ( int i ← 1; i < n; i ← i + 1 ) | 1 … n − 1 | n − 1 |
for ( int i ← 0; i ≤ n; i ← i + 1 ) | 0 … n | n + 1 |
for ( int i ← 0; i < n; i ← i + 2 ) | 0, 2, 4, … | ⌈n / 2⌉ |
for ( int i ← n; i > 0; i ← i - 1 ) | n … 1 | n |
After a for loop ends, the loop variable holds the first value that failed the test. For example, i is n after the first header in the table, although in ETS pseudocode a variable declared in the header is not normally used after the loop.
Nested loops
int count ← 0
for ( int i ← 1; i ≤ 4; i ← i + 1 )
for ( int j ← 1; j ≤ i; j ← j + 1 )
count ← count + 1
end for
end for
The inner loop runs 1, 2, 3, and then 4 times, so count = 1 + 2 + 3 + 4 = 10, or n(n + 1)/2 with n = 4. If the inner loop always ran 5 times, the body would run 4 × 5 = 20 times.
Pre-test and post-test loops
| Loop | Test | Minimum runs | Continues while… |
|---|---|---|---|
while ( c ) … end while | Before the body | 0 | c is true |
for ( … ; c ; … ) … end for | Before the body | 0 | c is true |
do … while ( c ) | After the body | 1 | c is true |
repeat … until ( c ) | After the body | 1 | c is false (stops when c becomes true) |
int k ← 5
repeat
k ← k * 2
until ( k ≥ 20 )
Pass 1: k = 10, and 10 ≥ 20 is false, so the loop repeats. Pass 2: k = 20, and 20 ≥ 20 is true, so it stops. The body runs twice and k ends at 20.
Post-test loops suit tasks that must happen at least once, such as showing a menu or prompting for input until it is valid.
Converting code into a loop
Repeated statements that differ only in a number can be replaced by a loop:
// Without iteration
print 3
print 6
print 9
print 12
print 15
// With iteration
for ( int i ← 1; i ≤ 5; i ← i + 1 )
print 3 * i
end for
To convert, find what changes from line to line (here 3, 6, 9, …, which is 3 × 1, 3 × 2, and so on), make the loop variable produce it, and set the bounds so the loop runs the same number of times. Verify both the first and the last output.
Converting between loop types
for to while. Move the initialization before the loop and the update to the end of the body:
int i ← 0
while ( i < n )
total ← total + list[i]
i ← i + 1
end while
while to do … while. These are equivalent only if the condition is true the first time. Otherwise the do … while runs once too often. A guarding if makes them equivalent.
do … while to repeat … until. Negate the condition: do … while ( x < 10 ) is equivalent to repeat … until ( x ≥ 10 ).
Leaving a loop early
Many languages provide break (exit the loop immediately) and continue (skip to the next iteration). They are not part of the ETS notation table. ETS-style code usually exits early by return-ing from a procedure, or by making the condition false with a flag such as while ( ( i < n ) and ( not found ) ).
Common loop bugs
| Bug | Example | Result |
|---|---|---|
| Off by one | i ≤ n with a 0-based array of length n | Reads the invalid index n |
| Missing update | No i ← i + 1 in a while loop | Infinite loop |
| Update in the wrong direction | while ( k > 0 ) with k ← k + 1 | Infinite loop |
| Skipped target | while ( x ≠ 10 ) with x going 1, 3, 5, … | Never equals 10, so it never stops |
| Floating-point condition | while ( v ≠ 1.0 ) with v increased by 0.1 | Round-off makes v skip exactly 1.0 |
| Wrong initialization | Accumulator reset inside the loop | Only the last value counts |
Consider the following segment.
How many times does the body run, and what is the final value of k?int k ← 5
repeat
k ← k * 2
until ( k ≥ 20 )
A segment consists of the five statements print 4, print 8, print 12, print 16, print 20, in that order. Which loop produces the same output?
What is the value of count after this segment runs?
int count ← 0
for ( int i ← 1; i ≤ 5; i ← i + 1 )
for ( int j ← 1; j ≤ i; j ← j + 1 )
count ← count + 1
end for
end for
Which while loop is equivalent to for ( int i ← 2; i ≤ 10; i ← i + 2 ) with body print i?