1、第第5 5章章 循环结构程序设计循环结构程序设计 掌握循环结构的基本特点掌握循环结构的基本特点 掌握掌握3 3种循环语句:种循环语句:forfor语句、语句、whilewhile语句和语句和do-do-whilewhile语句语句 学会利用学会利用forfor语句、语句、whilewhile语句和语句和do-whiledo-while语句设计语句设计简单的循环程序简单的循环程序 了解了解gotogoto语句构成的循环语句构成的循环 5.1 案例:一次有趣的投币游戏案例:一次有趣的投币游戏 5.1.1 5.1.1 游戏规则游戏规则 5.1.2 问题的解决 游戏的开始游戏的开始首先游戏中的投币数和
2、投币箱我们分别用变量首先游戏中的投币数和投币箱我们分别用变量i i和和s s来存储。游戏之前,执行以下两条语句:来存储。游戏之前,执行以下两条语句:s=0;s=0;/*投币箱开始必须是空的投币箱开始必须是空的*/i=1;i=1;/*投币数开始是投币数开始是1 1*/游戏的进行游戏的进行每次的投币操作都可以看成以下两条语句的执行:每次的投币操作都可以看成以下两条语句的执行:s=s+i;s=s+i;/*第第i i个人投币个人投币i i 枚枚*/i=i+1;i=i+1;/*第第i+1i+1个人准备投币个人准备投币*/将以上两条语句运行将以上两条语句运行100100次就完成了任务,就相当于投币次就完成
3、了任务,就相当于投币100100次。次。游戏的结束游戏的结束 还有个重要的问题就是,游戏什么时候结束?很还有个重要的问题就是,游戏什么时候结束?很显然,当第显然,当第100100个人投币结束,游戏结束,即只要个人投币结束,游戏结束,即只要i=100i=100,游,游戏继续进行,否则结束。戏继续进行,否则结束。2)1100(*100s5.1.2 问题的解决s=0;s=0;/*盒子开始为空盒子开始为空*/i=1;i=1;/*第第1 1次投币次投币*/while(i=100)while(i=100)/*100 100次投币次投币*/s=s+i;s=s+i;/*投入投入i i 枚硬币到枚硬币到s s中
4、中*/i=i+1;i=i+1;/*计算下次投币数计算下次投币数 */2)1100(*100s循环结构语句循环结构语句 for for 循环循环 while while 循环循环 do-while do-while 循环循环5.2 while循环循环 whilewhile循环通过循环通过whilewhile语句实现。语句实现。whilewhile循环又称为循环又称为“当型当型”循环。循环。一般格式为:一般格式为:whilewhile(表达式表达式)语句语句 其中,括号后面的语句可以是一条语句,也可以是复合其中,括号后面的语句可以是一条语句,也可以是复合语句。它们都称为循环体。语句。它们都称为循环
5、体。whilewhile语句的执行过程为:语句的执行过程为:(1)(1)计算并判断表达式的值。若值为计算并判断表达式的值。若值为0 0,则结束循环,则结束循环,退出退出whilewhile语句;若值为非语句;若值为非0 0,则执行循环体,则执行循环体 (2)(2)转步骤转步骤(1)(1)5.2 while循环循环 流程图流程图【例例5-1】计算计算s=1+2+3+100。#include#include void main()void main()int i,s;int i,s;i=1;i=1;s=0;s=0;while(i=100)/while(i=100)/*循环控制循环控制 */s=s+
6、i;s=s+i;i=i+1;i=i+1;printf(s=%dn,s);printf(s=%dn,s);注意注意:循环体包括一条或多条语句,多条语句必须用一对循环体包括一条或多条语句,多条语句必须用一对花括号花括号“”括起来。括起来。合理的循环是有限次循环。如果循环不能退出,则合理的循环是有限次循环。如果循环不能退出,则称为称为“死循环死循环”,在程序设计中应该避免出现。,在程序设计中应该避免出现。控制循环执行的次数因素包括循环中的循环条件、控制循环执行的次数因素包括循环中的循环条件、控制循环的主要变量的初值和终值以及每次变化的控制循环的主要变量的初值和终值以及每次变化的幅度等。幅度等。例如,
7、上例中例如,上例中i i有效地控制了循环的运行,有效地控制了循环的运行,i i从从1 1循环到循环到100100,每次加,每次加1 1,循环运行了,循环运行了100100次,次,i i也可也可以称为循环变量。以称为循环变量。注意注意:如果只有一个循环变量,而且循环变量每次有固定如果只有一个循环变量,而且循环变量每次有固定的增加和减少,则循环的次数可以用以下公式计算:的增加和减少,则循环的次数可以用以下公式计算:循环次数循环次数 =(=(终值终值-初值初值)/)/步长步长 +1+1 步长为循环变量每次增加或减少的值,例如,上例步长为循环变量每次增加或减少的值,例如,上例循环次数为:循环次数为:(
8、1001)/1+1(1001)/1+1,即,即100100次。次。步长可以为负数。步长可以为负数。【例例5-2】计算计算1到到100之间所有之间所有3的倍数的的倍数的和。和。#include#include void main()void main()int i,s;int i,s;i=3;s=0;i=3;s=0;while(i=99)while(i=99)s=s+i;s=s+i;i=i+3;i=i+3;printf(s=%dn,s);printf(s=%dn,s);5.3 do-while循环循环 do-whiledo-while循环,又称为循环,又称为“直到型直到型”循环循环,用用do-w
9、hiledo-while语句来语句来实现,其一般格式为:实现,其一般格式为:dodo 语句语句 while(while(表达式表达式););do-whiledo-while语句的执行过程为:语句的执行过程为:先执行循环体语句再判断表达式的值。若值为先执行循环体语句再判断表达式的值。若值为0 0,则结,则结束循环,退出束循环,退出do-whiledo-while语句;若值为非语句;若值为非0 0,则继续执行,则继续执行循环体。循环体。5.3 do-while循环循环流程图流程图【例例5-3】计算计算s=1+2+3+100。#include#include void main()void main
10、()int i,s;int i,s;i=1;s=0;i=1;s=0;do do s=s+i;s=s+i;i=i+1;i=i+1;while(i=100);while(i=100);printf(s=%dn,s);printf(s=%dn,s);do-whiledo-while循环和循环和whilewhile循环可以完成相同的任务。例如上面的程序都可循环可以完成相同的任务。例如上面的程序都可以计算出以计算出1 1到到100100的数的和。的数的和。do-whiledo-while循环的循环条件的判断在循环体的后面,所以和循环的循环条件的判断在循环体的后面,所以和whilewhile循环有循环有区
11、别,例如下面的两个程序:区别,例如下面的两个程序:int i=1;s=0;int i=1;s=0;int i=1,s=0;int i=1,s=0;whilewhile(i1i1)dodo s=s+i;s=s+i;s=s+i;s=s+i;i=i+1;i=i+1;i=i+1;i=i+1;while(i1);while(i1);printfprintf(s=%dn,ss=%dn,s);printf(s=%dn,s);printf(s=%dn,s);左边的程序运行结果为左边的程序运行结果为:s=0:s=0右边的程序运行结果为右边的程序运行结果为:s=1:s=1。5.4 for循环循环 forfor循环
12、是循环的一种标准形式,循环是循环的一种标准形式,通过通过forfor语句实现,语句实现,其语其语法如下:法如下:forfor(;)表达式,通常用于循环的初始化。包括循环变量的赋表达式,通常用于循环的初始化。包括循环变量的赋初值、其他变量的准备等;初值、其他变量的准备等;表达式,循环的条件判断式,如果为空则相当于真值;表达式,循环的条件判断式,如果为空则相当于真值;表达式,通常设计为循环的调整部分,主要是循环变表达式,通常设计为循环的调整部分,主要是循环变量的变化部分;量的变化部分;循环体,由一条或多条语句构成,多条语句需要用一循环体,由一条或多条语句构成,多条语句需要用一对花括号括起来。对花括
13、号括起来。5.4 for循环循环【例例5-4】计算计算s=1+2+3+100。#include#include void main()void main()int i,s;int i,s;for(i=1,s=0;i=100;i+)for(i=1,s=0;i=100;i+)s=s+i;s=s+i;printf(s=%dn,s);printf(s=%dn,s);forfor循环可以用以下循环可以用以下whilewhile循环代替:循环代替:;while(while();表达式可以是多个表达式构成的逗号表达式,例如表达式可以是多个表达式构成的逗号表达式,例如i=1,s=0;i=1,s=0;。、构成循
14、环的控制部分,、构成循环的控制部分,3 3个表达式之间用分号分个表达式之间用分号分隔。隔。表达式可以放在表达式可以放在forfor循环的前面,但后面的分号不能少,循环的前面,但后面的分号不能少,例如:例如:;forfor(;);表达式也可以省略,相当于始终为真值,从而构成无条表达式也可以省略,相当于始终为真值,从而构成无条件循环,循环将不能终止,需要采取其他措施。件循环,循环将不能终止,需要采取其他措施。表达式也可以省略,但作为循环变量的调整功能不能缺少,表达式也可以省略,但作为循环变量的调整功能不能缺少,可以在循环体中完成,例如下面的可以在循环体中完成,例如下面的forfor循环。循环。fo
15、rfor(i=1,s=0;i=100;)s=s+i+;(i=1,s=0;i=100;)s=s+i+;如果表达式和都省略的话,相当于如果表达式和都省略的话,相当于whilewhile循环,例如下循环,例如下面的程序形式:面的程序形式:i=1,s=0;i=1,s=0;forfor(;i=100;)/(;i=100;)/*相当于相当于 while(iwhile(i=100)=100)*/s=s+i+;s=s+i+;、均省略,即:、均省略,即:forfor(;)(;);相当于相当于whilewhile(1)(1);。循环的所有控制和计算功能都。循环的所有控制和计算功能都必须在循环体中完成,这样的循环适
16、合于随机退出必须在循环体中完成,这样的循环适合于随机退出循环程序的情况。循环程序的情况。表达式也可以省略,但必须至少保留一个分号,即:表达式也可以省略,但必须至少保留一个分号,即:forfor(;););一个分号即是一条空语句。一个分号即是一条空语句。如果、均省略,即如以下形式:如果、均省略,即如以下形式:forfor(;);(;);这将构成一个死循环。这将构成一个死循环。5.5 案例:倒数的求和案例:倒数的求和#include#include void main()void main()int i;int i;double s=0;double s=0;/*s s需要定义为需要定义为doub
17、ledouble型型 */for(i=1;i=99;i=i+2)for(i=1;i=99;i=i+2)/*先计算先计算:*/s=s+1.0/i;s=s+1.0/i;/*1.0/i 1.0/i不能写成不能写成1/i1/i*/for(i=2;i=100;i=i+2)for(i=2;i=100;i=i+2)/*再计算再计算:*/s=s 1.0/i;s=s 1.0/i;printf(s=%fn,s);printf(s=%fn,s);1001991.514131211#include#include void main()void main()int i;int i;double s=0;double
18、s=0;/*s s需要定义为需要定义为doubledouble型型 */for(i=1;i=100;i+)for(i=1;i=100;i+)if(i%2=1)if(i%2=1)s=s+1.0/i;s=s+1.0/i;/*i i是奇数时加是奇数时加1.0/i 1.0/i*/elseelses=s-1.0/i;s=s-1.0/i;/*i i是偶数时减是偶数时减1.0/i 1.0/i*/printf(s=%lfn,s);printf(s=%lfn,s);#include#include void main()void main()int i;int i;double s;double s;/*s s
19、需要定义为需要定义为doubledouble型型 */double flag=1;/double flag=1;/*doubledouble型的型的flagflag用于处理符号问题用于处理符号问题 */for(i=1,s=0;i=100;i+)for(i=1,s=0;i=100;i+)s=s+flag s=s+flag*1.0/i;1.0/i;/*用用flagflag处理符号问题处理符号问题*/flag=-flag;/flag=-flag;/*下一次下一次flagflag由由1 1变成变成-1-1,或者由,或者由-1-1变成变成1 1*/printf(s=%lfn,s);printf(s=%l
20、fn,s);5.6 循环嵌套循环嵌套(1 1)whilewhile()()whilewhile()()(2 2)forfor(;)(;)forfor(;)(;)(3 3)dodo dodo whilewhile();();whilewhile();();(4 4)whilewhile()()forfor(;)(;)(5 5)forfor(;)(;)whilewhile(;)(;)(6 6)dodo forfor(;);(;);whilewhile();();【例例5-6】计算计算s=1+(1+2)+(1+2+3)+(1+2+3+4)+(1+2+3+4+5)#include#include vo
21、id main()void main()int i,j,s;int i,j,s;for(i=1,s=0;i=5;i+)for(i=1,s=0;i=5;i+)for(j=1;j=i;j+)for(j=1;j=i;j+)printf(“i=%d,j=%d,s=%dn”,i,j,s);printf(“i=%d,j=%d,s=%dn”,i,j,s);s=s+j;s=s+j;printf(s=%dn,s);printf(s=%dn,s);可以删除【例例5-6】计算计算s=1+(1+2)+(1+2+3)+(1+2+3+4)+(1+2+3+4+5)5.7 break语句、语句、continue语句和语句和g
22、oto语句语句 5.7.1 breakbreak语句 switchswitch结构中可以用结构中可以用breakbreak语句跳出结构去执行语句跳出结构去执行switchswitch语句的下一条语句。实际上,语句的下一条语句。实际上,breakbreak语句语句也可以用来从循环体中跳出,常常和也可以用来从循环体中跳出,常常和ifif语句配合语句配合使用。例如:使用。例如:forfor(i=1;i100;i+i=1;i100i100)break;break;当变量当变量i100i100时退出循环。时退出循环。breakbreak语句不能用于循环语句和语句不能用于循环语句和switchswitch
23、语句之外语句之外的任何其他语句中。的任何其他语句中。5.6 break语句、语句、continue语句和语句和goto语句语句 5.7.2 continuecontinue语句语句 与与breakbreak语句退出循环不同的是,语句退出循环不同的是,continuecontinue语语句只结束本次循环,接着进行下一次循环的判句只结束本次循环,接着进行下一次循环的判断,如果满足循环条件,继续循环,否则退出断,如果满足循环条件,继续循环,否则退出循环。循环。5.7.3 gotogoto语句语句 gotogoto语句为无条件转向语句,形式为:语句为无条件转向语句,形式为:gotogoto 语句标号语
24、句标号语句标号用标识符表示,命名规则同变量名。语句标号用标识符表示,命名规则同变量名。【例例5.7】阅读下面程序,写出运行结果。阅读下面程序,写出运行结果。5.8 案例:阶乘的计算案例:阶乘的计算【例例5-85-8】计算计算s=1s=12 23 34 48 8。#include#include void main()void main()int i;int i;long s;long s;for(i=1,s=1;i=8;i+)for(i=1,s=1;i=8;i+)s=s s=s*i;i;printf(s=%ldn,s);printf(s=%ldn,s);计算阶乘的方法与求和差不多,但需要注意以
25、下几计算阶乘的方法与求和差不多,但需要注意以下几点:点:求和时累加器求和时累加器s s初始化为初始化为0 0,求阶乘时累乘器初始化,求阶乘时累乘器初始化为为1 1。求和时用求和时用s=s+i,s=s+i,求阶乘时用求阶乘时用s=ss=s*i i。由于阶乘的值很容易放大,所以数据类型定义为由于阶乘的值很容易放大,所以数据类型定义为longlong型,输出的时候用型,输出的时候用%ld%ld。5.9 案例:输出星号组成的图形案例:输出星号组成的图形5.9 案例:输出星号组成的图形案例:输出星号组成的图形 回顾:循环变量的功能回顾:循环变量的功能 控制循环控制循环 作为循环体中算法的引用变量作为循环
26、体中算法的引用变量for(i=0;i100;i+)s=s+i;for(i=1;i=100;i+)s=s+i;for(i=1,j=1;i=100;i+)s=s+j;j=j+1;for(i=0;i100;i+)s=s+i+1;0+1+2+0+1+2+99+991+2+3+1+2+3+100+1001+2+3+1+2+3+100+1001+2+3+1+2+3+100+100for(i=2,j=1;i=200;i=i+2)s=s+j;j=j+1;控控制制控控制制+引引用用5.9 案例:输出星号组成的图形案例:输出星号组成的图形 分析分析for(i=1;i=4;i+)/*控制输出控制输出4行行*/for
27、(j=1;j=i-1;j+)printf();/*输出输出i-1个空格个空格*/for(j=1;j=2*i-1;j+)printf(*);/*输出输出2*i-1个星号个星号*/printf(n);/*输出一行后换行输出一行后换行*/5.9 案例:输出星号组成的图形案例:输出星号组成的图形完整的程序完整的程序#include#include void main()void main()int i,j;int i,j;/*行数从行数从1 1到到5 5*/for(i=1;i=5;i+)for(i=1;i=5;i+)for(j=1;j=i-1;j+)for(j=1;j=i-1;j+)printf(pr
28、intf(););/*代表空格代表空格*/for(j=1;j=i;j+)for(j=1;j=i;j+)printf(printf(*););printf(n);/printf(n);/*每输出一行需要换行每输出一行需要换行 */j循环从循环从1到到i-1,共,共i-1次循环次循环,每次打每次打印印1个空格个空格,共输出共输出i-1个空格个空格j循环从循环从1到到i,共,共i次循环次循环,每次打印每次打印1个星号个星号,共输出共输出i个个星号星号5.10 案例:计算案例:计算100以内的素数之和以内的素数之和【分析分析】从定义来判断,除了从定义来判断,除了1 1和本身之外,没有其他因子,所以和本
29、身之外,没有其他因子,所以程序的任务是依次判断程序的任务是依次判断1 1到到100100之间所有的数是否为素数,之间所有的数是否为素数,如果是,将其累加。最后输出累加的和。如果是,将其累加。最后输出累加的和。需要嵌套的循环,外循环控制产生需要嵌套的循环,外循环控制产生1 1到到100100的数的循环,的数的循环,循环变量的值也正是内循环需要判断的对象;内循环首循环变量的值也正是内循环需要判断的对象;内循环首先判断当前的循环变量的值是否为素数,是则累加。循先判断当前的循环变量的值是否为素数,是则累加。循环结束后输出累加的和。环结束后输出累加的和。5.10 案例:计算案例:计算100以内的素数之和
30、以内的素数之和#include#include void main()void main()int i,j,s=0;int i,j,s=0;for(i=2;i=100;i+)/for(i=2;i=100;i+)/*设置循环产生设置循环产生2 2100100之间的数之间的数 */for(j=2;j=i-1;j+)for(j=2;ji-1)if(ji-1)/*i i是素数,因为是素数,因为2 2 i-1i-1没有没有i i的因子的因子 */s=s+i;s=s+i;printf(%dn,s);printf(%dn,s);以上程序中以上程序中j=i-1j=i-1也可以改成也可以改成j=i/2j=i/2
31、或或j=sqrt(i)j=3n=3)很显然,很显然,FibonacciFibonacci数列依次为:数列依次为:1,1,2,3,5,8,13,21,341,1,2,3,5,8,13,21,345.11 案例:计算案例:计算Fibonacci数列前数列前20项的项的和和#include#include void main()void main()int f1,f2,f;int f1,f2,f;int i;int i;long s;long s;f1=f2=1;f1=f2=1;s=f1+f2;s=f1+f2;for(i=1;i=18;i+)for(i=1;i=18;i+)f=f1+f2;/f=f1
32、+f2;/*得到一个新数得到一个新数*/s=s+f;s=s+f;f1=f2;/f1=f2;/*重置两个数重置两个数*/f2=f;f2=f;printf(%ldn,s);printf(%ldn,s);5.12 循环的阅读和技巧循环的阅读和技巧 不管是什么循环语句,循环的准备循环条件不管是什么循环语句,循环的准备循环条件循环的调整循环体这四个部分通常都存在循环的调整循环体这四个部分通常都存在 5.12 循环的阅读和技巧循环的阅读和技巧 变量跟踪变量跟踪 5.13 案例:日历的打印案例:日历的打印【例例5-115-11】输入输入20122012年的某个月份,打印该月份的日历。年的某个月份,打印该月份
33、的日历。#include#includemain()main()int i;int i;int month;int month;int first=0;int first=0;/*20122012年的年的1 1月月1 1日是星期天日是星期天*/int daysmonth;int daysmonth;/*用来记录该月有多少天用来记录该月有多少天*/printf(Year is 2012,Please input the month:);printf(Year is 2012,Please input the month:);scanf(%d,&month);scanf(%d,&month);5.
34、13 案例:日历的打印案例:日历的打印for(i=1;i=month;i+)for(i=1;i=month;i+)switch(i)switch(i)case 2:daysmonth=29;break;case 2:daysmonth=29;break;case 4:case 4:case 6:case 6:case 9:case 9:case 11:daysmonth=30;break;case 11:daysmonth=30;break;default:daysmonth=31;break;default:daysmonth=31;break;/*其他月份都是其他月份都是3131天天*/i
35、f(imonth)if(imonth)/*及时调整该月的及时调整该月的1 1号对应的星期号对应的星期,0,0表示星期天表示星期天*/first=(first+daysmonth)%7;first=(first+daysmonth)%7;5.13 案例:日历的打印案例:日历的打印printf(Year:2012,Month:%d,First:%dn,month,first);printf(Year:2012,Month:%d,First:%dn,month,first);printf(SU MO TU WE TH FR SAn);printf(SU MO TU WE TH FR SAn);/*每
36、个星期名称占每个星期名称占3 3个字符个字符*/for(i=0;ifirst;i+)for(i=0;ifirst;i+)/*输出输出1 1号前面的空格号前面的空格*/printf();printf();/*每次输出每次输出3 3个空格个空格*/for(i=1;i=daysmonth;i+)for(i=1;i=daysmonth;i+)printf(%3d,i);printf(%3d,i);if(i+first)%7=0)/if(i+first)%7=0)/*输出每行最后一天后补充输出一个换行符输出每行最后一天后补充输出一个换行符*/printf(n);printf(n);printf(n);p
37、rintf(n);l 循环结构是面向过程编程中三种结构中最重要循环结构是面向过程编程中三种结构中最重要的一种结构,学好它是学好这门课程的关键。本的一种结构,学好它是学好这门课程的关键。本章介绍的内容主要包括:章介绍的内容主要包括:l三种循环结构三种循环结构while、do-while和和for循环循环(goto也可以构成循环,通常不用)也可以构成循环,通常不用)l break语句、语句、continue语句和语句和goto语句语句l while循环和循环和do-while循环的条件判断一个在循环的条件判断一个在前,一个在后,为导致循环体执行的次数不同,前,一个在后,为导致循环体执行的次数不同,
38、需要密切注意。需要密切注意。lfor循环为标准的功能很强的循环,通常用于可循环为标准的功能很强的循环,通常用于可控制的循环,对于程序的维护和阅读都是最佳控制的循环,对于程序的维护和阅读都是最佳选择。选择。lbreak语句和语句和continue语句可以改变循环运行语句可以改变循环运行的方向,主要用于特殊情况的处理,但不能控的方向,主要用于特殊情况的处理,但不能控制制if和和goto构成的循环。构成的循环。l循环结构的实质是重复执行一系列语句,这种循环结构的实质是重复执行一系列语句,这种重复性是在循环条件的有效控制之下完成的。重复性是在循环条件的有效控制之下完成的。程序的关键在于如何控制循环的条件,在恰当程序的关键在于如何控制循环的条件,在恰当的时机由的时机由“真真”变变“假假”而退出循环。而退出循环。求求1-2+3-4+5-6+7+99-1001-2+3-4+5-6+7+99-100。输出所有的三位水仙花数。所谓水仙花数是指所有位的数字输出所有的三位水仙花数。所谓水仙花数是指所有位的数字的立方之和等于该数,例如:的立方之和等于该数,例如:153=1153=13 3+5+53 3+3+33 3 编写程序输出下面的图形。编写程序输出下面的图形。1 1232345645678907890