while循环的通用形式如下:
while (expression) statement
statement部分可以是以分号结尾的简单语句,也可以是用花括号括起来的复合语句。程序中的expression部分都使用关系表达式。也就是说,expression是值之间的比较,可以使用任何表达式。如果expression为真(或者更一般地说,非零),执行statement部分一次,然后再次判断expression。在expression为假(0)之前,循环的判断和执行一直重复进行。每次循环都被称为一次迭代(iteration),如图6.1所示。
1 终止while循环
while循环有一点非常重要:在构建while循环时,必须让测试表达式的值有变化,表达式最终要为假。否则,循环就不会终止(实际上,可以使用break和if语句来终止循环,但是你尚未学到)。考虑下面的例子:
index = 1;while (index < 5){ printf("Continue!")}
上面的程序段将打印无数次Continue。为什么?因为循环中index的值一直都是原来的值1,不曾变过。现在,考虑下面的程序段:
index 1;while (--index < 5) { printf("Continue!")}
这段程序也好不到哪里去。虽然改变了index的值,但是改错了!不过,这个版本至少在index减少到其类型可容纳的最小负值并变成最大正值时会终止循环(第3章3.4.2节中的toobig.c程序解释过,最大正值加1一般会得到一个负值;类似地,最小负值减1一般会得到最大正值)。
2 何时终止循环
要明确一点:只有在对测试条件求值时,才决定是终止还是继续循环。例如,下面的程序:
// when.c -- when a loop quits#include int main(void){ int n = 5; while (n < 7) // line 7 { printf("n = %d", n); n++; // line 10 printf("Now n = %d", n); // line 11 } printf("The loop has finished."); return 0;}
执行后输出如下:
n = 5
Now n = 6
n = 6
Now n = 7
The loop has finished.
在第2次循环时,变量n在第10行首次获得值7。但是,此时程序并未退出,它结束本次循环(第11行),并在对第7行的测试条件求值时才退出循环(变量n在第1次判断时为5,第2次判断时为6)。
3 while:入口条件循环
while循环是使用入口条件的有条件循环。所谓“有条件”指的是语句部分的执行取决于测试表达式描述的条件,如(index < 5)。该表达式是一个入口条件(entry-condition),因为必须满足条件才能进入循环体。在下面的情况中,就不会进入循环体,因为条件一开始就为假:
index = 10;while (index++ < 5){ printf("Have a fair day or better.")}
把第1行改为:
index = 3;
就可以运行这个循环了。
4 语法要点
使用while时,要牢记一点:只有在测试条件后面的单独语句(简单语句或复合语句)才是循环部分。程序清单6.3演示了忽略这点的后果。缩进是为了让读者阅读方便,不是计算机的要求。
/* while1.c -- watch your braces *//* bad coding creates an infinite loop */#include int main(void){ int n = 0; while (n < 3) printf("n is %d", n); n++; printf("That's all this program does"); return 0;}
输出为:
n is 0n is 0n is 0n is 0n is 0...
屏幕上会一直输出以上内容,除非强行关闭这个程序。
虽然程序中缩进了n++;这条语句,但是并未把它和上一条语句括在花括号内。因此,只有直接跟在测试条件后面的一条语句是循环的一部分。变量n的值不会改变,条件n <3 一直为真。该循环会一直打印n is 0,除非强行关闭程序。这是一个无限循环(infinite loop)的例子,没有外部干涉就不会退出。记住,即使while语句本身使用复合语句,在语句构成上,它也是一条单独的语句。该语句从while开始执行,到第1个分号结束。在使用了复合语句的情况下,到右花括号结束。要注意放置分号的位置。例如,考虑程序清单6.4。
#include int main(void){ int n = 0; while (n++ < 3); /* line 7 */ printf("n is %d", n); /* line 8 */ printf("That's all this program does."); return 0;}
改程序的输出为:
n is 4
That's all this program does.
如前所述,循环在执行完测试条件后面的第1条语句(简单语句或复合语句)后进入下一轮迭代,直到测试条件为假才会结束。该程序中第7行的测试条件后面直接跟着一个分号,循环在此进入下一轮迭代,因为单独一个分号被视为一条语句。虽然n的值在每次循环时都递增1,但是第8行的语句不是循环的一部分,因此只会打印一次循环结束后的n值。
在该例中,测试条件后面的单独分号是空语句(null-statement),它什么也不做。在C语言中,单独的分号表示空语句。有时,程序员会故意使用带空语句的while语句,因为所有的任务都在测试条件中完成了,不需要在循环体中做什么。例如,假设你想跳过输入到达第1个既不是空白字符也不是数字的位置,可以这样写:
while (scanf("%d", &num) == 1) ; /* skip integer input */
只要scanf()读取一个整数,就会返回1,循环继续执行。
注意,为了提高代码的可读性,应该让这个分号独占一行,不要直接把它放在测试表达式同行。这样做一方面让读者更容易看到空语句,一方面也提醒自己和读者空语句是有意而为之。处理这种情况更好的方法是使用continue语句。