第4章程序的控制结构2019/12/182内容提要算法的描述方法基本控制结构基本控制语句常用算法,如累加、累乘、统计、递推、迭代、穷举等程序的基本版式结构化程序设计的基本思想2019/12/183算法的概念数据结构+算法=程序算法:为解决一个具体问题而采取的确定的有限的操作步骤,这里仅指计算机能执行的算法算法特性:–有穷性–确定性–有效性–没有输入或有多个输入–有一个或多个输出2019/12/184算法的表示方法自然语言表示传统的流程图表示N-S结构化流程图表示伪代码表示2019/12/185S1:使p=1S2:使i=2S3:使p与i相乘,乘积仍放在变量p中,可表示为:p*ipS4:使i的值加1,即i+1iS5:如果i不大于5,返回重新执行S3;否则,算法结束最后得到p的值就是5!的值例:求1×2×3×4×51、用自然语言表示算法2019/12/186用自然语言表示算法的优缺点优点:通俗易懂缺点:文字冗长,容易出现歧义性描述包含分支和循环的算法,不很方便2019/12/1872、用传统的流程图表示算法起止框输入输出框处理框判断框流程线连接点注释框x≧0Y……N……一个入口两个出口2019/12/1882.4.2用流程图表示算法流程图是用一些图框来表示各种操作用图形表示算法,直观形象,易于理解起止框输入输出框处理框判断框流程线连接点注释框③①②①③②③位置不够防止交叉2019/12/189例:用流程图表示1×2×3×4×51ti5开始2it*iti+1i结束NY2019/12/18103、用N-S结构化流程图表示算法传统流程图的弊端传统的流程图用流程线指出各框的执行顺序,对流程线的使用没有严格限制使用者可以毫不受限制地使流程随意地转来转去,使人难以理解算法的逻辑2019/12/1811构成程序的三种基本结构顺序结构选择结构循环结构已经证明,任何程序均可只用这三种结构综合描述只用这三种结构编制的程序,叫结构化程序程序必须符合结构化规则2019/12/1812结构化程序设计的核心思想采用顺序、选择和循环三种基本结构作为程序设计的基本单元–只有一个入口;–只有一个出口;–无死语句,即不存在永远都执行不到的语句;–无死循环,即不存在永远都执行不完的循环。采用“自顶向下、逐步求精”和模块化的方法进行结构化程序设计2019/12/1813BA传统流程图顺序结构2019/12/1814BN如果成绩60那么通知补考否则告知你考试成绩AY条件P分支结构(选择结构)2019/12/1815条件PA当型循环直到型循环真假假条件PA假真循环结构2019/12/1816用N-S流程图表示算法N-S流程图用以下的流程图符号:ABABYNpA当p1成立A直到p2为假顺序结构选择结构循环结构(当型)循环结构(直到型)2019/12/1817例:将5!算法用N-S图表示。直到i51t输出t2it*iti+1i2019/12/18184、用伪代码表示算法伪代码是用介于自然语言和计算机语言之间的文字和符号来描述算法用伪代码写算法并无固定的、严格的语法规则,可以用英文,也可以中英文混用2019/12/1819例:用伪代码表示5!的算法。begin(算法开始)1t2iwhilei≤5{t*iti+1i}printtend(算法结束)2019/12/1820顺序结构程序设计举例例1:将用华氏法表示的温度(F)转换为以摄氏法表示的温度(C)。算法:输入f的值输出c的值)32(95fc2019/12/1821#includestdio.hmain(){floatf,c;scanf(“%f”,&f);c=(5.0/9)*(f-32);printf(f=%f\nc=%f\n,f,c);}//定义f和c为单精度浮点型变量//输入f的值//计算c的值//输出f和c的值2019/12/1822例2:计算存款利息。有1000元,想存一年。有三种方法可选:(1)活期,年利率为r1(2)一年期定期,年利率为r2(3)存两次半年定期,年利率为r3请分别计算出一年后按三种方法所得到的本息和。2019/12/1823解题思路:确定计算本息和的公式。从数学知识可知:若存款额为p0,则:活期存款一年后本息和为:p1=p0(1+r1)一年期定期存款,一年后本息和为:p2=p0(1+r2)两次半年定期存款,一年后本息和为:)23+)(123+p0(1=p3rr2019/12/1824算法:输入p0,r1,r2,r3的值计算p1=p0(1+r1)计算p2=p0(1+r2)计算p3=p0(1+)(1+)输出p1,p2,p323r23r2019/12/1825#includestdio.hmain(){floatp0=1000,r1=0.0036,r2=0.0225,r3=0.0198;floatp1,p2,p3;p1=p0*(1+r1);p2=p0*(1+r2);p3=p0*(1+r3/2)*(1+r3/2);printf(”%f\n%f\n%f\n”,p1,p2,p3);}定义变量同时赋予初值2019/12/1826选择结构程序设计在现实生活中,需要进行判断和选择的情况是很多的–如果你在家,我去拜访你–如果考试不及格,要补考–如果遇到红灯,要停车等待–周末我们去郊游–70岁以上的老年人,入公园免票2019/12/1827C语言有两种选择语句:(1)if语句,实现两个分支的选择结构(2)switch语句,实现多分支的选择结构2019/12/1828If语句if(表达式)语句1;例3:有一函数:编一程序,输入一个x值,要求输出相应的y值。)0(1)0(0)0(1xxxy2019/12/1829#includestdio.hmain(){scanf(%d,&x);if(x0)y=-1;if(x==0)y=0;if(x0)y=1;printf(x=%d,y=%d\n,x,y);}2019/12/1830解题思路:–只需要做一次比较,然后进行一次交换即可–用if语句实现条件判断–关键是怎样实现两个变量值的互换★●AB互换前●★AB互换后例4:输入两个实数,按数值由小到大的顺序输出这两个数。2019/12/1831★●ABC★2019/12/1832★●ABC★●2019/12/1833ABC★●★●2019/12/1834#includestdio.hmain(){floata,b,t;scanf(%f,%f,&a,&b);if(ab){t=a;a=b;b=t;}printf(%5.2f,%5.2f\n,a,b);}将a和b的值互换如果ab2019/12/1835练习:输入3个数a,b,c,要求按由小到大的顺序输出。2019/12/1836解题思路:可以先用伪代码写出算法:–ifab,a和b对换(a是a、b中的小者)–ifac,a和c对换(a是三者中最小者)–ifbc,b和c对换(b是三者中次小者)–顺序输出a,b,c2019/12/1837#includestdio.hmain(){floata,b,c,t;scanf(%f,%f,%f,&a,&b,&c);if(ab){t=a;a=b;b=t;}if(ac){t=a;a=c;c=t;}if(bc){t=b;b=c;c=t;}printf(%5.2f,%5.2f,%5.2f\n,a,b,c);}2019/12/1838if-else语句if(表达式)语句1;else语句2;语句3–表达式值非0时,执行语句1,然后语句3;表达式值为0时,执行语句2,然后语句32019/12/1839#includestdio.hmain(){scanf(%f,&x);if(x60)printf(“需要补考!”);elseprintf(“成绩为:%f”,x);}2019/12/1840else-if语句if的一种扩展形式if(表达式)语句1;elseif(表达式)语句2;elseif(表达式)语句3;…………else语句4;语句5;else部分可以没有2019/12/1841)0(1)0(0)0(1xxxy#includestdio.hmain(){scanf(%d,&x);if(x0)y=-1;elseif(x==0)y=0;elsey=1;printf(x=%d,y=%d\n,x,y);}2019/12/1842例5:教材P78猜数游戏用到的库函数随机函数rand()#includestdlib.hRAND_MAX在stdlib.h中定义,不大于双字节整数的最大值32767产生[0,RAND_MAX)之间的随机数magic=rand();产生[0,b)之间的随机数magic=rand()%b;产生[a,a+b)之间的随机数magic=rand()%b+a;2019/12/184302cbxax例6:求一元二次方程的解。(教材P75)判定一个实数a是否为0fabs(a)=1e-6判定两个实数a、b是否为相等fabs(a-b)=1e-62019/12/1844Switch语句switch语句用来实现多分支选择结构–学生成绩分类85分以上为’A’等70~84分为’B’等60~69分为’C’等……–人口统计分类按年龄分为老、中、青、少、儿童2019/12/1845Switch语句switch(表达式){case常数1:语句序列1;case常数2:语句序列2;…………default:语句序列3;}default可以没有,但最好不省略不要忘记break2019/12/1846例7:要求按照考试成绩的等级输出百分制分数段,A等为85分以上,B等为70~84分,C等为60~69分,D等为60分以下。成绩的等级由键盘输入。解题思路:–判断出这是一个多分支选择问题–根据百分制分数将学生成绩分为4个等级–如果用if语句,至少要用3层嵌套的if,进行3次检查判断–用switch语句进行一次检查即可得到结果2019/12/1847#includestdio.hmain(){chargrade;scanf(%c,&grade);printf(Yourscore:);switch(grade){case'A':printf(85~100\n);break;case'B':printf(70~84\n);break;case'C':printf(60~69\n);break;case'D':printf(60\n);break;default:printf(enterdataerror!\n);}}值为A2019/12/1848例8:运输公司对用户计算运输费用。路程(skm)越远,每吨·千米运费越低。标准如下:s250没有折扣250≤s5002%折扣500≤s10005%折扣1000≤s20008%折扣2000≤s300010%折扣3000≤s15%折扣2019/12/1849解题思路:–设每吨每千米货物的基本运费为p,货物重为w,距离为s,折扣为d–总运费f的计算公式为f=p×w×s×(1-d)2019/12/1850折扣的变化规律:–折扣的“变化点”都是250的倍数–可加一变量c,c的值为s/250,代表250的倍数–当c1时,表示s250,无折扣–1≤c2时,表示250≤s500,折扣d=2%–2≤c4时,d=5%;4≤c8时,d=8%;8≤c12时,d=10%;c≥12时,d=15%2019/12/1851#includestdio.hmain(){intc,s;floatp,w,d,f;printf(pleaseenterprice,weight,discount:);scanf(%f,%f,%d,&p,&w,&s);if(s=3000)c=12;elsec=s/250;输