C程序设计 - - 循环结构程序设计

更新时间:2023-03-08 05:59:39 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

第6章 循环结构程序设计

许多问题的求解归结为重复执行的操作,例如输入多个同学的成绩、对象遍历、迭代求根等问题。这种重复执行的操作在程序设计语言中用循环控制来实现。几乎所有实用程序都包含循环。特别是在现代多媒体处理程序(图像、声音、通讯)中,循环更是必不可少。

根据开始循环的初始条件和结束循环的条件不同,C语言中用如下语句实现循环 (1) while语句。 (2) do-while语句。 (3) for语句。

(4) 用goto语句和if语句构成循环。

循环结构在程序设计中十分重要。所谓循环结构就是当给定条件成立时,反复执行某段程序,直到条件不成立时为止。给定的条件称为循环条件,反复执行的程序段称为循环体。

6.1 while语句

while语句最简单的情况为循环体只有一个语句,其形式如下: while(表达式) 语句;

但是,while语句通常使用更复杂的形式,也就是其一般形式: while(表达式) {

语句序列; }

其中表达式是循环条件,语句序列为循环体。其执行过程是:先计算while后面圆括号内表达式的

假(0)值,如果其值为真(非0),则执行语句序列(循环表达式体),然后再计算while后面圆括号内表达式的值,

真(非0)并重复上述过程,直到表达式的值为“假”(值为0)时,退出循环,并转入下一语句去执行。 循环体While循环的执行流程如图6-1所示。

使用while语句时,需注意如下几个问题: (1) while语句的特点是先判断表达式的值,然

图 6-1 while循环流程图后根据表达式的值决定是否执行循环体中的语句,因

此,如果表达式的值一开始就为“假“,则循环体将一次也不执行。

(2)当循环体由多各语句组成时,必须用左、右花括号括起来,使其形成复合语句。如: while(x>0) {

s+=x x--; }

1

(3)为了使循环最终能够结束,而不至于使循环体语句无穷执行,即产生“死循环”。因此,每执行一次循环体,条件表达式的值都应该有所变化,这既可以在表达式本身中实现,也可以在循环体中实现。

【例6-1】利用while语句,编写程序,求1+2+3+?+100的值。

这是一个求100个数的累加和问题,加数从1变化到100,可以看到加数是有规律变化的。后一个加数比前一个加数增1,第一个加数为1,最后一个加数为100;因此可以在循环中使用一个整型变量i,每循环一次使i增1,一直循环到i的值超过100,用这个办法就解决了所需的加数问题;但是要特别注意的是变量i需要有一个正确的初值,在这里它的初值应当设定为0。

下一个要解决的是求累加和。设用一个变量sum来存放这100个数和的值,可以先求0+1的和并将其放在sum中,然后把sum中的数加上2再存放在sum中,依次类推,这和人们心算的过程没有什么区别,sum代表着人们脑中累加的那个和数,不同的是心算的过程由人们自己控制。在这里,sum累加的过程要放在循环中,由计算机来判断所加的数是否已经超过100,加数则放在变量i中,并在循环过程中一次次增加1。整个流程如图6-2所示。

图6-2累加求和流程图

以下就是求累加和的典型算法。

main() {

int i=1, sum=0; /*i的初值为1,sum的初值为0*/ while(i<=100) /*当i小于或等于100时执行循环体*/ {

sum=sum+i; /*在循环体中累加一次,i增加1*/ i=i+1; /*在循环体中i增加1*/ }

printf(\}

程序运行后的输出结果: sum=5050 注意:

(1) 如果在第一次进入循环时,while后圆括号内表达式的值为0,循环一次也不执行。在本程序中,如果i的初值大于100将使表达式i<=100的值为0,循环体不执行。

(2) 在循环体中一定要有使循环趋向结束的操作,以上循环体内的语句i=i+1使i不断增加1,当i>100时循环结束。如果没有这一语句,则i的值始终不变,循环将无限进行。 (3) 在循环体中,语句的先后位置必须符合逻辑,否则将会影响运算结果,例如,若将上例中的While循环体改写成:

while(i<=100)

{ i++; /*先计算i++,后计算sum的值*/

2

sum=sum+i; }

运行后,将输出:

sum=5150

运行的过程中,少加了第一项的值1,而多加了最后一项的值101。

【例6-2】利用while语句,计算1+1/2+1/4+?+1/50的值,并显示出来。 #include“stdio.h” main() { float sum=1; int i=2; while (i<=50) {

sum +=1/(float) i; i+=2; } printf(\}

