Team LiB
Previous Section Next Section

6.8. The for Loop Statement

6.8. for 循环语句

The syntactic form of a for statement is

for 语句的语法形式是:

     for (init-statement condition; expression)
           statement

The init-statement must be a declaration statement, an expression statement, or a null statement. Each of these statements is terminated by a semicolon, so the syntactic form can also be thought of as

init-statement 必须是声明语句、表达式语句或空语句。这些语句都以分号结束,因此其语法形式也可以看成:

     for (initializer; condition; expression)
           statement

although technically speaking, the semicolon after the initializer is part of the statement that begins the for header.

当然,从技术上说,在 initializer 后面的分号是 for 语句头的一部分。

In general, the init-statement is used to initialize or assign a starting value that is modified over the course of the loop. The condition serves as the loop control. As long as condition evaluates as true, statement is executed. If the first evaluation of condition evaluates to false, statement is not executed. The expression usually is used to modify the variable(s) initialized in init-statement and tested in condition. It is evaluated after each iteration of the loop. If condition evaluates to false on the first iteration, expression is never executed. As usual, statement can be either a single or a compound statement.

一般来说,init-statement 用于对每次循环过程中都要修改的变量进行初始化,或者赋给一个起始值。而 condition 则是用来控制循环的。当 conditiontrue 时,循环执行 statement。如果第一次求解 condition 就得 false 值,则不执行 statementexpression 通常用于修改在 init-statement 中初始化并在 condition 中检查的变量。它在每次循环迭代后都要求解。如果第一次求解 condition 就得 false 值,则始终不执行 expression。通常,statement 既可以是单个语句也可以是复合语句。

Using a for Loop

for 循环的使用

Given the following for loop, which prints the contents of a vector,

假设有下面的 for 循环,用于输出一个 vector 对象的内容:

     for (vector<string>::size_type ind = 0;
                   ind != svec.size(); ++ind) {
         cout << svec[ind]; // print current element
         // if not the last element, print a space to separate from the next one
         if (ind + 1 != svec.size())
            cout << " ";
     }

the order of evaluation is as follows:

它的计算顺序如下:

1.
The init-statement is executed once at the start of the loop. In this example, ind is defined and initialized to zero.

循环开始时,执行一次 init-statement。在这个例子中,定义了 ind,并将它初始化为 0。
2.
Next, condition is evaluated. If ind is not equal to svec.size(), then the for body is executed. Otherwise, the loop terminates. If the condition is false on the first trip, then the for body is not executed.

接着,求解 condition。如果 ind 不等于 svec.size(),则执行 for 循环体。否则,循环结束。如果在第一次循环时,条件就为 flase,则不执行 for 循环体。
3.
If the condition is true, the for body executes. In this case, the for body prints the current element and then tests whether this element is the last one. If not, it prints a space to separate it from the next element.

如果条件为 true,则执行 for 循环体。本例中,for 循环体输出当前元素值,并检验这个元素是否是最后一个。如果不是,则输出一个空格,用于分隔当前元素和下一个元素。
4.
Finally, expression is evaluated. In this example, ind is incremented by 1.

最后,求解 expression。本例中,ind 自增 1。

These four steps represent the first iteration of the for loop. Step 2 is now repeated, followed by steps 3 and 4, until the condition evaluates to falsethat is, when ind is equal to svec.size().

这四步描述了 for 循环的第一次完整迭代。接着重复第 2 步,然后是和 3、4 步,直到 condition 的值为 false,即 ind 等于 svec.size() 为止。

It is worth remembering that the visibility of any object defined within the for header is limited to the body of the for loop. Thus, in this example, ind is inaccessible after the for completes.

应该谨记:在 for 语句头定义的任何对象只限制在 for 循环体里可见。因此,对本例而言,在执行完 for 语句后,ind 不再有效(即不可访问)。



6.8.1. Omitting Parts of the for Header

6.8.1. 省略 for 语句头的某些部分

A for header can omit any (or all) of init-statement, condition, or expression.

for 语句头中,可以省略 init-statementcondition 或者 expression(表达式)中的任何一个(或全部)。

The init-statement is omitted if an initialization is unnecessary or occurs elsewhere. For example, if we rewrote the program to print the contents of a vector using iterators instead of subscripts, we might, for readability reasons, move the initialization outside the loop:

