Chapter 10

Looping for the Fun of It

In This Chapter

arrow Introducing the for loop

arrow Reviewing an example ForFactorial program

arrow 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.

The for Parts of Every Loop

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.)

  • The setup: Usually the setup involves declaring and initializing an increment variable. This generally occurs immediately before the while.
  • The test expression: The expression within the while loop that will cause the program to either execute the loop or exit and continue on. This always occurs within the parentheses following the keyword while.
  • The body: This is the code within the braces.
  • The increment: This is where the increment variable is incremented. This usually occurs at the end of the body.

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.

  1. As the CPU comes innocently upon the for keyword, control is diverted to the setup clause.
  2. Once the setup has been performed, control moves over to the test expression.
  3. (a) If the test expression is true, control passes to the body of the for loop.

    (b) If the test expression is false, control passes to the next statement after the closed brace.

  4. Once control has passed through the body of the loop, the CPU is forced to perform a U-turn back up to the increment section of the loop.
  5. That done, control returns to the test expression and back to Step 3.
9781118823873-fg1001.tif

Figure 10-1: The flow in and around the for loop.

tip.eps This for loop is completely equivalent to the following while loop:

  setup;
while(test expression)
{
    body;

    increment;
}

Looking at an Example

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 …

technicalstuff.eps All four sections of the for loop are optional. An empty setup, body, or increment section has no effect; that is, it does nothing. (That makes sense.) An empty test expression is the same as true. (This is the only thing that would make sense — if it evaluated to false, then the body of the for loop would never get executed, and the result would be useless.)

warning.eps A variable defined within the setup section of a for loop is only defined within the for loop. It is no longer defined once control exits the loop.

Getting More Done with the Comma Operator

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.

remember.eps The for loop can’t do anything that a while loop cannot do. In fact, any for loop can be converted into an equivalent while loop. However, because of its compactness, you will see the for loop a lot more often.

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.123.155