运行结果: sum=2.907979

注意:在此程序中,在循环体中进行累加计算时,必须要对变量i进行强制类型转换,即利用(float)i使其变为浮点型中间变量后再参加运算,否则,由于i中存放的是大于1的整型量,所以,1/i将按整型规则运算,其结果总是为0。

6.2 do-while循环语句

do-while循环结构的形式如下: do

语句序列(循环体); while(表达式); 例如: do {

i++; s+=i;

}

while(i<10); 说明:

(1) do是C语言的关键字,必须与While联合使用。

(2) do-while循环由do开始,用while结束。必须注意的是:在while(表达式)后的“;”不可丢,它表示do-while语句的结束。

(3) while后一对圆括号中的表达式,可以是C语言中任意合法的表达式。由它控制循环是否执行。

(4) 按语法,在do和while之间的循环体只能是一条可执行语句。若循环体内需要多

3

个语句,应该用大括号括起来,组成复合语句。

do-while 循环的执行过程是这样的(如图6-3所示): (1) 执行do后面循环体中的语句。

(2) 计算While后面一对圆括号中表达式的值。当值为非零时,转去执行步骤1;当值为零时,执行步骤(3)。 循环体(3) 退出do-while循环。

真(非0)由do-while构成的循环与while循环十分相似,

表达式它们之间的主要区别是: while循环结构的判断控制

假(0)出现在循环体之前,只有当 while后面表达式的值为

非零时,才能执行循环体;在do-while构成的循环结图 6-3 do-while循环流程图构中,总是先执行一次循环体,然后再求表达式的值,

因此,无论表达式的值是零还是非零,循环体至少要被执行一次。

和while循环一样,在do-while循环体中,一定要有能使while后表达式的值变为0的操作,否则,循环将会无限制的进行下去。

i=1【例6-3】利用do-while语句,

i=1编写程序,求1+2+3+?+100的值。

sum=sum+1sum=sum+1根据do-while循环的结构,先i=i+1i=i+1画出流程图,见图6-4((a)是传统

直到i>100真(非0)流程图,(b)是N-S图)。程序如下:

i<=100#include\

假(0)main ()

