后的循环体,在语法上要求是一条语句,若在循环体内需要多条语句,应该用大括号括起来,形成复合语句。
求解表达式1for循环的执行过程如下: (1) 计算“表达式1”。 假(0)表达式2(2) 计算“表达式2”,若其值为非零,则转步骤(3); 真(非0)若其值为零,则转步骤(5)。
循环体(3) 执行一次循环体。 (4) 计算“表达式3”,然后转向步骤2。 求解表达式3(5) 结束循环,执行for循环之后的语句。 整个流程如图6-5所示。
for语句的下【例6-6】请编写一个程序,计算半径为0.5、1.5、2.5、一语句3.5、4.5、5.5mm时的圆面积。本例要求计算6个不同半径
图 6-5 for循环流程图的圆面积,且半径的变化是有规律的,从0.5mm开始按增1mm
的规律递增,可直接用半径r作为for循环控制变量,每循环一次使r增1直到r大于5.5为止。程序如下: #include \main() { float r, s; float Pai=3.14159; for (r=0.5; r<6.0; r++) { s=Pai*r*r; /*计算圆面积s的值*/ printf(\ } }
运行结果: r=0.5 s=0.79 r=1.5 s=7.07 r=2.5 s=19.63 r=3.5 s=38.48 r=4.5 s=63.62 r=5.5 s=95.03
程序中定义了一个变量Pai,它的值是3.14159;变量r既用作循环控制变量又是半径的值,它的值由0.5变化到5.5,循环体共执行6次当r增到6.0时,条件表达式“r〈6.0”的值为0,从而退出循环。for循环的循环体是个用花括号括起来的复合语句,其中包含两个语句,通过赋值语句把求fac=1出的圆面积放在变量s中,然后输出r和s的值。
输入n的值【例6-7】求正整数n的阶乘n!其中n由用户输入。
i=1 在本例中省略了对用户输入的n的合理性的检测,整
个流程如图6-6所示。阶乘结果用fac表示,它的值一般比
假(0)i<=n较大,因此定义为实型变量。程序如下:
#include\真(非0)fac=fac*imain()
i++ 6
输出fac的值图 6-6 用for循环求阶乘{
float fac=1; int n,i;
scanf(\
/*以下省略了对用户输入的n的合理性的检测*/ for(i=1;i<=n;i++) fac=fac*i;
printf(\
}
由以上两个例子可以看出,for语句最典型的应用形式,也就是最易理解的形式如下: for(循环变量赋初值;循环条件;循环变量增值) 语句序列(循环体); 例如:
for(i=1;i<=10;i++) fac=fac*i; 它相当于以下语句; i=1;
while(i<=10) {
fac=fac*i; i++; }
显然,用for语句简单、方便。对于以上for语句的一般形式也可以改写如下: 表达式1;
while(表达式2) {
语句序列(循环体); 表达式3; } 说明:
(1) for语句一般形式中的“表达式1”可以省略,此时应在for语句之间前给循环变量赋初值。注意省略表达式1时,其后的分号不能省略。如 for(;i<=10;i++) fac=fac*i;
执行时,跳过“求解表达式1”这一步,其它不变。
(2) 如果表达式2省略,即不判断循环条件,循环无终止地进行下去。也就是认为表达式2始终为真。见图6-7。例如:
求解表达式1 for(i=1;;i++) fac=fac*i;
循环体它相当于:
i=1; 求解表达式3 while(1)
图 6-7 省略表达式2 {
fac=fac*i;
7
i++; }
(3) 表达式3也可以省略,但此时程序设计者应另外设法保证循环能正常结束。如: for(i=1;i<=10;) {
fac=fac*i; i++; }
本例把i++的操作不放在for语句的表达式3的位置处,而作为循环体的一部分,效果是一样的,都能使循环正常结束。
(4) 可以省略表达式1和表达式3,只有表达式2,即只给循环条件。如:
for( ;i<=10;) while(i<=10) { {
fac=fac*i; 相当于: fac=fac*i; i++; i++; } }
在这种情况下,完全等同于while语句。可见for语句比while语句功能强,除了可以给出循环条件外,还可以赋初值,使循环变量自动增值等。
(5) 三个表达式都可以省略,如 for(;;)
语句序列(循环体); 相当于
while(1)
语句序列(循环体);
即不设初值,不判断条件(认为表达式2为真),循环变量不增值。无终止地执行循环体。
(6) 表达式1可以是设置循环变量初值的赋值表达式,也可以是与循环变量无关的其它表达式。如
for (fac=1;i<=10;i++) fac=fac*i; 表达式3也类似。
表达式1和表达式3可以是一个简单的表达式,i=0也可以是逗号表达式,即包含一个以上的简单表达式,j=10中间用逗号间隔。如:
假(0) for(fac=1,i=1;i<=10;i++) fac=fac*i; i<=n或 真(非0) for(i=0,j=100;i<=j;i++,j--) k=i+j; k=i+j表达式1和表达式3都是逗号表达式,各包含两个赋值
i=i+1表达式,即同时设两个初值,使两个变量增值,执行情j=j-1况见图6-8。
在逗号表达式内按自左至右顺序求解,整个逗号表
图 6-8 两个循环变量的应用达式的值为其中最右边的表达式的值。如:
for(i=1;i<=10;i++,i++) fac=fac*i; 相当于
for(i=1;i<=10;i+2) fac=fac*i;
(7) 表达式2一般是关系表达式(如i<10)或逻辑表达式(如a
8
数值表达式或字符表达式,只要其值为非零,就执行循环体。分析下面两个例子: ① for(i=0;(c=getchar() )! =’\\n’;i+=c);
i=0 在表达式2中先从终端接收一个字符给c,然后判断此赋值表达式的值是否不等于’\\n’(换行符),如果不取一个字符赋给C等于’\\n’,就执行循环体。此for语句的执行过程见图
6-9,它的作用是不断输入字符,将它们的ASCII码相加,
假(0)C!=回车直到输入一个“回车换行”符为止。
注意:此for语句的循环体为空语句,把本来要在循真(非0)环体内处理的内容放在表达式3中,作用是一样的。可i=i+C见for语句功能强,可以在表达式中完成本来应在循环体内完成的操作。
图 6-9 表达式2的运用 ② for( ;(c=getchar() )! =’\\n’;)
printf(“%c”,c);
无表达式1和表达式3,其作用是每读入一个字符输出该字符,直到输入一个“回车换行”符为止。请注意,从终端键盘向计算机输入时,是在输入回车以后才送到内存缓冲区中去的。运行情况是:
Cmputer↙ (输入) Cmputer (输出) 而不是
CCoommppuutteerr
即不是从终端敲入一个字符马上输出一个字符,而是输入回车后数据送入内存缓冲区,然后每次从缓冲区读一字符,最后输出。
从上面介绍可以知道C语言中的for语句比其它语言(如BASIC,PASCAL)中的for语句功能强得多。可以把循环体和一些与循环控制无关的操作也都作为表达式1或表达式3出现,这样程序可以短小简洁,但过分地利用这一特点会使for语句显得杂乱,可读性降低,建议不要把与循环控制无关的内容放到for语句中。
6.4 语句标号和goto 语句
6.4.1 语句标号
语句标号是一个标识符加一个冒号“:”,它表示程序指令的地址。语句标号只能由字母、数字和下划线组成,第一个字符必须为字母或下划线,特别要注意不能用整数作语句标号。下面是合法的语句标号:
loop: ERR: 下面是不合法的语句标号:
1000: !Note: 6.4.2 goto语句
goto语句为无条件转向语句,一般形式为: goto 语句标号
它的作用是无条件转向“语句标号”处执行。
结构化程序设计方法主张限制使用goto语句,因为goto语句不符合结构化程序设计准则,无条件转向使程序结构无规律、可读性变差。但如果能大大提高程序的执行效率,也可以使用。一般来说,可以有两种用途:
9
(1) 与if语句一起构成循环。
(2) 从循环体中跳到循环体外,但在C语言中可以用break语句和continue语句(见6.6)跳出本层循环和结束本次循环。goto语句的使用机会已大大减少,只是需要从多层循环的内层跳到外层循环外时才用到。但是这种用法不符合结构化程序设计原则,一般不宜采用,只有在不得已时(例如能大大提高程序的执行效率)才使用。
【例6-8】 用if语句和goto语句构成循环,求1+2+3+?+100的值。
main() {
int i,sum=0; i = 1;
loop:if (i <= 100) { sum = sum + i; i++; goto loop; }
printf(\}
运行结果如下: sum=5050 这里用的是“当型”循环结构,当条件满足时,执行相加操作,并使计数器i的值加1,然后无条件转向,循环判断条件是否满足。if语句与goto语句一起也可以构成“直到”型循环。
6.5几种循环的比较
在C语言中,四种形式的循环都可以用来处理同一问题,但具体使用时又存在一些细微差别,一般情况下它们可以相互代替,但一般不提倡用goto型循环。
1. while和do-while型循环,只在while后面指定循环条件,在循环体中应包含使循环趋于结束的语句(如i++,或i=i+1等)。
for语句可以在表达式3中包含使循环趋于结束的操作,甚至可以将循环体中的操作全部放到表达式3中。由此可见,for语句的功能更强,凡用while循环能完成的,用for循环都能实现。
2. 用while和do-while循环时,循环变量初始化的操作应在while和do-while语句之前完成。而for语句可以在表达式1中实现循环变量的初始化。
3. while和for循环是先测试表达式,后执行循环体;而do-while语句是先执行一次循环体,再判断表达式。
4. 对while循环、do-while循环和for循环,可以用break语句跳出循环,用continue语句结束本次循环(break和continue语句见下节)。而对用goto语句和if语句构成的循环,不能用break和continue语句进行控制。
下面举一个例子,来说明如何用各种循环方法解决相同的问题。 要求:把50~100之间的不能被3整除的数输出。
【例6-9】用while语句实现 #include\
10