C语言基础要素(016):入口条件循环:while与for
程序按照我们书写的顺序依次执行语句,称为顺序
结构。根据条件,在多个语句序列间选择执行一种情况,属于分支
结构。还有一类在满足某个条件之前反复执行语句的结构,称为循环(迭代)
语句。假定现在要完成“重要的事情说三遍”这一壮举,我们可以这么做。
printf( "重要的事情说三遍!" );
printf( "重要的事情说三遍!" );
printf( "重要的事情说三遍!" );
万一重要的事情要喋喋不休说个千百遍呢?显然,我们需要有更有效的方式去完成这件事,这正是循环语句的用武之地。
while 循环语句
while语句的语法如下:
while (表达式)
语句
在while循环语句中,首先对表达式求值。如果值为真,则执行语句;语句执行完成后,会再次求表达式的值,这一过程会一直进行下去,直到表达式求值为假,随后执行语句后面的部分。这种先判断再决定执行与否的循环,归属于入口条件循环。
现在,重要的事情说几遍都是简单的事了。
#include <stdio.h>
int main()
{
int i = 0;
while (i < 3)
{
printf("重要的事情说三遍!\n");
i++;
}
return 0;
}
这里i初值为0,while中的表达式是 i<3
,也可以写为 i=1; i<=3
。作为惯用法,迭代初始值通常从0开始,迭代范围采用的是上限不在其内原则,要让循环执行3次,迭代的范围是[0,3),即0、1、2;而不是[1,3],即1、2、3。另一方面,语句i++在完后一次迭代操作后让入口条件趋于束;否则程序会一直执行下去,形成死循环。
下面的例子展示了如何使用while循环,打印指定范围内的偶数。
#include <stdio.h>
int main()
{
int pos = 0;
int end = 127;
int count = 0;
while (pos < end)
{
if (pos % 2 == 0)
{
count++;
printf("%d\t", pos);
if (count % 10 == 0)
printf("\n");
}
pos++;
}
return 0;
}
可以看出,建立一个重复执行固定次数的循环时涉及到三个动作。
- 初始化:必须初始化一个计数器。
- 测试:计数器与某个有限的值进行比较。
- 更新:每执行完一次语句,计数器的值都要更新,向结束条件逼近。
for 循环语句
for是一种更易于使用的循环语句,语法如下:
for (表达式1; 表达式2; 表达式3)
语句
- 表达式1进行初始化,它在for循环开始的时候仅执行一次;
- 表达式2是判断条件,在每次执行循环之前都要对它进行求值。当表达式为假时,循环就结了。
- 表达式3进行改变或更新,它在每次循环结束时进行计算。
#include <stdio.h>
int main()
{
for (int i = 0; i < 3; i++)
printf("Hello!\n");
return 0;
}
for语句将建立循环的三个动作初始化、测试、更新都放在了一起,它等价于下列的while语句:
表达式1
while (表达式2)
语句
表达式3
与while语句不同的是,在for语句头中定义的变量,其作域用仅在for语句中
。
#include <stdio.h>
int main()
{
for (int i = 0; i < 10; i++)
{
printf("%d ", i); // 变量i的有效范围是整个for语句
}
printf("%d", i); // Error:i在这里已经无效
return 0;
}
for语句头的三个部分都是表达式,这很灵活,比如用逗号表达式完成整个初始化。
#include <stdio.h>
int main()
{
for (int pos = 0, end = 200, count = 0; pos < end; pos++)
{
if (pos % 2 == 0)
{
count++;
printf("%d\t", pos);
if (count % 10 == 0)
printf("\n");
}
}
return 0;
}
甚至是输出一条信息…
#include <stdio.h>
int main()
{
int a = 'a';
int i = 0;
for (a > 'b', printf("hello, world!\n"); i < 10; i++)
printf("%d ", i);
return 0;
}
示例有些偏于炫技,我们更偏向于将同种类型的操作放在初始化部分(像上面那样初始化三个相关的变量);而不是像这里,塞入一个关系比较、一个打印语句。for语句中所有表达式都可以省略,但表示语句的分号需要保留,我们逐步看看for退化为while的过程。首先省略掉第一个表达式,即初始化部分。
#include <stdio.h>
int main()
{
int i = 0;
for (; i < 10; i++) // 省略掉第一个表达式,保留语法形式上的分号。
printf("%d ", i);
return 0;
}
接下来我们省略掉第三个表达式,这是计数器的更新部分。
#include <stdio.h>
int main()
{
int i = 0;
for (;i < 10;) // 省略掉第3个表达式
{
printf("%d ", i);
i++; // 计数器更新部分挪到这里
}
return 0;
}
除去for头部因为语法需要的分号,几乎与while等价了。for的第二个表达式也可以省略,这表示判断条件永远为真,这就相当于 while (true),形成无限循环条件。
练习
- 改进打印指定范围内偶数的程序,让循环次数减半,更改范围进行测试。
- 使用for与while分别打印出 9, 8, 7, … 0 这些数值,除0外,数与数之间以逗号分隔。
- 尝试“忘记”编写循环的计数器更新部分,看看程序的表现,并找到结束程序的方法。