《第三章分支和循环.ppt》由会员分享,可在线阅读,更多相关《第三章分支和循环.ppt(107页珍藏版)》请在三一办公上搜索。
1、第三章 分支和循环,分支结构,一、程序结构的分类:(1)顺序:,(2)分支:二选一(if),多选一(switch),(3)循环:while语句,for,do while,(4)子程序:函数 function,主程序,子程序一,子程序二,二、结构化程序设计模块化、自顶向下,逐步求精,if语句,1、作用:通过对给定的条件(表达式)进行判断,决定所要执行的操作。2、语句格式(1)格式一:if(表达式)语句 含义:,例:if(ab)max=a;if(a=0)x=sqrt(a);(2)格式二 if(表达式)语句1 else 语句2 含义:,例:输入两个数a和b,输出其中较大者。main()int a,b
2、,max;scanf(%d%d,例:输入一个实数a,若a 不是负值,输出a 的平方根,否则输出a的平方。#include“math.h”main()float a;if(a=0)printf(“a=%f”,sqrt(a);else printf(“a=%f”,a*a);,例:输入一个三位数,判断它 是否是“水仙花数”。,main()int n,a,b,c,d;scanf(”n=%d”,&n);a=n%10;/个位 c=n/100;/百位 b=n%100/10;/十位 d=a*a*a+c*c*c+b*b*b;if(n=d)printf(”%d是水仙花数”,n);else printf(”%d不是
3、水仙花数”,n);,3、复合语句(1)格式:语句1;语句2;语句3;(2)作用:把多条语句组合成一条语句。(3)注意:后不允许有分号。,例:输入三角形的三条边长。如果构成三角形则输出三角形面积,否则打印出错信息。思路:a+bc 且b+ca且c+ab s=(a+b+c)/2,#include“math.h”main()float a,b,c,s,area;scanf(“%f%f%f”,4、注意,(1)if(ab)max=a;else max=b;各有一个分号(2)复合语句的作用 后不能加;号(3)else子句是不能单独使用,必须与if配对使用。(4)格式一:“做”或者“不做”格式二:“做这件事”
4、或“做那件事”,(五)if 语句的嵌套,1、定义:在if语句中又包含一个或多个if语句。例:if(b1)s1else if(b2)s2 else s3,例:if()if()语句1 else 语句2 内嵌if else if()语句3 else 语句4 内嵌if,规定:else总是与它上面最近的(未曾配对的)if配对。,例:if()if()语句1 else 语句2,用复合语句改变配对if()if()语句1 else 语句2,例:编写一个程序,输入一个x值,按下述函数关系输出y的值。1(x0),main()int x,y;scanf(%d,switch语句,1、一般格式:switch(表达式)ca
5、se 常量表达式1:语句1 case 常量表达式2:语句2 case 常量表达式n:语句n default:语句n+1 其中,default部分可以缺省。,例:switch(n)case 1:x=11;case 2:x=21;default:x=31;当n=1时,x=31;当n=2时,x=31;其它,x=31;,例:,switch(n)case 1:x=11;break;case 2:x=21;break;default:x=31;x的结果值或者等于11,或者等于21,或者等于31。,例:多个case可以共用一组执行语句,如:switch(n)case 1:case 2:case 3:x=31
6、;break;case 4:当n等于1或2或3时,都执行“x=31”这条语句,并跳出switch。,2、注意,(1)switch语句的表达式和常量表达式可以为任何类型(ANSI),一般为整型、字符型或枚举类型。(TC中若switch语句的表达式为实型,系统自动截尾;常量表达式为实型,系统报错)(VC中若switch语句的表达式为实型,系统报错;常量表达式为实型,系统报错)(2)同一个switch语句中的所有case后面的常量表达式的值,都必须互不相同。(3)switch语句中的各个case和default的出现次序不影响执行结果,default可以在case的前面、中间或最后。,3、注意(续)
7、,(4)由于switch语句中的“case常量表达式”部分只起语句标号的作用,而不进行条件判断,因此,在执行完一个case后面的语句后,流程控制自动转到下一个case继续执行,直到遇到switch语句的右花括号或“break”语句为止。(5)尽管case后面的语句多于一个,却不必用花括号括起来。(6)多个case可以共用一组执行语句。,例:设今天是星期三(Wednesday),那么t天以后是星期几?要求输出星期几的英文名称。(switch 实现),main()int t;scanf(“%d”,例:上题用if语句 实现。,main()int t;scanf(“%d”,例:从键盘中输入三个数,找出
8、其中的最大数。,(1)用条件运算符实现。main()int a,b,c,max;printf(Please input a,b,c:);/*此句用于提示用户输入数据*/scanf(%d%d%d,(2)用if语句实现,main()int a,b,c,max;printf(Please input a,b,c:);scanf(%d%d%d,(year%4=0&year%100!=0)|(year%400=0),例:从键盘输入某年的年号和月份,计算这一年的该月共有多少天。说明编写此程序需要考虑闰年的问题,因为二月份的天数与闰年有关。闰年的规定是,若年号能被4整除但不能被100整除,或者能被400整除
9、,则该年为闰年。,main()int year,month,days;printf(“Please input year and month:”);scanf(“%d%d”,例:将a,b,c,d四个整数按从 小到大的顺序排列后输出。,main()int a,b,c,d,temp;printf(Please input a,b,c,d:);scanf(%d,%d,%d,%d,循环控制结构,求解某问题时,往往遇到具有规律性的重复计算,完成这些计算,通常需要反复执行同一程序段。为了描述这种现象,C语言专门提供了三种循环语句:while语句、do-while语句和for语句。,一、while语句,1、
10、一般格式:while(表达式)语句 其中,语句(称为循环体)只能是一条语句,若为多个语句,要用“”将它们括起来,形成复合语句。,2、while语句流程图,例:编程求1到100之间所有整数的和。,main()int n,sum=0;n=1;while(n=100)sum=sum+n;n=n+1;printf(1+2+3+100=%dn,sum);,这是一个典型的计算累加和的示例,循环体中要对100个数进行累加,累加器(变量sum)在进行循环之前必须先“清0”(这里采用定义时赋初值0的办法进行清0的)。先清0,再循环累加,这种“累加模式”,一定要记住。,3、注意,(1)判别表达式中涉及到的变量必须
11、在循环开始前先赋值;(2)循环体中必须有修改判别表达式E的值的语句(如上例中的n=n+1),并最终使判别表达式的值为0(上例中n的超过100时,n=100的值为0),否则循环永不结束,成为“死循环”;(3)循环体中不止一条语句时,要用 复合。(4)while语句的循环体执行次数可以是0到多次。,例:编程求出一批学生的总成绩、人数和平均成绩。,main()float x,sum=0;int n=0;scanf(“%d”,例:从键盘读入若干个字符(以&结束),统计其中有多少个字母,多少个数字?,main()int letter=0,digital=0;char ch;ch=getchar();wh
12、ile(ch!=,二、for语句,1、一般格式:for(表达式1;表达式2;表达式3)语句,2、for的流程图,例:编程求1到100之间所有 整数倒数的和。,main()int n;double sum=0;for(n=1;n=100;n+)sum+=1/n;printf(“1/1+1/2+1/3+1/100=%fn”,sum);,3、注意,(1)E1,E2,E3是任意表达式,它们之间用分号隔开(注意,不是逗号);(2)若循环体中含有多条语句,必须用“”括起来构成复合语句;(3)判别表达式中涉及到的变量必须在循环开始前先赋值;(4)for语句的循环体执行次数可以是0到多次。,4、for与whi
13、le的关系,(1)将for语句“翻译”成while语句为:E1;while(E2)S;/for的循环体 E3;(2)while语句也可以翻译成for语句,即 while(E)S;相当于 for(;E;)S;,5、for的几种“灵活”用法,(1)初始表达式1的灵活用法 a)使用逗号表达式,可以一次设置多项初始条件,例:for(n=1,sum=0;n=100;n+)sum+=1/n;b)如果进入for循环之前,已经设置了初始条件,那么E1即可省略,例:n=1;sum=0;for(;n=100;n+)sum+=1/n;注意尽管E1省略,但E1后面的分号仍不能少。,(2)判别表达式2的灵活用法,a)判
14、别表达式2可以省略,由于循环条件“永远”满足,通常要在循环体中设置结束循环的条件和语句(比如用if加break语句终止循环),否则循环真的永不休止,形成“死循环”。例如:for(n=1,sum=0;n+)if(n100)break;else sum+=1/n;,b)判别表达式2除关系表达式和逻辑表达式,还可以是数值表达式或字符表达式,例如:for(x=10;x;x-);相当于 x=10;while(x);x-;,(3)后置表达式E3的灵活用法,a)E3省略,将其功能放在循环体中。例如:for(n=1,sum=0;n=100;)sum+=1/n+;b)将循环体中的处理语句放在E3中“顺带”执行,
15、例如:for(sum=0,n=1;n=100;sum+=1/n+);/循环体是一条空语句或 for(sum=0,n=1;n=100;sum+=1/n,n+);,(4)三个表达式都省略,极端情况下,形如:for(;)S;相当于 WHILE(1)S;,例如:for(;(c=getchar()=;);“=”后面是一个空格字符,循环体是空语句。该语句的功能是“过滤空格”,即反复读字符赋给变量c,直到读一个非空格字符为止。,例:从键盘键入“Q”或“q”表示退出,否则“I”(插入)“D”(删除)“S”(查找)的主控制程序。,for(;)ch=getchar();switch(ch)case Q:case
16、q:exit(0);case i:case I:insert();break;case D:case d:delete();break;case s:case S:search();break;,例:计算,n=1 x=1;sum=sum+1/x;n=2 x=1*2;n=3 x=1*2*3;n=100 x=1*2*3*100;迭代公式:x=x*n;,#include“stdio.h”main()int n;double x,sum=0;x=1;for(n=1;n=100;n+)x=x*n;sum+=1/x;/循环累加 printf(“sum=%fn”,sum);,三、do-while语句,1、一
17、般格式:do 语句 while(表达式);,例:用do-while语句求1到100之间 所有整数的和。main()int n,sum=0;n=1;do sum=sum+n;n=n+1;while(n=100);printf(1+2+3+100=%dn,sum);,2、do-while语句与while语句比较,相同点:a)B成立时,才执行循环体b)循环次数未知(条件循环)和已知(计数循环)c)循环体中一定要有改B的语句,并最终使其变为0,退出循环。,不同点:,a)do-while先执行循环体,后判断终止条件;而while是先判断终止条件,后执行循环体。b)在进入while语句之前,判别表达式的初
18、值必须确定;do-while语句中B的值可以不确定(适用不易给B赋初值的场合)。c)while的循环体执行0多次;do-while的循环体至少执行一次。,例:输入若干个字符(以“&”结束),统计其中有多少个字母,多少个数字。,算法设计:设置两个“计数器”,letters用于统计字母个数,digits用于统计数字个数,初值均为0。循环地读字符。(1)若读入的字符是字母,则letters 加一;若是数字,则digits 加一;不是字母和数字,则什么也不做。(2)若读入的是结束符“&”时,则退出循环。,#include stdio.h#include ctype.h/isdigit和isalpha的
19、头文件void main()int letters=0,digits=0;char ch;do ch=getchar();/读字符 if(isdigit(ch)digits+;/判断是否是数字 else if(isalpha(ch)letters+;/判断是否是字母 while(ch!=,/用while语句实现的程序#include ctype.h/isdigit和isalpha的头文件main()int letters=0,digits=0;char ch;ch=getchar();/读第一个字符 while(ch!=,多重循环,(1)概念:若循环语句A的循环体中出现另一个循环语句B,循环中
20、套着循环(即循环嵌套),则A和B构成双重循环,称A是外层循环(外循环),称B是内层循环(内循环)。如果B的循环体内又嵌套一个内层循环语句C,于是A,B,C构成三重循环。循环可以嵌套多层(多重循环)。,例:编程产生“九九乘法表”。希望输出成以下表格形式。,编程思想:行*列,程序设计如下:#include stdio.hvoid main()int i,j;for(i=1;i=9;+i)for(j=1;j=9;+j)printf(%2d*%d=%2d,i,j,i*j);printf(n);,例:编程产生“九九乘法表”。希望输出成以下表格形式。,程序如下:#include stdio.hvoid m
21、ain()int i,j;for(i=1;i=9;+i)for(j=1;j=i;+j)printf(%2d*%d=%2d,i,j,i*j);printf(n);,该程序打印的“九九乘法表”是什么样?,#include stdio.hvoid main()int i,j;printf(|);for(i=1;i=9;i+)printf(%4d,i);printf(n);printf(-|-);for(i=3;i=11;i+)printf(-);printf(n);for(i=1;i=9;i+)printf(%4d|,i);for(j=1;j=9;j+)printf(%4d,i*j);printf(
22、n);,运行结果:,|1 2 3 4 5 6 7 8 9-|-1|1 2 3 4 5 6 7 8 9 2|2 4 6 8 10 12 14 16 18 3|3 6 9 12 15 18 21 24 27 4|4 8 12 16 20 24 28 32 36 5|5 10 15 20 25 30 35 40 45 6|6 12 18 24 30 36 42 48 54 7|7 14 21 28 35 42 49 56 63 8|8 16 24 32 40 48 56 64 72 9|9 18 27 36 45 54 63 72 81,例:编程产生如图所示的n级三角星形宝塔图案。,#include
23、 stdio.hvoid main()int i,j,n;printf(n=);scanf(%d,/*输出一行星号之后,换行*/,break语句和continue语句,1break语句 从switch语句中跳出来,执行 switch语句下面的一条语句。用于跳出循环体,终止本循环的执行,即强制性地结束本循环。,例如:下面的程序段:for(;)scanf(“%c”,else/*此处的“else”可以省略*/,例:break语句用法示例。#include main()int i,j;for(i=1;i=4;i+)for(j=1;j=4;j+)if(i=j)break;else printf(i=%d
24、,j=%d,%4dn,i,j,i*j);printf(The endn);,执行结果:i=2,j=1,2i=3,j=1,3i=3,j=2,6i=4,j=1,4i=4,j=2,8i=4,j=3,12 The end,注意:,(1)break语句只能用于循环语句或switch语句,不能用于其它语句。(2)不能指望用一条break一步跳出两层(或多层)循环。在多重循环结构中,内层循环体中的break语句,只是强制终止内层循环的本次执行,外层循环仍要继续执行。,2continue语句,(1)作用:提前结束循环中的某一轮的执行,使进入该循环的下一轮继续执行。(2)控制流程:,continue语句通常与i
25、f语句联合使用,以便在某种情况下,提前结束循环的本次执行。,例:求1到100之间所有非4的整倍数的整数之和。main()int i,sum=0;for(i=1;i=100;i+)if(i%4=0)continue;/*跳过4的整倍数*/sum=sum+i;printf(“sum=%dn”,sum);,上例只是使用continue语句的示意性程序。可以改写成:for(i=1;i=100;i+)if(i%4)sum+=i;/*跳过4的整倍数*/一般情况下,总可以适当地选用if条件跳过循环的某次执行,而不必使用continue语句,这也是continue语句不常用的原因。,例:continue语句用
26、法示例。#include main()int i,j;for(i=1;i=4;i+)for(j=1;j=4;j+)if(i=j)continue;else printf(i=%d,j=%d,%4dn,i,j,i*j);printf(The endn);,执行结果:i=1,j=2,2i=1,j=3,3i=1,j=4,4i=2,j=1,2i=2,j=3,6i=2,j=4,8i=3,j=1,3i=3,j=2,6i=3,j=4,12i=4,j=1,4i=4,j=2,8i=4,j=3,12 The end,循环语句用法示例,例:依次输出26个大写英文字母和它对应的大、小写字母的ASCII码值,每4个字母
27、占一行。小写字母与大写字母的差值:97-65=32 ch(小)=ch(大)+32或 ch(小)=ch(大)+a-A,main()char letter;int aline=0,i=0;for(i=0;i4;i+)printf(大写|值 小写|值);printf(n);for(i=0;i73;i+)putchar(-);printf(n);for(letter=A;letter=Z;letter+)printf(%4c|%3d%4c|%3d,letter,letter,letter+32,letter+32);if(!(+aline%4)printf(|n);printf(n);,例:宰相达依尔
28、发明了国际象棋,以后每格比前一格加倍,放满64格为止。,分析:p为每格麦粒数,初值为p=1下一格为前一格的p=2*p p=1;for(sum=0,i=1;i=64;i+)sum=sum+p;p=2*p;,例:输出1999中能被3整除,而且至少有一位数字是5的所有整数。算法设计:把1999中的任一个数n都“看成”三位数,将n的百位数,十位数,和个位数拆开,分别放在变量a,b,c中,再按题意判断要不要输出n的值,,#include stdio.h void main()int n,a,b,c;for(n=1;n1000;n+)c=n%10;b=(n/10)%10;a=n/100;if(n%3=0)
29、,例:判断一个正整数是否同时含有偶、奇数字。,main()int i,j,n,f1=0,f2=0;scanf(%d,例:斐波那契问题。假设小兔子出生一个月后就成为“成年”兔,并具有繁殖能力。假定每对成年兔每个月生一对小兔子,新生的小兔子一个月后又可以每个月生一对小兔子。如果兔子都不死,现在有一对幼兔,问多少个月后,兔子数目超过100对?这时共有多少对兔子?,#include stdio.hvoid main()int f1=1,f2=1,f3,i=2;do f3=f1+f2;f1=f2;f2=f3;i+;while(f3100);printf(%d%dn,i,f3);,例:计算多项式 p(x)
30、=anx n+an-1xn1+.+a1x+a0在x=b点的值。解题算法设计:计算多项式的值有一种非常好的迭代法Hanoi算法,或秦九韶算法。例如:p(x)=12.3x 367x 2+2.19 x+0.45=(12.3x67)x+2.19)x+0.45,开始时 p=12.3循环一次后 p=p*x+(67)=12.3x67循环二次后 p=p*x+2.19=(12.3x67)x+2.19=12.3x 267x+2.19循环三次后 p=p*x+0.45=(12.3x267x+2.19)x+0.45=12.3x 367x 2+2.19x+0.45推广到n次多项式,那么上述多项式p(x)可改写:p(x)=
31、(.(a nx+an1)x+a n2)x+.+a 1)x+a 0这个算法好在计算量少,精确度高。,main()int i,n;float x,a,y;/定义为float,保证scanf正确读入数据 double p;/保存运算结果,提高精度 printf(请输入多项式的次数n和自变量x的值:);scanf(%d%f,例:求两个正整数a、b的最大公约数gcd(a,b)。,方法:欧几里德“辗转相除”算法。具体方法是:若a是b的倍数(a%b=0),那么 gcd(a,b)=b(这是显然的);否则,反复利用下面原理:gcd(a,b)=gcd(b,r)(即r=a%b)即a和b的最大公约数等于b和r的最大公
32、约数。直到余数为0止。,例如,求gcd(124,46)的步骤如下:gcd(124,46)=gcd(46,32)124%46=32=gcd(32,14)46%32=14=gcd(14,4)32%14=4=gcd(4,2)14%4=2=2 4%2=0,又如:gcd(123,219)=gcd(219,123)123%219=123=gcd(123,96)219%123=96=gcd(96,27)123%96=27=gcd(27,15)96%27=15=gcd(15,12)27%15=12=gcd(12,3)15%12=3=3 12%3=0,#include stdio.hvoid main()int
33、 a,b,r;scanf(%d%d,例:判断一个正整数是否是奇偶数字相邻的。,/pred代表相邻两位的前一位(值1为偶数,0为奇数)/succ代表相邻两位的后一位(值1为偶数,0为奇数),main()int a,b,pred,succ;scanf(%d,例:求n是否是素数。,思路一:对任一数n,用2n-1除,main()int flag,n,i;printf(Input data n=);scanf(%d,求素数的方法二:对任一数n,用2 除,例:求100至200以内的所有素数。,for(i=100;i=200;i+)判i是否是素数;,main()int flag,n,j=0,i;for(n=100;n=200;n+)flag=1;/*假定是素数*/for(i=2;i=n-1;i+)if(n%i=0)flag=0;break;if(flag)printf(%d,n);j+;if(j%10=0)printf(“n”);/换行,