(a)(b){

图 6-4 用do-while循环实现累加 int i=1,sum=0; do { sum=sum+i; i=i+1; }while(i<=100); printf(\}

程序运行后的输出结果: sum=5050

使用do-while语句应注意如下几个问题: (1) 由于do-while语句是先执行一次循环体,然后再判断表达式的值。所以,无论一开始表达式的值为“真”还是为“假”,循环体中的语句都至少被执行一次,这一点同while语句是有区别的。 (2) 如果do-while语句的循环体部分是由多个语句组成的话,则必须用左、右花括号括起来,使其形成复合语句。 (3) C语言中的do-while语句是在表达式的值为真时重复执行循环体,这一点与别的语言中类似语句有区别,在程序设计时应引起注意。

【例6-4】 利用do-while语句计算1+1/2+1/4+…+1/50的值,并显示出来。 main() {

4

int i=2; float sum=1; do { sum+=1/(float)i; i+=2;

}while(i<=50);

printf(\}

运行结果: sum=2.907979

在一般情况下,用while语句和do-while语句处理同一问题时,若二者的循环体部分是一样的,它们的结果也一样。如例6-1和例6-3中的循环体是相同的,得到的结果也相同。但在while后面的表达式一开始就为假(0值)时,两种循环的结果是不同的。

【例6-5】while和do-while循环的比较

main() main() { {

int sum=0,i; int sum=0,i; scanf(\ while(i<=10) do { { sum=sum+i; sum=sum+i; i++; i++;

} }while(i<=10);

printf(\} }

本例左半部分用while循环求i到10的连加和,i的值由用户输入。右半部分用do-while循环实现相同的功能。当输入i的值小于或等于10时,二者得到的结果相同。例如,当输入的i=1时,用while结构和do-while结构得到的结果是都是55;而当输入的i的值大于10时,二者得到的结果就不同了。例如,当输入的i=15时,用while结构得到的结果是0;而用do-while结构得到的结果是15。这是因为此时对while循环来说,一次也不执行循环体,而对do-while循环来说,则要执行一次循环体。由此可以得到结论:当while后面的表达式的第一次的值为“真”时,两种循环得到的结果相同。否则,两者结果不同(指两者具有相同循环体的情况)。

6.3 for语句

for语句构成的循环通常称为for循环。for循环的一般形式如下:

for(表达式1;表达式2;表达式3) 循环体; 例如:

for(k=0;k<10;k++) printf(“*”);

以上for循环在一行上打印10个“*”号。

for是C语言的关键字,其后的圆括号中通常含有3个表达式,各表达式之间用“;”隔开。这三个表达式可以是任意表达式,通常主要用于for循环的控制。紧跟在for(…)之

5

后的循环体,在语法上要求是一条语句,若在循环体内需要多条语句,应该用大括号括起来,形成复合语句。

求解表达式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

main () {

int n=50; /*循环变量初始化。*/

while(n<=100) /*先判断条件,再决定执行与否*/ { if(n%3!=0) printf(\ n++; } }

【例6-10】用do-while语句实现 #include\main () {

int n=50; /*循环变量初始化。*/

do /*先执行一次循环体,再判断条件,决定是否继续执行循环体*/ { if(n%3!=0) printf(\ n++;

}while(n<=100); }

【例6-11】用for语句实现 #include\main () {

int n;

/*循环变量初始化、条件判断、循环变量自增在一条语句中实现。*/ for(n=50;n<=100;n++) { if(n%3!=0) printf(\ } }

【例6-12】用if和goto语句构成的循环实现 #include\main () {

int n=50; loop: if(n%3!=0) printf(\ n++;

if(n<=100) goto loop; /*非结构化程序设计方法,不提倡。*/

11

}

从【例6-9】到【例6-12】这几个例子可以看出,处理同一问题可以使用不同形式的循环,相较而言for循环的功能更强大一些。goto型循环不符合结构化设计原则,可读性较差,一般不宜采用。

6.6 break和continue语句

6.6.1 break语句

前面已经介绍了C语言的三种循环语句,这三种循环语句都是在执行循环体之前或之后通过对一个表达式的测试来决定是否中止对循环体的执行。另外,在循环体中,也可以通过使用break语句来立即终止循环的执行,而转到循环结构的下一语句处执行。

break语句的一般形式如下所示: break ;

其执行过程是:终止对switch语句或循环语句的执行,即跳出这两种语句,而转入下一语句执行。

使用break语句应注意如下几个问题: (1) break语句只能用于循环语句或switch语句中。如果在程序中有下列语句: if(?) break;

则此时的if语句一定位于循环体中或switch语句中,break语句跳出的也不是if语句,而是跳出包含此if语句的循环体或switch语句。

(2)由于循环语句的循环体部分还可以使用循环语句,这样,循环语句就可以嵌套使用。在循环语句嵌套使用的情况下,break语句只能跳出(或终止)它所在的循环,而不能同时跳出(或终止)多层循环,如: for(?) {

for(?) {?

break; } }

上述的break语句只能从内层的for循环体中跳到外层的for循环体中,而不能同时跳出两层循环体。

【例6-13】 从键盘上连续输入字符,并统计其中大写字母的个数,直到输入“换行”字符时结束。

#include\main () {

char ch; int sum=0; while(1) { ch=getchar();

12

if(ch=='\\n') break; /*跳出整个while循环结构*/ if(ch>='A'&&ch<='Z') sum++; }

printf(\}

说明:在本程序中,while(1)表示“无限循环”,即循环条件总为“真”,在这种情况下,就只能依靠循环体中的语句来结束循环了。由程序可知,当读入的字符是“换行”符(’\\n’)时,将执行break语句,这时,将终止循环体的执行。

【例6-14】 在循环体中break语句执行示例。 #include\main () {

int i,s=0;

for(i=1;i<=10;i++) { s=s+2; if(s>5) break; /*跳出整个for循环结构*/ printf(\ } }

程序运行结果: s=2 s=4

上例中,如果没有break语句,程序将进行10次循环;但当i=3时,s的值为6,if语句中的表达式:s>5的值为1,于是执行break语句,跳出for循环,从而提前终止循环。

6.6.2 continue语句

continue语句的一般形式为: continue;

其作用是结束本次循环,即跳过本层循环体中余下尚未执行的语句,接着再一次进行循环的条件判定。注意:执行continue语句并没有使整个循环终止。 在while和do-while循环中,continue语句使得流程直接跳到循环控制条件的测试部分,然后决定循环是否继续进行。在for循环中,遇到continue后,跳过循环体中余下的语句,而去对for语句中的“表达式3”求值,然后进行“表达式2”的条件测试,最后根据“表达式2”的值来决定for循环是否执行。在循环体内,不论continue是作为何种语句中的语句成分,都将按上述功能执行,这点与break有所不同。

【例6-15】 从键盘输入30个字符,并统计其中数字字符的个数。

#include\main () {

int sum=0,i;

13

char ch;

for(i=0;i<30;i++) { ch=getchar(); if(ch<'0'||ch>'9') continue; /*终止本轮循环,但未跳出循环结构*/ sum++; }

printf(\}

在本程序中,当读入的字符(在ch中)不是数字字符(‘0’~‘9’)时,将不执行sum++语句,而立即进行下一轮循环。

【例6-16】 在循环体中continue语句执行示例。

#include\main () {

int k=0,s=0,i; for(i=1;i<=5;i++) { s=s+i; if(s>5) { printf(\ continue; /*终止本轮循环,但未跳出循环结构*/ } k=k+s; printf(\ } }

程序运行结果: i=1,s=1,k=1 i=2,s=3,k=4 ***i=3,s=6,k=4 ***i=4,s=10,k=4 ***i=5,s=15,k=4

程序运行时,当i为1和2时,并不执行if之后的复合语句,仅执行k=k+s;和第2个输出语句;执行第三次循环时,s的值已是6,这时表达式s>5的值为1,因此执行if分支中的第1个输出语句和continue语句,并跳过k=k+s;语句和第2个输出语句;接着执行for后面括号中的i++,继续执行下一次循环。由输出结果可见,后面三次循环中k的值没有改变。

由以上几个例子可以看出,continue语句和break语句的主要区别是:continue语句只终止本次循环,而不是终止整个循环结构的执行;break语句则是结束循环,不再进行条件判断。如果有以下两个循环结构:

(1) while (表达式1) (2) while (表达式1) { ……; { ……;

14

if(表达式2) break; if(表达式2)continue; …… ; ……; } }

表达式1真假表达式1真假表达式2假真break表达式2假真continuewhile循环的下一语句图 6-10 break流程示意while循环的下一语句图 6-11 continue流程示意程序(1)的流程图如图6-10所示,而程序(2)的流程图如图6-11所示。请注意图中当“表达式2”为真时,流程的转向。

6.7 应用举例

【例6-17】从键盘输入一个大于2 的整数n,判断n是不是素数。 只能被1和它本身整除的数是素数。为了判断n是不是素数,可以让n除以2到n的平方根(sqrt(n))之间的每一个整数,如果n能被某个数整除,则说明n不是素数,否则,n一定是素数。程序的执行过程见图6-12。程序如下:

#include\

读入n#include\直到n>2m=sqrt(n) flag=0main ()

for i=1 to m{ n被i整除真假 int n, m, i, flag;

flag=1 do 结束循环flag==1 scanf (\真假n是素数n不是素数 while(n<=2);

图 6-12 判断素数N—S图 m=sqrt(n); flag=0;

for(i=2;i<=m;i++) { if(n%i==0) { flag=1; break; }

15

}

if(flag==1) printf(\else printf(\

}

说明:

(1) 此程序中增加了一个头文件“math.h”,这是因为在使用sprt函数(求平方根)时需要这一头文件。

(2) 在程序的开始处利用了do-while循环语句来处理读键盘过程,这是为了保证所读入的数据是一个大于2的整数,如果不满足这一条件,将重复读操作,一直到读入的数据满足条件为止。

(3) 程序中的flag变量是用于设置标志的,当flag=1时,说明n不满足素数条件,最后通过对flag的判断来显示相应的提示信息。正确地使用标志变量,对程序设计会带来方便。

一个循环体内又包含另一个完整的循环结构,称为循环的嵌套。内嵌的循环中还可以嵌套循环,这就是多层循环。

三种循环(while循环、do-while循环和for循环)可以相互嵌套。例如: (1) while( )

{

……;

for( ; ; ) {……;} }

(2) for( ; ; ) {

……; do {……;

}while( ); }

【例6-18】求100~200之间的所有素数

在例6-17的基础上,对本题用一个嵌套的for循环即可处理。程序如下: #include\#include\main () {

int n, m, i, flag;

for(n=101;n<=200;n=n+2) { m=sqrt(n); flag=0; for(i=2;i<=m;i++) {

16

}

if(n%i==0) { flag=1; break; } }

if(flag==0) printf(\

}

程序运行结果:

101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199

循环变量n代表被检测的数,从101变化到200。在每一次循环中,又内嵌一个for循环,用来检测当前的n是否素数,这个内嵌循环的循环变量是i,它从2变化到m。

【例6-19】输出下三角形式九九乘法表。 1 2 3 4 5 6 7 8 9 1 1 2 2 4 3 3 6 9

4 4 8 12 16 ……

9 9 18 27 36 45 54 63 72 81

对这样表格形式的输出,可以用多次循环来解决。用外层循环来控制行,如: for(i=1;i<=9;i++)

用内层循环来控制列,如: for(j=1;j<=i;j++) 程序如下: #include\main () {

int i,j;

printf(\ ***九九乘法表***\\n \ /*输出表头*/

for(i=1;i<=9;i++) /*外层循环,控制行*/ printf(\ printf(\

for(i=1;i<=9;i++) /*内层循环,控制列*/ {

printf(\ for(j=1;j<=i;j++) printf(\ printf(\ } }

【例6-20】求Fibonacci数列的前50项。Fibonacci数列的第一项为1,第二项为1,

17

从第三项开始,每项等于前两项之和。

我们可以引入三个变量f1、f2和f,分别存放数列的前两项和当前项,其中f=f1+f2。用一个循环来求解数列的前50项,每次求下一项时,令f1=f2,f2=f,f=f1+f2。程序如下:

#include\main () {

int i;

long f1=1,f2=1,f; /*数字较大,可能超出整数范围,定义为长整型*/ printf(\输出数列的前两项*/ for(i=3;i<=30;i++) { f=f1+f2; printf(\ f1=f2; /*这两行为下一次循环作准备*/ f2=f; } }

本章小结

循环结构的设计,是程序设计的重要组成部分,也是等级考试的一个重要考点。

while循环和do-while循环是两种形式非常相近的循环结构,都是当循环条件满足时执行循环体。它们之间的主要区别是:

while循环先检测循环条件然后再决定是否执行循环体;而do-while循环先执行一次循环体再检测循环条件,根据检测结构决定是否继续执行循环体。

for循环相对上述两种循环结构而言功能更加强大,在for语句中可包含三个表达式,习惯用法是用表达式1来实现变量初始化,用表达式2来作循环条件判断,用表达式3作循环变量的自增自减。

用if和goto语句组合也可以构成循环,但这种方法不符合结构化程序设计准则,因此并不提倡。

解决同一问题可以采用上述各种循环结构,一般来讲它们之间可以互相代替使用。在一个循环的循环体中可以嵌入另一个循环结构,这就是循环的嵌套。循环嵌套的层数并没有限制,但层数过多会使可读性变差,一般嵌套层数不宜超过3层。

continue语句只能出现在循环体中,它的作用是终止本次循环转而开始进行下一次循环;和continue语句相对应的break语句的作用是终止循环,并跳出当前循环结构。 习题:

1. 比较while语句、do-while语句和for语句的异同. 2. 阅读下列程序,指出运行结果: main( ) { int x=3; do { printf(\ }while(!(--x)); }

18

3. 阅读下列程序,指出运行结果: main( ) {

int j=0,k=0,a=0; while(j<2) { j++; a++; k=0; }

while(k<=3) { k++; if(k%2!=0) continue; a++; } a++;

printf(\ }

4. 阅读下列程序,指出运行结果:

main( ) { int i;

for(i=0;++i;i<5) { if(i==3) { printf(\ break; } printf(\ } }

5. 阅读下列程序,指出运行结果: main( ) {

int a,b;

for(a=1,b=1;a<=100;a++) { if(b>=20) break; if(b%3==1)

19

{ b+=3; continue; } b-=5; }

printf(\

}

6. 阅读下列程序,指出运行结果: main( ) {

int i,a=0;

for(i=1;i<=5;i++) { do { i++; a++; }while(i<3); } i++;

printf(\}

7. 已知有如下计算公式:

π≈4*(1/1-1/3+1/5-1/7+……)

下列程序就是根据这一公式计算圆周率的。其中,精度控制在0.00001;变量s表示当前符号项,item表示当前项,n表示当前项的序号。阅读程序,并填空: #include \ main( ) {

float pai=0.0,item=1.0,s=1.0; int n=1;

while( ) { pai+=item; s=-s; item=s/(2*n+1); }

pai=4*pai;

printf(\ }

8. 编写程序,求1000以内奇数的和。

9. 编写程序,求任意两个整数之间所有的素数。

20

10. 编写程序,以上三角形式输出九九乘法表。

11. 编写程序,求1!+2!+3!+……+n!。n从键盘输入。

12. 一球从100米高空自由落下,每次落地后反跳回原高度的一半,再落下,求它在第十次落地时,共经过多少米,第十次反弹多高?

21

本文来源:https://www.bwwdw.com/article/c6h.html

Top