《2022年C程序设计第章循环结构程序设计.docx》由会员分享,可在线阅读,更多相关《2022年C程序设计第章循环结构程序设计.docx(23页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、精品学习资源封面欢迎下载精品学习资源作者: PanHongliang仅供个人学习第6章 循环结构程序设计许多问题的求解归结为重复执行的操作, 例如输入多个同学的成果、对象遍历、迭代求根等问题. 这种重复执行的操作在程序设计语言中用循环把握来实现. 几乎全部有用程序都包含循环. 特殊是在现代多媒体处理程序(图像、声音、通讯)中,循环更是必不行少 .欢迎下载精品学习资源依据开头循环的初始条件和终止循环的条件不同,C语言中用如下语句实现循环(1) while 语句 .(2) do-while语句.(3) for 语句 .(4) 用goto 语句和 if 语句构成循环 .循环结构在程序设计中特殊重要
2、. 所谓循环结构就是当给定条件成立时,反复执行某段程序,直到条件不成立时为止 . 给定的条件称为循环条件,反复执行的程序段称为循环体 .6.1 while语句while语句最简洁的情形为循环体只有一个语句,其形式如下:while表达式 语句;但是, while语句通常使用更复杂的形式,也就是其一般形式:while表达式 语句序列;其中表达式是循环条件,语句序列为循环体 . 其执行过程是:先运算 while 后面圆括号内表达式的值,假如其值为真(非 0 ),就执行语句序列(循环体),然后再运算 while 后面圆括号内表达式的值,并重复上述过程,直到表达式的值为“假”(值为0)时,退出循环,并转
3、入下一语句去执行 .While 循环的执行流程如图 6-1 所示 .使用 while 语句时,需留意如下几个问题:( 1) while语句的特点是先判定表达式的值,然后依据表达式的值准备是否执行循环体中的语句,因此,假如表达式的值一开头就为“假“,就循环体将一次也不执行.( 2)当循环体由多各语句组成时,必需用左、右花括号括起来,使其形成复合语句.如:whilex0s+=xx-;( 3)为了使循环最终能够终止,而不至于使循环体语句无穷执行,即产生“死循环”.因此,每执行一次循环体,条件表达式的值都应当有所变化,这既可以在表达式本身中实现,也可以在循环体中实现.【例 6-1 】利用 while语
4、句,编写程序,求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 中,依次类
5、推,这和人们心算的过程没有什么区分, sum 代表着人们脑中累加的那个和数,不同的是心算的过欢迎下载精品学习资源程由人们自己把握 . 在这里, sum 累加的过程要放在循环中,由运算机来判定所加的数是否已经超过 100,加数就放在变量i中,并在循环过程中一次次增加1. 整个流程如图 6-2 所示.图 6-2 累加求和流程图以下就是求累加和的典型算法. mainint i=1, sum=0;/*i的初值为 1, sum的初值为 0*/ whilei=100/*当 i 小于或等于 100 时执行循环体 */sum=sum+i;/*在循环体中累加一次,i增加 1*/i=i+1;/*在循环体中 i 增
6、加 1*/printfsum=%dn,sum;程序运行后的输出结果:sum=5050留意:( 1) 假如在第一次进入循环时,while后圆括号内表达式的值为0,循环一次也不执行. 在本程序中,假如i 的初值大于 100 将使表达式 i100时循环终止 . 假如没有这一语句,就i的值始终不变,循环将无限进行.( 3) 在循环体中,语句的先后位置必需符合规律,否就将会影响运算结果,例如,如将上例中的 While循环体改写成:whilei=100i+;/*先运算 i+, 后运算 sum的值 */ sum=sum+i;运行后,将输出:sum=5150运行的过程中,少加了第一项的值1,而多加了最终一项的
7、值101.【例 6-2 】利用 while语句,运算1+1/2+1/4+ +1/50 的值,并显示出来. #include“stdio.h”mainfloat sum=1;int i=2;while i=50sum +=1/float i;i+=2 ;printfsum=%f,sum;欢迎下载精品学习资源运行结果:sum=2.907979留意:在此程序中,在循环体中进行累加运算时,必需要对变量 i 进行强制类型转换, 即利用( float ) i 使其变为浮点型中间变量后再参加运算,否就,由于 i 中存放的是大于1 的整型量,所以, 1/i 将按整型规章运算,其结果总是为 0.6.2 do-w
8、hile循环语句do-while循环结构的形式如下:do语句序列(循环体);while表达式 ; 例如:doi+;s+=i;whilei10;说明:( 1) do 是 C 语言的关键字,必需与While 联合使用 .( 2) do-while循环由 do 开头,用 while终止 . 必需留意的是:在while (表达式) 后的“;”不行丢,它表示do-while语句的终止 .( 3) while后一对圆括号中的表达式,可以是C 语言中任意合法的表达式. 由它把握循环是否执行 .( 4) 按语法,在 do 和 while之间的循环体只能是一条可执行语句. 如循环体内需要多个语句,应当用大括号括
9、起来,组成复合语句.do-while循环的执行过程是这样的(如图6-3 所示):(1) 执行 do 后面循环体中的语句 .(2) 运算 While后面一对圆括号中表达式的值. 当值为非零时,转去执行步骤1;当值为零时,执行步骤( 3) .(3) 退出 do-while循环.由 do-while构成的循环与 while循环特殊相像,它们之间的主要区分是:while循环结构的判定把握显现在循环体之前,只有当while后面表达式的值为非零时,才能执行循环体;在do-while构成的循环结构中,总是先执行一次循环体,然后再求表达式的值,因此,无论表达式的值是零仍是非零,循环体至少要被执行一次.和 wh
10、ile循环一样,在 do-while循环体中,确定要有能使while后表达式的值变为0 的操作,否就,循环将会无限制的进行下去.【例 6-3 】利用 do-while语句,编写程序,求1+2+3+100 的值.依据 do-while循环的结构,先画出流程图,见图6-4 ( a 是传统流程图, b 是 N-S图) . 程序如下: #includestdio.h main int i=1,sum=0;欢迎下载精品学习资源dosum=sum+i;i=i+1 ;whilei=100;printfsum=%dn,sum;程序运行后的输出结果:sum=5050使用 do-while语句应留意如下几个问题:
11、( 1)由于 do-while语句是先执行一次循环体,然后再判定表达式的值. 所以,无论一开头表达式的值为“真”仍是为“假”,循环体中的语句都至少被执行一次,这一点同 while语句是有区分的 .( 2)假如 do-while语句的循环体部分是由多个语句组成的话,就必需用左、右花括号括起来,使其形成复合语句.( 3)C 语言中的 do-while语句是在表达式的值为真时重复执行循环体,这一点与别的语言中类似语句有区分,在程序设计时应引起留意.【例 6-4 】 利用 do-while语句运算 1+1/2+1/4+ +1/50 的值,并显示出来.mainint i=2; float sum=1;d
12、osum+=1/floati;i+=2 ;whilei=50;printfsum=%fn,sum;运行结果:sum=2.907979在一般情形下,用while语句和 do-while语句处理同一问题时,如二者的循环体部分是一样的,它们的结果也一样. 如例 6-1 和例 6-3 中的循环体是相同的,得到的结果也相同.但在 while后面的表达式一开头就为假(0 值)时,两种循环的结果是不同的.【例 6-5 】while和 do-while循环的比较mainmainint sum=0,i;int sum=0,i;scanf%d,&i;scanf%d,&i;whilei=10dosum=sum+i;
13、sum=sum+i;i+ ;i+;whilei=10;欢迎下载精品学习资源printfsum=%dn,sum;printfsum=%dn,sum;本例左半部分用while循环求 i到 10 的连加和, i的值由用户输入 . 右半部分用do- while循环实现相同的功能 . 当输入 i 的值小于或等于10 时,二者得到的结果相同. 例如, 当输入的 i=1时,用 while结构和 do-while结构得到的结果是都是55;而当输入的 i的值大于 10 时,二者得到的结果就不同了. 例如,当输入的 i=15 时,用 while结构得到的结果是 0;而用 do-while结构得到的结果是15. 这
14、是由于此时对 while循环来说,一次也不 执行循环体,而对do-while循环来说,就要执行一次循环体. 由此可以得到结论:当while后面的表达式的第一次的值为“真”时,两种循环得到的结果相同. 否就,两者结果不同(指两者具有相同循环体的情形).6.3 for语句for语句构成的循环通常称为for循环.for循环的一般形式如下:for (表达式 1;表达式 2;表达式 3) 循环体;例如:fork=0;k10;k+ printf“* ” ;以上 for循环在一行上打印10 个“ * ”号 .for是 C 语言的关键字,其后的圆括号中通常含有3 个表达式,各表达式之间用“;”隔开 . 这三个
15、表达式可以是任意表达式,通常主要用于for循环的把握 . 紧跟在for 之后的循环体,在语法上要求是一条语句,如在循环体内需要多条语句,应当用大括号括起来,形成复合语句. for循环的执行过程如下:(1) 运算“表达式 1” .(2) 运算“表达式 2”,如其值为非零,就转步骤(3);如其值为零,就转步骤( 5) .(3) 执行一次循环体 .(4) 运算“表达式 3”,然后转向步骤2.(5) 终止循环,执行 for循环之后的语句 .整个流程如图 6-5 所示 .【例 6-6 】请编写一个程序,运算半径为0.5 、1.5 、2.5 、3.5 、4.5 、5.5mm 时的圆面积. 本例要求运算6
16、个不同半径的圆面积,且半径的变化是有规律的,从0.5mm 开头按增1mm的规律递增,可直接用半径r 作为 for循环把握变量,每循环一次使r 增 1 直到 r 大于 5.5 为止. 程序如下:#include stdio.h mainfloat r, s;float Pai=3.14159;for r=0.5; r6.0; r+s=Pai*r*r;/*运算圆面积 s 的值 */ printfr=%3.1f s=%5.2fn, r, s;欢迎下载精品学习资源运行结果:r=0.5s=0.79r=1.5s=7.07r=2.5s=19.63r=3.5s=38.48r=4.5s=63.62r=5.5s=
17、95.03程序中定义了一个变量Pai, 它的值是3.14159 ;变量 r既用作循环把握变量又是半径 的值,它的值由0.5变化到 5.5 ,循环体共执行6 次当 r增到 6.0时,条件表达式“r6.0 ”的值为 0,从而退出循环 .for循环的循环体是个用花括号括起来的复合语句,其中包含两个语句,通过赋值语句把求出的圆面积放在变量s 中,然后输出r 和 s 的值 .【例 6-7 】求正整数 n 的阶乘 n. 其中 n 由用户输入 .在本例中省略了对用户输入的n 的合理性的检测,整个流程如图6-6所示 . 阶乘结果用 fac 表示,它的值一般比较大,因此定义为实型变量. 程序如下:#includ
18、estdio.h mainfloat fac=1; int n,i;scanf%d,&n;/*以下省略了对用户输入的n 的合理性的检测 */ fori=1;i=n ;i+fac=fac*i;printffac=%7.0fn,fac;由以上两个例子可以看出,for语句最典型的应用形式,也就是最易懂得的形式如下:for (循环变量赋初值;循环条件;循环变量增值) 语句序列(循环体);例如:fori=1;i=10 ;i+ fac=fac*i;它相当于以下语句;i=1;whilei=10fac=fac*i;i+;明显,用 for语句简洁、便利 . 对于以上 for语句的一般形式也可以改写如下: 表达式
19、 1;while(表达式 2)语句序列(循环体);欢迎下载精品学习资源表达式 3;说明:(1) for语句一般形式中的“表达式1”可以省略,此时应在for语句之间前给循环变量赋初值 . 留意省略表达式1 时,其后的分号不能省略. 如for;i=10 ;i+ fac=fac*i;执行时,跳过“求解表达式1”这一步,其它不变 .(2) 假如表达式 2 省略,即不判定循环条件,循环无终止地进行下去. 也就是认为表达式 2 始终为真 . 见图 6-7. 例如:fori=1; i+ fac=fac*i;它相当于:i=1;while1fac=fac*i;i+;(3) 表达式 3 也可以省略,但此时程序设计
20、者应另外设法保证循环能正常终止. 如:fori=1;i=10 ;fac=fac*i;i+;本例把 i+ 的操作不放在 for语句的表达式3 的位置处,而作为循环体的一部分,成效是一样的,都能使循环正常终止.(4) 可以省略表达式1 和表达式 3,只有表达式 2,即只给循环条件. 如:for; i=10 ;whilei=10fac=fac*i;相当于:fac=fac*i;i+;i+;在这种情形下,完全等同于while语句. 可见 for语句比 while语句功能强,除了可以给出循环条件外,仍可以赋初值,使循环变量自动增值等.(5) 三个表达式都可以省略,如for; 语句序列(循环体);相当于wh
21、ile1语句序列(循环体);即不设初值,不判定条件(认为表达式2 为真),循环变量不增值. 无终止地执行循环体 .(6) 表达式1 可以是设置循环变量初值的赋值表达式,也可以是与循环变量无关的其它表达式 . 如欢迎下载精品学习资源for fac=1;i=10 ;i+ fac=fac*i;表达式 3 也类似 .表达式 1 和表达式 3 可以是一个简洁的表达式,也可以是逗号表达式,即包含一个以上的简洁表达式,中间用逗号间隔. 如:forfac=1,i=1;i=10 ;i+ fac=fac*i;或fori=0,j=100;i=j ;i+,j- k=i+j;表达式 1 和表达式 3 都是逗号表达式,各
22、包含两个赋值表达式,即同时设两个初值,使两个变量增值,执行情形见图6-8.在逗号表达式内按自左至右次序求解,整个逗号表达式的值为其中最右边的表达式的值. 如:fori=1;i=10 ;i+,i+ fac=fac*i;相当于fori=1;i=10 ;i+2 fac=fac*i;(7) 表达式 2 一般是关系表达式(如i10 )或规律表达式(如ab&xy),但也可以是数值表达式或字符表达式,只要其值为非零,就执行循环体. 分析下面两个例子: fori=0;c=getchar . =n ;i+=c ;在表达式2 中先从终端接收一个字符给c,然后判定此赋值表达式的值是否不等于n (换行符),假如不等于
23、n ,就执行循环体 . 此 for语句的执行过程见图6-9 ,它的作用是不断输入字符,将它们的ASCII 码相加,直到输入一个“回车换行”符为止.留意:此 for语句的循环体为空语句,把原先要在循环体内处理的内容放在表达式3中,作用是一样的 . 可见 for语句功能强,可以在表达式中完成原先应在循环体内完成的操作. for; c=getchar . =n ; printf“%c”,c ;无表达式 1 和表达式 3,其作用是每读入一个字符输出该字符,直到输入一个“回车换行”符为止 . 请留意,从终端键盘向运算机输入时,是在输入回车以后才送到内存缓冲区中去的 . 运行情形是:Cmputer(输入)
24、Cmputer(输出)而不是CCoommppuutteerr即不是从终端敲入一个字符马上输出一个字符,而是输入回车后数据送入内存缓冲区,然后每次从缓冲区读一字符,最终输出.从上面介绍可以知道C 语言中的 for语句比其它语言(如BASIC,PASCAL)中的 for语句功能强得多 . 可以把循环体和一些与循环把握无关的操作也都作为表达式1 或表达式 3 显现,这样程序可以短小简洁,但过分地利用这一特点会使for语句显得杂乱,可读性降 低,建议不要把与循环把握无关的内容放到for语句中 .6.4 4语句标号和 goto 语句6.4.1 语句标号语句标号是一个标识符加一个冒号“: ”,它表示程序指
25、令的地址. 语句标号只能由字母、数字和下划线组成,第一个字符必需为字母或下划线,特殊要留意不能用整数作语句标号 . 下面是合法的语句标号:欢迎下载精品学习资源loop :ERR: 下面是不合法的语句标号:1000:! Note:6.4.2 goto语句goto 语句为无条件转向语句,一般形式为:goto语句标号它的作用是无条件转向“语句标号”处执行.结构化程序设计方法主见限制使用goto语句,由于 goto语句不符合结构化程序设计准就,无条件转向使程序结构无规律、可读性变差. 但假如能大大提高程序的执行效率,也可以使用 . 一般来说,可以有两种用途:( 1) 与 if语句一起构成循环 .( 2
26、) 从循环体中跳到循环体外,但在C 语言中可以用break语句和 continue语句(见 6.6 )跳出本层循环和终止本次循环.goto语句的使用机会已大大削减,只是需要从多层循环的内层跳到外层循环外时才用到. 但是这种用法不符合结构化程序设计原就,一般不宜接受,只有在不得已时(例如能大大提高程序的执行效率)才使用.【例 6-8 】用 if语句和 goto 语句构成循环,求1+2+3+ +100 的值 . mainint i,sum=0;i = 1;loop:if i = 100 sum = sum + i;i+;goto loop;printfsum=%d,sum;运行结果如下:sum=5
27、050这里用的是“当型”循环结构,当条件中意时,执行相加操作,并使计数器i 的值加1 ,然后无条件转向,循环判定条件是否中意.if语句与 goto 语句一起也可以构成“直到”型循环 .6.5 几种循环的比较在 C 语言中 ,四种形式的循环都可以用来处理同一问题,但具体使用时又存在一些微小差别,一般情形下它们可以相互代替,但一般不提倡用 goto 型循环 .1. while 和 do-while 型循环,只在 while 后面指定循环条件,在循环体中应包含使循环趋于终止的语句(如i+, 或 i=i+1 等) .for 语句可以在表达式3 中包含使循环趋于终止的操作,甚至可以将循环体中的操作全部放
28、到表达式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 和 cont
29、inue 语句见下节) .而对用 goto 语句和 if 语句构成的循环,不能用 break 和 continue 语句进行把握 .下面举一个例子,来说明如何用各种循环方法解决相同的问题.要求:把 50100 之间的不能被 3 整除的数输出 .【例 6-9 】用 while语句实现#includestdio.h main int n=50;/*循环变量初始化 .*/ whilen=100/*先判定条件,再准备执行与否*/ifn%3.=0printf%4d,n;n+;【例 6-10 】用 do-while语句实现#includestdio.h main int n=50;/*循环变量初始化 .*
30、/do/*先执行一次循环体,再判定条件,准备是否连续执行循环体*/ifn%3.=0printf%4d,n;n+;whilen=100;【例 6-11 】用 for语句实现#includestdio.h main int n;/*循环变量初始化、条件判定、循环变量自增在一条语句中实现.*/ forn=50;n=100;n+ifn%3.=0printf%4d,n;【例 6-12 】用 if和 goto 语句构成的循环实现#includestdio.h欢迎下载精品学习资源main 欢迎下载精品学习资源int n=50;loop: ifn%3.=0n+;ifn=A&ch=Zsum+;printfsum
31、=%dn,sum;说明:在本程序中,while ( 1 )表示“无限循环”,即循环条件总为“真”,在这种情形下,就只能依靠循环体中的语句来终止循环了. 由程序可知,当读入的字符是“换行” 符( n )时,将执行 break 语句,这时,将终止循环体的执行.【例 6-14 】 在循环体中 break 语句执行示例 . #includestdio.hmain int i,s=0;fori=1;i5break ;/*跳出整个 for循环结构 */printfs=%dn,s;程序运行结果:s=2 s=4上例中,假如没有break语句,程序将进行10 次循环;但当 i=3时, s 的值为 6, if语句
32、中的表达式: s5 的值为 1,于是执行 break 语句,跳出 for循环,从而提前终止循环.6.6.2 continue语句continue 语句的一般形式为: continue;其作用是终止本次循环,即跳过本层循环体中余下尚未执行的语句,接着再一次进行循环的条件判定 .留意:执行continue 语句并没有使整个循环终止.在 while 和 do-while 循环中, continue 语句使得流程直接跳到循环把握条件的测试部分, 然后准备循环是否连续进行.在 for 循环中,遇到continue 后,跳过循环体中余下的语句, 而去对 for 语句中的“表达式3”求值,然后进行“表达式2
33、”的条件测试,最终依据“表达式 2”的值来准备 for 循环是否执行 .在循环体内,不论continue 是作为何种语句中的语句成分,都将按上述功能执行,这点与break 有所不同 .欢迎下载精品学习资源【例 6-15 】 从键盘输入 30 个字符,并统计其中数字字符的个数. #includestdio.hmain int sum=0,i ;char ch;fori=0 ; i30 ;i+ch=getchar;ifch9continue;/* 终止本轮循环,但未跳出循环结构*/ sum+;printfsum=%dn,sum ;在本程序中,当读入的字符(在ch 中)不是数字字符(0 9)时,将不
34、执行sum+ 语句,而马上进行下一轮循环.【例 6-16 】 在循环体中 continue 语句执行示例 .#includestdio.h main int k=0,s=0,i ;fori=1 ; i5k=k+s ;printf*i=%d,s=%d,k=%dn,i,s,k;continue;/* 终止本轮循环,但未跳出循环结构*/欢迎下载精品学习资源printfi=%d,s=%d,k=%dn,i,s,k;程序运行结果: 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
35、 之后的复合语句 ,仅执行 k=k+s ;和第 2 个输出语句;执行第三次循环时, s 的值已是 6,这时表达式 s5 的值为 1,因此执行 if 分支中的第 1 个输出语句和 continue 语句,并跳过 k=k+s ;语句和第 2 个输出语句;接着执行for 后面括号中的 i+ ,连续执行下一次循环 .由输出结果可见,后面三次循环中 k 的值没有欢迎下载精品学习资源转变 .由以上几个例子可以看出,continue 语句和 break 语句的主要区分是: continue 语句只终止本次循环,而不是终止整个循环结构的执行;break 语句就是终止循环,不再进行条件判定 .假如有以下两个循环
36、结构:( 1) while 表达式 1( 2) while 表达式 1 ; ;if (表达式 2) break;if (表达式 2) continue; ; ;程序( 1)的流程图如图6-10 所示,而程序( 2)的流程图如图6-11 所示 .请留意图中当“表达式 2”为真时,流程的转向.6.7应用举例【例 6-17 】从键盘输入一个大于2 的整数 n,判定 n 是不是素数.只能被 1 和它本身整除的数是素数. 为了判定 n 是不是素数,可以让n 除以 2 到 n 的平方根( sqrtn)之间的每一个整数,假如n 能被某个数整除,就说明n 不是素数,否就,n 确定是素数 . 程序的执行过程见图
37、6-12. 程序如下:#includestdio.h #includemath.h main int n, m, i, flag;doscanf %d,&n;whilen=2; m=sqrtn;flag=0;fori=2;i=m;i+ifn%i=0欢迎下载精品学习资源ifflag=1flag=1 ;break ;欢迎下载精品学习资源说明:elseprintf%d is NOT a prime number.n,n;printf%d is a prime number.n,n;欢迎下载精品学习资源( 1) 此程序中增加了一个头文件“math.h ”,这是由于在使用sprt函数(求平方根)时需要这一头文件.( 2) 在程序的开头处利用了do-while循环语句来处理读键盘过程,这是为了保证所欢迎下载精品学习资源读入的数据是一个大于2 的整数,假如不中意这一条件,将重复读操作,始终到读入的数据中意条件为止 .( 3) 程序中的 flag变量是用于设置标志的,当flag=1时,说明 n 不中意素数条件, 最终通过对 flag的判定来显示相应的提示信息. 正确地使用标志变量,对程序设计会带来便利 .一个循环体内又包含另一个完整的循环结构,称为循环的嵌套. 内嵌的循环中仍可以嵌套循
限制150内