3.5.7. Understanding Loops

Review

As loops increase in size and complexity, they can become difficult to understand and follow. A simple table sketched on paper or a whiteboard is valuable for helping programmers understand them. Create a column for every variable appearing in the loop - both in the loop's control and participating in operations in its body. This technique is beneficial when understanding how a for-loop's control variable interacts with operations in its body. Each table row represents one iteration or repetition of the loop.

As you study the program, "play computer" by walking through the code and manually performing the operations. A table helps us track the values saved in the variables during each iteration. You should calculate the value of each variable and enter it in the appropriate row and column of the table. The code fragment in the following example prints a table similar to the one proposed here, making it easy to check our answer after creating our table.

Example 1: A Simple For-Loop

int	number = 8;

for (int count = 1; count <= number; count++)
{
	cout << number << '\t' << count << endl;
	number /= 2;
}
number count Steps
7 1 (a), (b), (c), and (d)
3 2 (e), (f), and (g)
1 3 (h) and (i)
A simple for-loop. The loop in this example is small and understandable without assistance. But our goal is to learn a new technique, which is easier with a small, simple problem. The figure includes the "Steps" column to facilitate the example. There are no rules for building the tables, so you may include the steps if it helps you understand the loop's behavior. However, the primary goal is tracking the variables through their various operations. The ellipses represent code omitted for simplicity.
  1. Enter the initial values in the first row.
  2. for (...; count <= number; ...): 1 <= 7, so the loop body runs, printing the saved (initial) values.
  3. number /= 2: 7 / 2 = 3 - enter the value in the second row, number column.
  4. for (...; ...; count++): increments count - enter the updated value in the second row.
  5. for (...; count <= number; ...): 2 <= 3 and the loop runs, printing the saved values.
  6. number /= 2: 3 / 2 = 1, which we enter in the third row.
  7. for (...; ...; count++): increments count - enter the updated value in the third row.
  8. for (...; count <= number; ...): the test expression, 3 <= 1, is false, ending the loop.
  9. The program does not print this row.
The code fragment prints a partial table as it runs, but a "real" program typically doesn't, leaving the programmer to create the table without assistance.

Example 2: A Longer Table

#define MAX 5
#include <iostream>
using namespace std;

int main()
{
	int	number = 0;

	for (int count = MAX; count >= 1; count--)
		number += count * count;

	cout << "number = " << number << endl;

	return 0;
}
number count
0 5
25 4
41 3
50 2
54 1
55 0
A longer-running for loop. Like the previous example, we can understand this one without assistance. Still, two features make it incrementally more complex and, therefore, a natural progression. First, the program doesn't print a table, leaving that task to us. And second, the loop iterates a greater number of times, producing a longer table. When filling in the table, recalling the operation order of the various for-loop elements is essential, so you may find it convenient to review the for-loop logic diagram (part(c)). Try filling in the table before comparing it with the one above.

The program prints number = 55

Most IDEs include a debugger that helps build or replace the loop tables. We'll explore how to use the debugger with loops shortly.