4.4 for 语句——让数值渐增的 while 语句更简洁
笔者曾有耳闻,大学里初学C语言时,有些人提出,有了 while 语句,for 语句不要也可以。有这种质疑其实并不奇怪,因为实际上 for 语句能实现的功能用 while 语句已经能够实现了。
使用 for 语句的表达方式
我们来考察下面的 for 语句,它表示 i 在 0 至 N 的范围内按 1 递增同时打印显示。
C语言
for(i = 0; i < N; i++){
printf("%d\n", i);
}
不使用 for 语句的表达方式
同样的逻辑使用 while 语句来表达,就变成了下面这样。
C语言
i = 0;
while(i < N){
printf("%d\n", i);
i++;
}
对在 0 至 N 范围的某数做某种操作,这样的需求时常能碰到。比如,要对数组 xs 中全部数值做某种处理,即,要对从 xs[0] 到 xs[N-1] 范围内的各个元素做处理。如果用 while 语句来表达,就需要在循环体外写 i=0,循环条件写 i < N,循环体最后写 i++。代码分散在三处,对于阅读代码的人来说,原本的意图没那么直观。用 for 语句就不同了,相关代码更加紧凑,代码阅读者很容易就能理解循环的意图(图 4.1)。

图 4.1 三处散落的代码在 for 语句中只存在于一处
像这样,带有初值、递增值和终值这三组数的 for 语句,早在于 1958 年发明的 ALGOL 58 语言里就已经出现了 10。
10参见 A. J. PERLIS and K. SAMELSON,“Report on the Algorithmic Language ALGOL by the ACM Committee on Programming Languages and the GAMM Committee on Programming”, Numberische Mathematik, Bd.1, S.41-60, 1959, p.50.
ALGOL 58
for I : = 0 ( 1 ) N; ……
foreach——根据处理的对象来控制循环操作
for 语句已经有了新的发展,这就是目前许多语言里采用的 foreach 句型。在 Java 语言里被称为扩展 for 语句,而在 Perl11、PHP、C# 等众多语言里被叫做 foreach 语句。本书为了体现其与 for 语句的区别,把它称为 foreach 语句 12。
11在 Perl 语言中,for 和 foreach 为同义词,为了方便阅读,两者在语言中都有提供。
12Python 语言的 for 语句就是 foreach,它反而没有相当于C语言里功能的 for 语句。
while 语句通过条件判断来控制循环操作,for 语句通过循环次数来控制循环操作 13,而 foreach 句型则是通过处理的对象来控制循环操作。
13准确来讲,for 语句也是通过条件判断来控制的,但它主要体现的还是对循环次数的跟踪。
在没有 foreach 语句的 C 语言里,for 语句常常被用来实现对数组里各元素的处理操作。foreach 的句型的产生,就是为了方便编写对某对象内所有元素进行某种处理的代码。
Java
// 数组
int[] items = new int[]{1, 2, 3, 4, 5};
// 用一般的for语句输出各元素
for(int i = 0; i < items.length; i++){
int item = items[i];
System.out.println(item);
}
// 用扩展的for语句输出各元素
for(int item: items){
System.out.println(item);
}
如上,for 语句表达的是在 0 至数组 items 长度范围以内,对 i 按 1 递增同时打印显示数组 items 第 i 个元素。使用了 foreach 语句后,意思就变成了将数组 items 里的各个元素都打印显示出来,相当地简洁易懂。
