3.5.2. multtab.cpp

Time: 00:04:52 | Download: Large Small | Streaming

To demonstrate the behavior of nested for-loops and how to coordinate them to form a solution, we set ourselves the problem of writing a program to print a 12 × 12 multiplication table.

Problem Algorithm / Pseudo Code
      j=1  j=2  j=3  ...  j=12
i=1     d    d    d  ...    d 
i=2    dd   dd   dd  ...   dd 
       .    .    .    .    .  
       .    .    .     .   .  
       .    .    .      .  .  
i=12  ddd  ddd  ddd  ...  ddd 
for i = 1, 2, ..., 12			// (a)
	for j = 1, 2, ..., 12		// (b)
		print i x j		// (c)
		next j (j = j + 1)	// (d)
	print new line			// (e)
	next i (i = i + 1)		// (f)
	reset j (j = 1)			// (g)
 
 
(a)(b)
Calculating and displaying table elements. The cursor's allowed movements on the console constrain the order programs can send output to (i.e., display output on) the console. Although retrograde (backward) cursor movement is possible, it's awkward at best. Furthermore, what constitutes a "backward" movement, vertically or horizontally, depends on the system's language. For this discussion, we assume a language reading left to right and top to bottom, implying that programs must display data in that order.
  1. Each 'd' represents a digit in the table. Numbers in the upper left part of the table consist of a single digit (1×1=1), numbers in the lower right part consist of three digits (12×12=144), with transitions from one to two digits, and from two to three digits in between. Labels displayed in orange denote the i and j values of each row and column, receptively, where each number = i×j. The ↵ characters explicitly indicate where the program must send a new line to the console.
  2. The outer or i loop controls row operations - those occurring once for each row. The inner or j loop controls column operations - those operations occurring for each column or number in a row. Following common practice, the pseudo-code uses indentation to indicate nesting (like the Python programming language). Therefore, print i×j is nested inside both loops, so it occurs for each number in each row. However, if the program prints a new line after each number, it would produce a single column of numbers rather than a table, so print new line is only nested in the outer or i loop, where it only runs after a row is complete.

The algorithm correctly calculates and logically places the multiplication values but does not separate them, forming a single, long sequence of digits for each row. Modifying the nested print statement to put spaces between the numbers fails to make an aesthetically pleasing and readable table. Part (a) above suggests the problem: the lengths of the numbers in the table vary from one to three digits. So, the number of spaces needed to separate two numbers depends on their lengths. Programmers sometimes print horizontal tab characters to create columns, but tabs have two problems. If the lengths of the individual data items vary too much, then the number of tabs separating them also varies, which is challenging to calculate. Furthermore, tabs always align the numbers on the left side, but aligning on the right is desirable - as if we were manually performing column addition.

Code Output
cout << '|' << setw(3) << 1 << '|' << endl;
cout << '|' << setw(3) << 12 << '|' << endl;
cout << '|' << setw(3) << 123 << '|' << endl;
cout << '|' << setw(3) << 1234 << '|' << endl;
|  1|
| 12|
|123|
|1234|
(a)(b)
Aligning table output with setw. setw is a C++ formatting manipulator. Recall that manipulators, like endl, are functions tailored to work with the << and >> operators. setw doesn't change the data, just how cout displays it. In this example, setw(3) formats the data to occupy at least three places, called the field width, and aligns it on the right. If the data length is less than three, it "pads" the unused space with blank or space characters. Programmers can use manipulators without arguments with the directive #include <iostream>, but manipulators with arguments, like setw, require a separate directive: #include <iomanip>. Please see setw later in the chapter for more detail.
Program Output
#include <iostream>
#include <iomanip>
using namespace std;

int main()
{
    for (int i = 1; i <= 12; i++)	// (a and f)
    {
        for (int j = 1; j <= 12; j++)	// (b, d, and g)
            cout << setw(5) << i * j;	// (c)
        cout << endl;			// (e)
    }

    return 0;
}
    1    2    3    4    5    6    7    8    9   10   11   12
    2    4    6    8   10   12   14   16   18   20   22   24
    3    6    9   12   15   18   21   24   27   30   33   36
    4    8   12   16   20   24   28   32   36   40   44   48
    5   10   15   20   25   30   35   40   45   50   55   60
    6   12   18   24   30   36   42   48   54   60   66   72
    7   14   21   28   35   42   49   56   63   70   77   84
    8   16   24   32   40   48   56   64   72   80   88   96
    9   18   27   36   45   54   63   72   81   90   99  108
   10   20   30   40   50   60   70   80   90  100  110  120
   11   22   33   44   55   66   77   88   99  110  121  132
   12   24   36   48   60   72   84   96  108  120  132  144
 
 
 
multtab.cpp program and output.
  1. (a) Begin the outer loop, initialize i to 1
    1. (b) Begin the inner or nested loop, initialize j to 1
      1. (c) Working from right to left (in the arrow direction) - calculate, format, and print i × j
        • Calculate the product
        • Format the product to display in a field five characters wide and pad narrower data with spaces on the left
        • Prints the formatted product
        • The inner cout statement does not have an endl, so all output is placed on one line, filled left to right
      2. (d) Increments j without changing i and repeats the inner loop
    2. (e) The cout prints an endl, moving the cursor down one line and to the left edge of the console
  2. (f) Increments i and repeats the outer loop
  3. (g) Resets j to 1 and repeats the inner loop
  4. The loops continues until both i and j reach 13