如果不需要初始化或者初始化已经在别处实现了,则可以省略 init-statement。例如,使用迭代器代替下标重写输出 vector 对象内容的程序,为了提高易读性,可将初始化移到循环外面:

     vector<string>::iterator iter = svec.begin();
     for( /* null */ ; iter != svec.end(); ++iter) {
         cout << *iter; // print current element
         // if not the last element, print a space to separate from the next one
         if (iter+1 != svec.end())
             cout << " ";
     }

Note that the semicolon is necessary to indicate the absence of the init-statement more precisely, the semicolon represents a null init-statement.

注意此时必须要有一个分号表明活力了 init-statement——更准确地说,分号代表一个空的 init-statement

If the condition is omitted, then it is equivalent to having written true as the condition:

省略 condition,则等效于循环条件永远为 true

     for (int i = 0; /* no condition */ ; ++i)

It is as if the program were written as

相当于程序写为:

     for (int i = 0; true ; ++i)

It is essential that the body of the loop contain a break or return statement. Otherwise the loop will execute until it exhausts the system resources. Similarly, if the expression is omitted, then the loop must exit through a break or return or the loop body must arrange to change the value tested in the condition:

这么一来,循环体内就必须包含一个 break 或者 return 语句。否则,循环会一直执行直到耗尽系统的资源为止。同样地,如果省略 expression,则必须利用 breakreturn 语句跳出循环,或者在循环体内安排语句修改 condition 所检查的变量值。

     for (int i = 0; i != 10; /* no expression */ ) {
        // body must change i or the loop won't terminate
     }

If the body doesn't change the value of i, then i remains 0 and the test will always succeed.

如果循环体不修改 i 的值,则 i 始终为 0,循环条件永远成立。

6.8.2. Multiple Definitions in the for Header

6.8.2. for 语句头中的多个定义

Multiple objects may be defined in the init-statement; however, only one statement may appear, so all the objects must be of the same general type:

可以在 for 语句的 init-statement 中定义多个对象;但是不管怎么样,该处只能出现一个语句,因此所有的对象必须具有相同的一般类型:

     const int size = 42;
     int val = 0, ia[size];
     // declare 3 variables local to the for loop:
     // ival is an int, pi a pointer to int, and ri a reference to int
     for (int ival = 0, *pi = ia, &ri = val;
           ival != size;
           ++ival, ++pi, ++ri)
                   // ...

Exercises Section 6.8.2

Exercise 6.14:

Explain each of the following loops. Correct any problems you detect.

解释下面每个循环,更正你发现的任何问题。

     (a) for (int *ptr = &ia, ix = 0;
               ix != size && ptr != ia+size;
               ++ix, ++ptr)   { /* ... */ }
     (b) for (; ;) {
               if (some_condition) return;
               // ...
         }
     (c) for (int ix = 0; ix != sz; ++ix) { /* ... */ }
         if (ix != sz)
              // ...
     (d) int ix;
         for (ix != sz; ++ix) { /* ... */ }
     (e) for (int ix = 0; ix != sz; ++ix, ++ sz) { /* ... */ }

Exercise 6.15:

The while loop is particularly good at executing while some condition holds; for example, while the end-of-file is not reached, read a next value. The for loop is generally thought of as a step loop: An index steps through a range of values in a collection. Write an idiomatic use of each loop and then rewrite each using the other loop construct. If you were able to program with only one loop, which construct would you choose? Why?

while 循环特别擅长在某个条件保持为真时反复地执行;例如,当未到达文件尾时,一直读取下一个值。一般认为 for 循环是一种按步骤执行的循环;使用下标依次遍历集合中一定范围内的元素。按每种循环的习惯用法编写程序,然后再用另外一种结构重写。如果只能用一种循环来编写程序,你会选择哪种结构?为什么?

Exercise 6.16:

Given two vectors of ints, write a program to determine whether one vectors is a prefix of the other. For vectors of unequal length, compare the number of elements of the smaller vector. For example, given the vectors (0,1,1,2) and (0,1,1,2,3,5,8), your program should return true.

给出两个 int 型的 vector 对象,编写程序判断一个对象是否是另一个对象的前缀。如果两个 vector 对象的长度不相同,假设较短的 vector 对象长度为 n,则只对这两个对象的前面 n 个元素做比较。例如,对于 (0, 1, 1, 2) 和 (0, 1, 1, 2, 3, 5, 8) 这两个 vector,你的程序应该返回 true


Team LiB
Previous Section Next Section