Nested Loops

You might remember the multiplication table, generally rendered as a 10 by 10 table containing the products of first 10 natural numbers. This is what it usually looks like:

1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90100

The primary task of this chapter is to output a multiplication table similar to the one above. It will not be a table with lines and cells, since the only intention is to output all the products and, if possible, to output them in a tabular form.

An easy way to complete the given task would be to write out each row of the table by using a literal string. For example, the first row could be written out by:

cout << "1 2 3 4 5 6 7 8 9 10" << endl;

Similarly, the sixth row could be written out by:

cout << "6 12 18 24 30 36 42 48 54 60" << endl;

Yet, such a solution to this problem would miss the intention of the given task. A solution like this would make us calculate and type in all the numbers that make up the table (i.e. all the products) ourselves, manually. We certainly do not want to do that, since we are trying to learn how to make a computer do all the calculations for us (however simple those calculations might be). Accordingly, let us add another requirement to our task: we want the computer to calculate all the products that make up the table.

This new requirement provides the benefit of preventing an error in calculating or typing in the results because if the computer does calculations for us, we should expect the results to be absolutely accurate and without any typing errors. Finally, what would the purpose of using a computer be if we had to calculate all the results manually?

Perhaps the task of printing out the entire table is too complicated to deal with all at once, so let us simplify our problem by focusing on printing out just the sixth row of the multiplication table. The program has to print out 10 numbers that make up that row. After a while, one may come up with an idea that a for loop can be used to repeat printing out a product 10 times:

    for (int column=1; column<=10; column++)
        cout << 6*column << " ";

We have already done something similar in the chapter if and for Statements, except that here the program has to print out all the numbers in a single line. To separate each number from the next one, a string containing one space character is used. The output of this piece of code should look like this:

6 12 18 24 30 36 42 48 54 60

We have succeeded in printing out the sixth row, but what about the other rows? We could use another for loop to print out a row ten times. Let us write that for loop only:

    for (int row=1; row<=10; row++)
        {
        // here we need to insert the code for printing out a row
    
        cout << endl;
        }

This for loop ends with a cout statement in order to move on to the next output line, after one row of the table has been printed out. This causes each row of the table to be printed out in its own output line.

So far, we have written two pieces of code: the piece that prints the sixth row and the piece that repeats printing a row. Let us now merge the two given code fragments together:

    for (int row=1; row<=10; row++)
        {
        for (int column=1; column<=10; column++)
            cout << row*column << " ";
        cout << endl;
        }

As you can notice, a for loop can reside inside another for loop. Together they are called nested for loops, while individually they are called the outer for loop and the inner for loop. In addition to this, there can even be a for loop residing inside a second for loop which resides inside a third for loop, etc. This means that for loops can in fact be nested many times inside each other.

Pay attention to a small change in a piece of code for printing out a row: originally, we used a product 6*column to print out the sixth row. If we were to leave it like that, we would have printed out the sixth row ten times. To print out each row of the table, we have to use the product row*column which does exactly what we want. The variable row will assume a value of the row's number in each iteration of the outer for loop.

The output of this piece of code should be exactly this:

1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100

As you might have noticed, some lines are longer and some are shorter than the others, so the table does not look well organized. It does not even look like a table, but at least all the products seem to be correct.

To remedy this problem, we need each printed number to have equal "width", which can be accomplished by using the setw manipulator. We will soon look into it in more detail, but for the time being two things have to be done:

a) change the line that prints out the products into:

        cout << setw(3) << row*column << " ";

b) at the beginning of the program, add a line:

#include <iomanip>

Here is the code of the entire program:

#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
    for (int row=1; row<=10; row++)
        {
        for (int column=1; column<=10; column++)
            cout << setw(3) << row*column << " ";
        cout << endl;
        }
}

The exact output is:

  1   2   3   4   5   6   7   8   9  10
  2   4   6   8  10  12  14  16  18  20
  3   6   9  12  15  18  21  24  27  30
  4   8  12  16  20  24  28  32  36  40
  5  10  15  20  25  30  35  40  45  50
  6  12  18  24  30  36  42  48  54  60
  7  14  21  28  35  42  49  56  63  70
  8  16  24  32  40  48  56  64  72  80
  9  18  27  36  45  54  63  72  81  90
 10  20  30  40  50  60  70  80  90 100

It looks just as we wanted it to.

Let us explain the nested for loops in a slightly different manner. Think as if we were to execute the given program manually. In that case, the variable row is being assigned values from 1 to 10 by the outermost for loop. However, for each iteration of outermost loop (and also for each value of the row variable), the innermost for loop will iterate 10 times, assigning a value from 1 to 10 to the column variable. Thus, there will be 10 times 10 iterations of the innermost cout statement, printing out one hundred numbers. In this manner, the two nested loops make row and column variables assume all the possible combinations of two values from 1 to 10. If you still have any uncertainties, try stepping through the program with a debugger.

To solve this task, we had to use two nested for loops, which are together called a double loop. Generally speaking, whenever we need to process data from a table, we are likely to require at least a double loop in order to process all the table's values. What do we mean by 'at least'? Well, three nested loops make a triple loop, four of them make a quadruple loop and so on...

Warning! It goes without saying that you should not use the same variable name for inner and outer for loop.