for Repetition Statement
Section 5.2 presented the essentials of counter-controlled repetition. The while statement can be used to implement any counter-controlled loop. C++ also provides the for repetition statement, which specifies the counter-controlled repetition details in a single line of code. To illustrate the power of for, let us rewrite the program of Fig. 5.1. The result is shown in Fig. 5.2.
Figure 5.2. Counter-controlled repetition with the for statement.
(This item is displayed on page 189 in the print version)
1 // Fig. 5.2: fig05_02.cpp 2 // Counter-controlled repetition with the for statement. 3 #include 4 using std::cout; 5 using std::endl; 6 7 int main() 8 { 9 // for statement header includes initialization, 10 // loop-continuation condition and increment. 11 for ( int counter = 1; counter <= 10; counter++ ) 12 cout << counter << " "; 13 14 cout << endl; // output a newline 15 return 0; // indicate successful termination 16 } // end main
|
When the for statement (lines 1112) begins executing, the control variable counter is declared and initialized to 1. Then, the loop-continuation condition counter <= 10 is checked. The initial value of counter is 1, so the condition is satisfied and the body statement (line 12) prints the value of counter, namely 1. Then, the expression counter++ increments control variable counter and the loop begins again with the loop-continuation test. The control variable is now equal to 2, so the final value is not exceeded and the program performs the body statement again. This process continues until the loop body has executed 10 times and the control variable counter is incremented to 11this causes the loop-continuation test (line 11 between the semicolons) to fail and repetition to terminate. The program continues by performing the first statement after the for statement (in this case, the output statement at line 14).
for Statement Header Components
Figure 5.3 takes a closer look at the for statement header (line 11) of Fig. 5.2. Notice that the for statement header "does it all"it specifies each of the items needed for counter-controlled repetition with a control variable. If there is more than one statement in the body of the for, braces are required to enclose the body of the loop.
Figure 5.3. for statement header components.
Notice that Fig. 5.2 uses the loop-continuation condition counter <= 10. If the programmer incorrectly wrote counter < 10, then the loop would execute only 9 times. This is a common off-by-one error.
Common Programming Error 5.2
Using an incorrect relational operator or using an incorrect final value of a loop counter in the condition of a while or for statement can cause off-by-one errors. |
Good Programming Practice 5.4
Using the final value in the condition of a while or for statement and using the <= relational operator will help avoid off-by-one errors. For a loop used to print the values 1 to 10, for example, the loop-continuation condition should be counter <= 10 rather than counter < 10 (which is an off-by-one error) or counter < 11 (which is nevertheless correct). Many programmers prefer so-called zero-based counting, in which, to count 10 times through the loop, counter would be initialized to zero and the loop-continuation test would be counter < 10. |
The general form of the for statement is
for ( initialization; loopContinuationCondition; increment ) statement
where the initialization expression initializes the loop's control variable, loopContinuationCondition determines whether the loop should continue executing (this condition typically contains the final value of the control variable for which the condition is true) and increment increments the control variable. In most cases, the for statement can be represented by an equivalent while statement, as follows:
initialization; while ( loopContinuationCondition ) { statement increment; }
There is an exception to this rule, which we will discuss in Section 5.7.
If the initialization expression in the for statement header declares the control variable (i.e., the control variable's type is specified before the variable name), the control variable can be used only in the body of the for statementthe control variable will be unknown outside the for statement. This restricted use of the control variable name is known as the variable's scope. The scope of a variable specifies where it can be used in a program. Scope is discussed in detail in Chapter 6, Functions and an Introduction to Recursion.
Common Programming Error 5.3
When the control variable of a for statement is declared in the initialization section of the for statement header, using the control variable after the body of the statement is a compilation error. |
Portability Tip 5.1
In the C++ standard, the scope of the control variable declared in the initialization section of a for statement differs from the scope in older C++ compilers. In pre-standard compilers, the scope of the control variable does not terminate at the end of the block defining the body of the for statement; rather, the scope terminates at the end of the block that encloses the for statement. C++ code created with prestandard C++ compilers can break when compiled on standard-compliant compilers. If you are working with prestandard compilers and you want to be sure your code will work with standard-compliant compilers, there are two defensive programming strategies you can use: either declare control variables with different names in every for statement, or, if you prefer to use the same name for the control variable in several for statements, declare the control variable before the first for statement. |
As we will see, the initialization and increment expressions can be comma-separated lists of expressions. The commas, as used in these expressions, are comma operators, which guarantee that lists of expressions evaluate from left to right. The comma operator has the lowest precedence of all C++ operators. The value and type of a comma-separated list of expressions is the value and type of the rightmost expression in the list. The comma operator most often is used in for statements. Its primary application is to enable the programmer to use multiple initialization expressions and/or multiple increment expressions. For example, there may be several control variables in a single for statement that must be initialized and incremented.
Good Programming Practice 5.5
Place only expressions involving the control variables in the initialization and increment sections of a for statement. Manipulations of other variables should appear either before the loop (if they should execute only once, like initialization statements) or in the loop body (if they should execute once per repetition, like incrementing or decrementing statements). |
The three expressions in the for statement header are optional (but the two semicolon separators are required). If the loopContinuationCondition is omitted, C++ assumes that the condition is true, thus creating an infinite loop. One might omit the initialization expression if the control variable is initialized earlier in the program. One might omit the increment expression if the increment is calculated by statements in the body of the for or if no increment is needed. The increment expression in the for statement acts as a stand-alone statement at the end of the body of the for. Therefore, the expressions
counter = counter + 1 counter += 1 ++counter counter++
are all equivalent in the incrementing portion of the for statement (when no other code appears there). Many programmers prefer the form counter++, because for loops evaluate the increment expression after the loop body executes. The postincrementing form therefore seems more natural. The variable being incremented here does not appear in a larger expression, so both preincrementing and postincrementing actually have the same effect.
Common Programming Error 5.4
Using commas instead of the two required semicolons in a for header is a syntax error. |
Common Programming Error 5.5
Placing a semicolon immediately to the right of the right parenthesis of a for header makes the body of that for statement an empty statement. This is usually a logic error. |
Software Engineering Observation 5.1
Placing a semicolon immediately after a for header is sometimes used to create a so-called delay loop. Such a for loop with an empty body still loops the indicated number of times, doing nothing other than the counting. For example, you might use a delay loop to slow down a program that is producing outputs on the screen too quickly for you to read them. Be careful though, because such a time delay will vary among systems with different processor speeds. |
The initialization, loop-continuation condition and increment expressions of a for statement can contain arithmetic expressions. For example, if x = 2 and y = 10, and x and y are not modified in the loop body, the for header
for ( int j = x; j <= 4 * x * y; j += y / x )
is equivalent to
for ( int j = 2; j <= 80; j += 5 )
The "increment" of a for statement can be negative, in which case it is really a decrement and the loop actually counts downward (as shown in Section 5.4).
If the loop-continuation condition is initially false, the body of the for statement is not performed. Instead, execution proceeds with the statement following the for.
Frequently, the control variable is printed or used in calculations in the body of a for statement, but this is not required. It is common to use the control variable for controlling repetition while never mentioning it in the body of the for statement.
Error-Prevention Tip 5.2
Although the value of the control variable can be changed in the body of a for statement, avoid doing so, because this practice can lead to subtle logic errors. |
for Statement UML Activity Diagram
The for statement's UML activity diagram is similar to that of the while statement (Fig. 4.6). Figure 5.4 shows the activity diagram of the for statement in Fig. 5.2. The diagram makes it clear that initialization occurs once before the loop-continuation test is evaluated the first time, and that incrementing occurs each time through the loop after the body statement executes. Note that (besides an initial state, transition arrows, a merge, a final state and several notes) the diagram contains only action states and a decision. Imagine, again, that the programmer has a bin of empty for statement UML activity diagramsas many as the programmer might need to stack and nest with the activity diagrams of other control statements to form a structured implementation of an algorithm. The programmer fills in the action states and decision symbols with action expressions and guard conditions appropriate to the algorithm.
Figure 5.4. UML activity diagram for the for statement in Fig. 5.2.
(This item is displayed on page 192 in the print version)