|

Loops
may be nested, with one loop sitting in the body
of another. The inner loop will be executed in full
for every execution of the outer loop. Listing 7.14
illustrates writing marks into a matrix using nested
for loops.
Listing
7.14. Illustrates nested for loops.
1:
//Listing 7.14
2:
//Illustrates nested for loops
3:
4:
#include <iostream.h>
5:
6:
int main()
7:
{
8:
int rows, columns;
9:
char theChar;
10:
cout << "How many rows? ";
11:
cin >> rows;
12:
cout << "How many columns? ";
13:
cin >> columns;
14:
cout << "What character? ";
15:
cin >> theChar;
16:
for (int i = 0; i<rows; i++)
17:
{
18:
for (int j = 0; j<columns; j++)
19:
cout << theChar;
20:
cout << "\n";
21:
}
22:
return 0;
23:
}
Output:
How many rows? 4
How many columns? 12
What character? x
xxxxxxxxxxxx
xxxxxxxxxxxx
xxxxxxxxxxxx
xxxxxxxxxxxx
Analysis: The user is prompted for
the number of rows and columns and for a character
to print. The first for loop, on line 16, initializes
a counter (i) to 0, and then the body of the outer
for loop is run. On line 18, the first line of the
body of the outer for loop, another for loop is
established. A second counter (j) is also initialized
to 0, and the body of the inner for loop is executed.
On line 19, the chosen character is printed, and
control returns to the header of the inner for loop.
Note that the inner for loop is only one statement
(the printing of the character). The condition is
tested (j < columns) and if it evaluates true,
j is incremented and the next character is printed.
This continues until j equals the number of columns.
Once
the inner for loop fails its test, in this case
after 12 Xs are printed, execution falls through
to line 20, and a new line is printed. The outer
for loop now returns to its header, where its condition
(i < rows) is tested. If this evaluates true,
i is incremented and the body of the loop is executed.
In
the second iteration of the outer for loop, the
inner for loop is started over. Thus, j is reinitialized
to 0 and the entire inner loop is run again.
The
important idea here is that by using a nested loop,
the inner loop is executed for each iteration of
the outer loop. Thus the character is printed columns
times for each row.
NOTE: As an aside, many C++ programmers
use the letters i and j as counting variables. This
tradition goes all the way back to FORTRAN, in which
the letters i, j, k, l, m, and n were the only legal
counting variables. Other programmers prefer to
use more descriptive counter variable names, such
as Ctrl and Ctr2. Using i and j in for loop headers
should not cause much confusion, however.
Scoping
in for Loops
You
will remember that variables are scoped to the block
in which they are created. That is, a local variable
is visible only within the block in which it is
created. It is important to note that counting variables
created in the header of a for loop are scoped to
the outer block, not the inner block. The implication
of this is that if you have two for loops in the
same function, you must give them different counter
variables, or they may interfere with one another.
Summing
Up Loops
In
Unit 5, "Functions," you learned how to solve the
Fibonacci series problem using recursion. To review
briefly, a Fibonacci series starts with 1, 1, 2,
3, and all subsequent numbers are the sum of the
previous two:
1,1,2,3,5,8,13,21,34...
The
nth Fibonacci number is the sum of the n-1 and the
n-2 Fibonacci numbers. The problem solved in unit
5 was finding the value of the nth Fibonacci number.
This was done with recursion. Listing 7.15 offers
a solution using iteration.
Listing
7.15. Solving the nth Fibonacci numberusing
iteration.
1:
// Listing 7.15
2:
// Demonstrates solving the nth
3:
// Fibonacci number using iteration
4:
5:
#include <iostream.h>
6:
7:
typedef unsigned long int ULONG;
8:
9:
ULONG fib(ULONG position);
10:
int main()
11:
{
12:
ULONG answer, position;
13:
cout << "Which position? ";
14:
cin >> position;
15:
cout << "\n";
16:
17:
answer = fib(position);
18:
cout << answer << " is the ";
19:
cout << position << "th Fibonacci number.\n";
20:
return 0;
21:
}
22:
23:
ULONG fib(ULONG n)
24:
{
25:
ULONG minusTwo=1, minusOne=1, answer=2;
26:
27:
if (n < 3)
28:
return 1;
29:
30:
for (n -= 3; n; n—)
31:
{
32:
minusTwo = minusOne;
33:
minusOne = answer;
34:
answer = minusOne + minusTwo;
35:
}
36:
37:
return answer;
38:
}
Output:
Which position? 4
3 is the 4th Fibonacci number.
Which position? 5
5 is the 5th Fibonacci number.
Which position? 20
6765 is the 20th Fibonacci number.
Which position? 100
3314859971 is the 100th Fibonacci number.
Analysis: Listing 7.15 solves the Fibonacci
series using iteration rather than recursion. This
approach is faster and uses less memory than the
recursive solution. On line 13, the user is asked
for the position to check. The function fib() is
called, which evaluates the position. If the position
is less than 3, the function returns the value 1.
Starting with position 3, the function iterates
using the following algorithm:
1.
Establish the starting position: Fill variable answer
with 2, minusTwo with 0 (answer-2), and minusOne
with 1 (answer-1). Decrement the position by 3,
because the first two numbers are handled by the
starting position.
2.
For every number, count up the Fibonacci series.
This is done by
a.
Putting the value currently in minusOne into minusTwo.
b.
Putting the value currently in answer into minusOne.
c.
Adding minusOne and minusTwo and putting the sum
in answer.
d.
Decrementing n.
3.
When n reaches 0, return the answer.
This
is exactly how you would solve this problem with
pencil and paper. If you were asked for the fifth
Fibonacci number, you would write:
1,
1, 2,
and
think, "two more to do." You would then add 2+1
and write 3, and think, "one more to find." Finally
you would write 3+2 and the answer would be 5. In
effect, you are shifting your attention right one
number each time through, and decrementing the number
remaining to be found.
Note
the condition tested on line 30 (n). This is a C++
idiom, and is exactly equivalent to n != 0. This
for loop relies on the fact that when n reaches
0 it will evaluate false, because 0 is false in
C++. The for loop header could have been written:
for
(n-=3; n>0; n++)
which
might have been clearer. However, this idiom is
so common in C++ that there is little sense in fighting
it.
Compile,
link, and run this program, along with the recursive
solution offered in unit 5. Try finding position
25 and compare the time it takes each program. Recursion
is elegant, but because the function call brings
a performance overhead, and because it is called
so many times, its performance is noticeably slower
than iteration. Microcomputers tend to be optimized
for the arithmetic operations, so the iterative
solution should be blazingly fast.
Be
careful how large a number you enter. fib grows
quickly, and long integers will overflow after a
while.
|