Chapter 10
In This Chapter
Introducing the for loop
Reviewing an example ForFactorial program
Using the comma operator to get more done in a single for loop
The most basic of all control structures is the while loop, which is the topic of Chapter 9. This chapter introduces you its sibling, the for loop. Though not quite as flexible, the for loop is actually the more popular of the two — it has a certain elegance that is hard to ignore.
If you look again at the examples in Chapter 9, you’ll notice that most loops have four essential parts. (This feels like breaking down a golf swing into its constituent parts.)
In the case of the Factorial program, the four parts looked like this:
int nValue = 1; // the setup
while (nValue <= nTarget) // the test expression
{ // the body
cout << nAccumulator << " * "
<< nValue << " equals ";
nAccumulator = nAccumulator * nValue;
cout << nAccumulator << endl;
nValue++; // the increment
}
The for loop incorporates these four parts into a single structure using the keyword for:
for(setup; test expression; increment)
{
body;
}
The flow is shown graphically in Figure 10-1.
(b) If the test expression is false, control passes to the next statement after the closed brace.
setup;
while(test expression)
{
body;
increment;
}
The following example program is the Factorial program written as a for loop :
//
// ForFactorial - calculate factorial using the for
// construct.
//
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int nNumberofArgs, char* pszArgs[])
{
// enter the number to calculate the factorial of
int nTarget;
cout << "This program calculates factorial.
"
<< "Enter a number to take factorial of: ";
cin >> nTarget;
// start with an accumulator that's initialized to 1
int nAccumulator = 1;
for(int nValue = 1; nValue <= nTarget; nValue++)
{
cout << nAccumulator << " * "
<< nValue << " equals ";
nAccumulator = nAccumulator * nValue;
cout << nAccumulator << endl;
}
// display the result
cout << nTarget << " factorial is "
<< nAccumulator << endl;
// wait until user is ready before terminating program
// to allow the user to see the program results
cout << "Press Enter to continue..." << endl;
cin.ignore(10, '
'),
cin.get();
return 0;
}
The logic of this ForFactorial program is virtually identical to its older Factorial twin: The program prompts the user to enter a number to take the factorial of. It then initializes nAccumulator to 1 before entering the loop that calculates the factorial.
ForFactorial creates an increment variable, nValue, that it initializes to 1 in the setup clause of the for statement. That done, the program compares nValue to nTarget, the value entered by the user in the test expression section of the for. If nValue is less than or equal to nTarget, control enters the body of the loop where nAccumulator is multiplied by nValue.
That done, control flows back up to the increment section of the for loop. This expression, nValue++, increments nValue by 1. Flow then moves to the test expression, where nValue is compared with nTarget and the process repeated until eventually nValue exceeds the value of nTarget. At that point, control passes to the next statement after the closed brace.
The output from this program appears as follows:
This program calculates factorials of user input.
Enter a negative number to exit
Enter number: 5
5 factorial is 120
Enter number: 6
6 factorial is 720
Enter number: -1
Press Enter to continue …
There is a seemingly useless operator that I haven’t mentioned (up until now, that is) known as the comma operator. It appears as follows:
expression1, expression2;
This says execute expression1 and then execute expression2. The resulting value and type of the overall expression is the same as that of expression2. Thus, I could say something like the following:
int i;
int j;
i = 1, j = 2;
Why would I ever want to do such a thing, you ask? Answer: You wouldn’t except when writing for loops.
The following CommaOperator program demonstrates the comma operator in combat. This program calculates the products of pairs of numbers. If the operator enters N, the program outputs 1 * N, 2 * N-1, 3 * N-2, and so on, all the way up to N * 1. (This program doesn’t do anything particularly useful. You’ll see the comma operator used to effect when discussing arrays in Chapter 15.)
//
// CommaOperator - demonstrate how the comma operator
// is used within a for loop.
//
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
int main(int nNumberofArgs, char* pszArgs[])
{
// enter a target number
int nTarget;
cout << "Enter maximum value: ";
cin >> nTarget;
for(int nLower = 1, nUpper = nTarget;
nLower <= nTarget; nLower++, nUpper--)
{
cout << nLower << " * "
<< nUpper << " equals "
<< nLower * nUpper << endl;
}
// wait until user is ready before terminating program
// to allow the user to see the program results
cout << "Press Enter to continue..." << endl;
cin.ignore(10, '
'),
cin.get();
return 0;
}
The program first prompts the operator for a target value, which is read into nTarget. It then moves to the for loop. However, this time not only do you want to increment a variable from 1 to nTarget, you also want to decrement a second variable from nTarget down to 1.
Here the setup clause of the for loop declares a variable nLower that it initializes to 1 and a second variable nTarget that gets initialized to nTarget. The body of the loop displays nLower, nUpper, and the product nLower * nTarget. The increment section increments nLower and decrements nUpper.
The output from the program appears as follows:
Enter maximum value: 15
1 * 15 equals 15
2 * 14 equals 28
3 * 13 equals 39
4 * 12 equals 48
5 * 11 equals 55
6 * 10 equals 60
7 * 9 equals 63
8 * 8 equals 64
9 * 7 equals 63
10 * 6 equals 60
11 * 5 equals 55
12 * 4 equals 48
13 * 3 equals 39
14 * 2 equals 28
15 * 1 equals 15
Press Enter to continue …
In this example run, I entered 15 as the target value. You can see how nLower increments in a straight line from 1 to 15, while nUpper makes its way from 15 down to 1.
Actually, the output from this program is mildly interesting: No matter what you enter, the value of the product increases rapidly at first as nLower increments from 1. Fairly quickly, however, the curve flattens out and asymptotically approaches the maximum value in the middle of the range before heading back down. The maximum value for the product always occurs when nLower and nUpper are equal.
Could I have made the earlier for loop work without using the comma operator? Absolutely. I could have taken either variable, nLower or nUpper, out of the for loop and handled them as separate variables. Consider the following code snippet:
nUpper = nTarget;
for(int nLower = 1; nLower <= nTarget; nLower++)
{
cout << nLower << " * "
<< nUpper << " equals "
<< nLower * nUpper << endl;
nUpper--;
}
This version would have worked just as well.
Up to and including this chapter, all of the programs have been one monolithic whole stretching from the opening brace after main() to the corresponding closing brace. This is okay for small programs, but it would be really cool if you could divide your program into smaller bites that could be digested separately. That is the goal of the next chapter on functions.
3.144.123.155