Previous: 5.2 New Control Constructs
Up: 5.2 New Control Constructs
Next: 5.2.2 The do...while Statement
Previous Page: 5.2 New Control Constructs

5.2.1 The for Statement

The logic of the loops we have constructed so far has included three components: some form of initialization before the loop, a test for loop termination, and some form of data update within the body of the loop. We implemented these loops using three separate statements in the program, with a while statment forming the condition test and loop body. Another looping construct combines all three components of a loop in a single statement: the for statement.

The syntax for the for statement is:

The keyword, for, and the parentheses are required as shown. Notice the three expressions are separated by semi-colons ( ;). The semantics of the for statement is as follows. The expression, <expr1>, is evaluated once before the loop condition is tested for the first time; <expr2> is the loop condition which is evaluated prior to each execution of the loop body; and <expr3> is evaluated at the end of the loop body, just prior to testing the condition. The process repeats until the loop condition becomes False. The body of the loop is <statement>, which, as usual, may be any valid type of C statement; empty, simple, or compound. As with the while loop, if the loop condition evaluates to True, the loop body is executed; otherwise, if the loop condition evaluates to False, the loop is terminated, and control passes to the next statement following the for statement. In typical use, the expressions, <expr1> and <expr3> initialize and update a variable, respectively. Figure 5.1 shows the control flow for a for statement.

A for statement includes all the necessary features of a loop: an initialization expression, a loop condition, and an update expression. Thus, the following two forms of implementing a loop are equivalent:

and

The break and continue statements can also be used in the body of a for statement, just as in a statement. The use of a for statement or a while statement to implement a loop is a matter of choice, based on the logic of the algorithm. One advantage might be that writing a for statement reminds one that initialization and update expressions are usually necessary for a loop.

An Example: Factorial

Let us consider an example task which may require a bigger range of integers than the one provided by int on many machines. The task is to determine a cumulative product from 1 to a positive integer, . The product from 1 to is called the factorial of , written . The algorithm is very simple: read an integer n; call a function fact(n) which returns the factorial of n; print the result.

The function fact() merely needs to multiply a cumulative product variable, initialized to 1, by all integers from 1 through n:

initialize product to 1
     repeat for values of i = 1, 2, 3,..., n
          product = product * i
     return product
The variable, product, must be initialized to 1 before the loop, otherwise the cumulative product will be garbage. Each iteration brings us closer to the result. We will use a for statement to implement the iterative algorithm for a factorial function as shown in Figure 5.2. The for loop executes as follows. The first expression in parentheses is an initialization expression, i.e. i is initialized to 1. The second expression is the loop condition. If the second expression, i <= n, evaluates to True, then the loop body is executed. The third expression is the update expression; it is evaluated after the loop body is executed, and control then passes to the loop condition. In our example, the expression, i = i + 1, is evaluated to update the variable, i, after the loop body is executed. The loop condition is then tested, and the process repeats until the loop condition becomes False. The above loop executes for i = 1, 2, 3, ..., and n and the variable product accumulates the factorial value of .

The driver uses a while condition:

(scanf("%d", &n) != EOF)
where scanf() reads an integer item if possible and stores it in n. The value returned by scanf() is then compared with EOF and if the value returned is NOT EOF, the loop executes. As soon as scanf() returns EOF, the loop is terminated. The while expression serves both to read an item and to check if the returned value is EOF. The loop body tests the value of n; if it not a positive integer, the user is asked to retype a positive number; otherwise, the value of fact(n) is printed.

Here is a sample session run on an IBM PC:

The cumulative product in the factorial function grows very fast with n. For moderately large values of n, the cumulative product overflows the int type object; the number is too large for the size of the object. When this occurs, the results are meaningless. Usually, an overflow is indicated when a program, working correctly for smaller numbers, gives ridiculous results for larger numbers. In the case of the factorial function, the first sign of trouble is a negative result for the factorial of 8. We know the result must be positive since we are multiplying only positive numbers. What has happened is the result has overflowed into the sign bit resulting in a negative integer. If factorial of larger numbers is desired, a long int variable should be used for the variable product as well as for the function fact. Here is a revised version of the factorial function.

/*   Function computes a long factorial of n using a for loop. */
long longfact(int n)
{    long int product;
     int i;

product = 1; for (i = 1; i <= n; i = i + 1) product = product * i; return product; }

We must keep several things in mind when using the function, longfact(), in the driver program. In the calling function, if the value returned by longfact() is saved, it must be assigned to a long integer; otherwise, a long result would be converted to int by dropping higher order bits and the result would be meaningless. In addition, to print the long value of longfact(), the conversion specifier must be qualified by the prefix l:
printf("Factorial of %d is %ld\n", n, longfact(n));
The conversion specifier, %ld, prints a long decimal integer.

This example has shown a case where the size of the type int is smaller than the type long, as it is in some implementations. The situation could be corrected by using a larger size data type to accumulate the factorial. However, even this type has limitations; the factorial of 13 will overflow the size of a long integer. The only possibility provided for even larger numbers is to use a floating point representation, which has a larger range, at the expense of loss of precision.



Previous: 5.2 New Control Constructs
Up: 5.2 New Control Constructs
Next: 5.2.2 The do...while Statement
Previous Page: 5.2 New Control Constructs

tep@wiliki.eng.hawaii.edu
Wed Aug 17 08:40:40 HST 1994