§5.1 概述 §5.2 goto语句 §5.3 while语句 §5.4 do-while语句 §5.5 for语句 §5.6 循环的嵌套 §5.7 几种循环的比较 §5.8 break语句和continue语句 §5.9 程序举例
循环:反复执行称为“循环体”的程序段。
循环控制常用于数学迭代、对象遍历等问题的求解,几乎所有实用程序都包含循环。特别是在现代多媒体处理程序(图像、声音、通讯)中,循环更是必不可少。Intel公司为了加快循环程序的执行,在CPU硬件中加入多媒体扩展指令MMX(Multi-Media-eXtension );AMD在CPU中加入3D Now!指令。
循环结构是结构化程序三种基本结构之一。(顺序结构、分支结构)。
根据开始循环的初始条件和结束循环的条件不同,C语言中用如下语句实现循环
1、用goto语句和if语句构成循环。
2、用while语句。
3、用do-while语句。
4、用for语句。
一般形式: goto 语句标号 作用: 无条件转向“语句标号”处执行。 “语句标号”是一个标识符,它表示程序指令的地址。
goto语句不符合结构化程序设计准则,因为无条件转向使程序结构无规律、可读性差。一般应避免使用goto语句,但如果能大大提高程序的执行效率,也可以使用。
[例5.1] 用if语句和goto语句构成循环,求
。
| main() | |
| { | |
| int i,sum=0; | |
| i = 1; | |
| loop: | if (i <= 100) |
| { sum = sum + i; | |
| i++; | |
| goto loop; | |
| } | |
| printf("%d",sum); | |
| } | |
|
一般形式: while(表达式) 语句
|
![]() |
|
作用:实现“当型”循环。当“表达式”非0(真)时,执行“语句”。“语句”是被循环执行的程序,称为“循环体”。 |
| 特点:先判“表达式(条件)”。 |
[例5.2] ![]()
流程图:
main() { int i,sum=0; i = 1; whie (i <= 100) { sum = sum + i; i++; } printf("%d",sum); }
注意:
1、注意给出循环的初始条件,如本例中“sum=0、i=1”。
2、循环体包含一个以上的语句时,用大括号括起来,形成复合语句。
3、循环体中必须有使循环趋于结束的语句,否则程序进入“死循环”(不结束)。
一般形式: do 语句
while (表达式)
特点:“直到型”循环结构。先执行一次“语句”,判“表达式”,当“表达式”非0,再执行“语句”,直到“表达式”为0,循环结束。
[例5.3] 用do-while语句求
。
![]() |
main() | |
| { | ||
| int i,sum=0; | ||
| i = 1; | ||
| do | ||
| { sum = sum + i; | ||
| i++; | ||
| } | ||
| while(i<=100); | ||
| printf("%d",sum); | ||
| } | ||
注意:
1、上面的流程图中循环条件是“当i≤100时循环”,N-S图中的条件是“循环直到i>100”,这两者是等同的。
2、同一个问题,既可以用while循环处理,也可以用do-while循环处理。
do-while处理,图5.3(p68) while处理,图5.5(p69)
在一般情况下,用while和do-while语句解决同一问题时,若二者的循环体部分是一样的,它们的结果也一样。但当while后面的“表达式”一开始就为“假”时,两种循环的结果不同。这是因为此时while循环的循环不被执行,而do-while循环的循环体被执行一次。
[例5.4] 求i+(i+1)+(i+2)+....+10,其中,i由键盘输入。(用while和do-while两种语句分别编程序)。
| while循环程序
|
do-while循环程序
|
| main() | main() |
| { int sum=0,i; | { int sum=0,i; |
| scanf("%d",&i); | scanf("%d",&i); |
| while(i <= 10) | do |
| { sum = sum + i; | { sum = sum + i; |
| i++; | i++; |
| } | }while(i<= 10); |
| printf("%d",sum); | printf("%d",sum); |
| } | } |
for语句常用于循环次数已知的循环控制,也可以灵活用于其他循环控制。
一般形式:
for(表达式1;表达式2;表达式3) 语句
执行过程:
(1)求表达式1;
(2)求表达式2,若为“真”,执行“语句”;若为假,转第(5)步。
(3)求表达式3。
(4)转第(2)步。
(5)执行for语句下面的语句。
for语句中: “表达式1”设置循环初始条件 “表达式2”判别循环条件 “表达式3”修改循环条件 例、
for(i=1;i<=100;i++) sum = sum + i;
这里,循环条件由变量i设定,变量i称为“循环变量”。
“表达式1”,i=1, 循环初始条件。 “表达式2”,i<=100, 循环条件。 “表达式3”,i++, 修改循环条件。 这是for语句的典型用法:已知循环次数。(本例100次)。
上述for语句也可以用如下while语句表示:
i = 1; while (i <= 100) { sum = sum + i; i++; }
for语句使用非常灵活,可以省略“表达式1”、“表达式2”、“表达式3”中的几个或全部表达式。
1、for语句省略“表达式1”。“表达式1”的作用是设定循环初始条件,“表达式1”省略后,应在for语句前面设置循环初始条件。例、
for(;i<=100;i++)sum = sum + i;
/* 注意,“表达式1”后面的分号不能省略 */
2、for语句中,如果省略“表达式2(循环条件)”,不判别循环条件,认为循环循环条件始终为“真”,循环将无终止地进行下去。
for(i=1;□;i++) sum = sum + i; “表达式2”被省略。相当于: i = 1; while (1) { sum = sum + i; i++; }
3、“表达式3(修改循环条件)”也可以省略,但程序应在循环体(“语句”)中修改循环条件,以保证循环能正常结束。例、
for (sum=0,i=1;i<=100;□) { sum = sum + i; i++; }
4、省略“表达式1”和“表达式3”,只有“表达式2”。例、
for(;i<=100;) 相当于 while (i<=100) { sum = sum + i; { sum = sum + i; i++;} i++;}
5、“表达式1”、“表达式2”、“表达式3”均省略。例、
for(;;)语句 while(1) 语句
这是一种简单的死循环形式。
6、for语句的其他变形。
例1、for(sum=0;i<=100;i++) sum = sum + i; 例2、for(sum=0,i=1;i<=100;i++) sum = sum + i; 例3、for(i=0,j=100;i<=j;i++,j--) k = i + j; 例4、for(i=0;(c=getchar()) != '\n';i += c);
例4的执行情况:
循环嵌套:一个循环(称为“外循环”)的循环体内包含另一个循环(称为“内循环”)。内循环中还可以包含循环,形成多层循环。(循环嵌套的层数理论上无限制)。
三种循环(while循环、do-while循环、for循环)可以互相嵌套。例、
|
(1) |
(2) |
| while() | do |
|
{┆ |
{ ┆ |
| while() | do |
| {...} | {...} |
| } | while(); |
| } | |
| while(); | |
|
(3) |
(4) |
| for(;;) | while() |
| { ┆ | { ┆ |
| for(;;) | do |
| {...} | {....} |
| } | while(); |
| ┆ | |
| } | |
| (5) |
(6) |
| for(;;) | do |
| { ┆ | { |
| while() | ┆ |
| {....} | for(;;) |
| ┆ | {....} |
| } | ┆ |
| } | |
| while(); |
多重循环的使用与单一循环完全相同,但应特别注意内、外层循环条件的变化。
1、四种循环(while、do-while、for、goto)可以互相替换,但应尽量少用goto。
2、循环条件:while、do-while在whie后面指定;for循环在“表达式3”中指定。
3、循环初始条件:while、do-while在循环前指定;for循环在“表达式1”中指定。
4、判循环条件的时机:while、for循环先判循环条件,后执行;do-while循环先执行,后判循环条件。
5、while、do-while、for循环均可用break语句跳出循环(结束循环),用continue语句提前结束本次循环体的执行。
一、break语句
作用:跳出所在的多分支switch语句,跳出所在的while、do-while、for循环语句(提前结束循环)。
例、
for (r=1;r<=10;r++) { area = pi*r*r; if (area > 100) break; printf("%f",aera); }
r aera 1 3.14 2 12.57 3 28.27 4 50.27 5 78.54 6 113.10 7 153.94 8 201.06 9 254.47 10 314.16
二、continue语句
作用:提前结束本次循环体的执行,接着进行下一次循环条件的判别。
[例5.5] 把100~200之间不能被3整除的数输出。
main () { int n; for (n=100; n<=200; n++) { if (n%3 == 0) continue; printf("%d",n); } }
三、break语句和continue语句的区别
while (表达式1) while (表达式1) { ┇ { ┇ if (表达式2) break; if (表达式2) continue; ┇ ┇ } } break语句跳出循环 continue语句结束本次循环体的执行,进入下一次循环
[例5.6] 用以下公式计算л的值,直到最后一项的绝对值小于1E-6为止。
算法分析:
1、每项的分母,等于前一项分母加2,用n=n+2实现,n的初值为1。
2、每项的符号交替变化,用 s = -s实现,s的初值为+1(第一项为正)。
3、根据1和2,每一项的值 t = s/n,第一项的值为1。
#include "math.h" main() { int s; float n,t,pi; t = 1; pi = 0; n = 1.0; s = 1; while((fabs(t)) >= 1E-6) { pi = pi + t; n = n + 2; s = -s; t = s/n; } pi = pi * 4; printf("pi=%10.6f\n",pi); } 运行结果:pi=3.141397
[例5.7] 求Fibonacci数列:1,1,2,3,5,8,....的前40个数,即:
F1 = 1 (n = 1) F2 = 1 (n = 2) Fn = Fn-1 + Fn-2 (n≥3)
算法:
![]()
即:把40个数分为每2个一组,每组中的两个数的计算方法为:
f1 = f2 + f1 f2 = f1 + f2
N-S流程图:
程序:
main () { long int f1,f2; /* 长整型数 */ int i; f1 = 1; f2 = 1; /* 已知数列的前两个初值 */ for (i=1; i<=20; i++) { printf("%12ld %12ld ",f1,f2); /* 输出长整型数 */ if (i%2 == 0) printf("\n"); /* 控制输出格式 */ f1 = f2 + f1; f2 = f1 + f2; } }
[例5.8] 输入一个数m,判其是否为“素数”。
素数(prime):又称质数,是大于1的整数,除了能被自身和1整除外,不能被其它正整数整除。
算法:
程序:
#include "math.h" main () { int m,i,k; scanf("%d",&m); /* 输入一个整数m */ k = sqrt(m); for(i=2;i<=k;i++) if (m%i == 0) break; if (i > k+1) printf("%d 是素数\n",m); else printf("%d 不是素数\n",m); }
[例5.9] 求100~200间的全部素数。
算法:与上例类似。
程序:
#include "math.h" main () { int m,k,i,n=0;/* n用于累计素数的个数 */ for(m=101; m<=200; m=m+2) { if (n%10 == 0) printf("\n"); k = sqrt(m); for(i=2; i<=k; i++) if (m%i == 0) break; if (i >= k+1) { printf("%d ",m); n = n+1;} } }
[例5.10]
|
译密码。为使报文保密,往往按一定规律将其转换为密码,收报人再按约定的规律将其译为原文。设加密规律为:将字母变成其后的第四个字母,如,A变为E,a变为e。
|
![]() |
算法:
1、当输入字符不是“回车”时,执行密码转换。
2、仅转换A~Z、a~z。
3、转换规则:c=c+4,当c=Z~Z+4范围,或c>z时,c=c-26。
程序:
#include "stdio.h" main () { char c; while ((c=getchar()) != '\n') { if ((c>='a' && c<='z') || (c>='A' && c<='Z')) { c = c + 4; if (c>'Z' && c<='Z'+4 || c>'z') c = c - 26; } printf("%c",c); } }
[小结] 从以上几个例子可以看到,程序设计中的关键环节有:
1、算法。如求π值的算法、求Fibonicci数列的算法、验证素数的算法、字符的ASCII码间的关系。
算法分析是程序设计中的第一个步骤,也是最重要的步骤。
2、框图。根据算法的要求,列出程序实现的步骤。
框图是保证程序正确性的重要手段,它可以避免程序分支错误或分支遗漏。复杂的算法必须画出框图。
3、程序设计环境。如操作系统的特征、键盘输入的特点(如,仅在按回车键后输入的字符才进入程序缓冲区)、开发系统环境(如#include的使用)等。
4、程序设计的方法(结构化、面向对象)和风格(如适当的缩进)。
5、语言。注意语法规定。如while、do-while、for语句的执行流程和特点,break、continue语句的作用等。
程序 = 算法 + 数据结构 + 程序设计方法 + 语言工具和环境
要求:
1、初步熟悉用计算机解决问题的思路。
2、掌握while、do-while、for语句的特点和使用方法。
3、掌握break、continue语句的用法。
4、熟悉一些常见问题的算法及其C语言实现。