程序的流程控制.pptx
本章内容流程控制概述顺序控制选择控制循环控制无条件转移控制程序设计风格第1页/共57页流程控制概述表达式构成了数据处理的基本单位。当程序中有多个表达式时,就会面临:先计算哪一个表达式根据不同的情况计算不同的表达式一个或几个表达式需要重复计算多次语句实现对程序执行流程的控制,包括:顺序控制:按书写次序执行。选择控制:根据条件选择执行。循环控制:重复执行。第2页/共57页C+语句的分类第3页/共57页顺序控制按书写次序,从左到右、从上到下顺序执行。实现顺序控制的C+语句有:表达式语句复合语句空语句第4页/共57页 表达式语句在C+表达式的后面加上一个分号“;”就可以构成表达式语句,其格式为:;例如:a+b*c;a b?a:b;a+;x=a|b&c;连续的多个表达式语句按它们的书写次序依次执行。第5页/共57页较常使用的表达式语句 赋值自增/自减无返回值的函数调用,等输入/输出例如x=a+b;/赋值x+;/自增f(a);/函数调用cin a;/输入cout b;/输出 第6页/共57页复合语句复合语句是由一对花括号括起来的一条或多条语句,又称为块(block)。语法上,复合语句可看作是一个语句。其格式为:中的语句可以是任何的C+语句,其中包括数据定义和声明语句。复合语句中的语句序列一般按照书写次序执行。复合语句一般作为函数体和结构语句的成分语句。第7页/共57页复合语句举例int a,b;cin a b;int max;if(a=b)/选择语句max=a;else max=b;cout max endl;第8页/共57页空语句 根据程序设计的需要,在程序中的某些地方有时需要加上一些空操作,以方便其它流程控制的实现。空语句的格式为:;空语句不做任何事情,其作用是用于语法上需要一条语句的地方,而该地方又不需做任何事情。空语句常常作为结构语句的子句。第9页/共57页例如:.goto end;/转向下面由语句标号end标识的空语句.end:;/空语句其中,在“end:;”中,end是一个语句标号,“;”是一个空语句。再例如:int i,sum;for(sum=0,i=1;i=100;sum+=i,i+);其中,循环体为一条空语句第10页/共57页选择控制在程序中,常常需要根据不同的情况来从一组语句中选择一个来执行(分支),这是通过选择语句来完成的。选择语句包括:if语句switch语句第11页/共57页 if 语句if语句(又称条件语句)是根据一个条件满足与否来决定是否执行某个语句或从两个语句中选择一个语句执行。if语句有两种格式:if()if()else 其中的、必须是一个语句!(复合语句算一个语句。)第12页/共57页 if语句的含义第一种格式第二种格式第13页/共57页例子:从键盘输入三个整数,计算其中的最大值并将其输出#include using namespace std;int main()int a,b,c,max;cout 请输入三个整数:a b c;if(a b)max=a;elsemax=b;if(c max)max=c;cout 最大者为:max endl;return 0;第14页/共57页if语句的锯齿格式为了提高程序的易读性,在写if语句时,最好采用“锯齿”格式,即把成分语句往后缩进几列。当if语句的成分语句也是if语句时,如果嵌套层次很深,“锯齿”格式将会使得程序正文严重偏向右边,从而带来对程序编辑、查看带来困难。为了减少文本的缩进量,可以把这样的if语句按下面的格式书写:if(.)if(.).else if(.)else if(.).else if(.)else if(.).else if(.)else if(.).elseelse .if(.)if(.).else else if(.)if(.).else else if(.)if(.).else else if(.)if(.).else else .等价于:等价于:第15页/共57页例子:从键盘输入一个三角形的三条边,判断其为何种三角形#include using namespace std;int main()int a,b,c;cin a b c;if(a+b=c|b+c=a|c+a=b)cout 不是三角形;else if(a=b&b=c)cout 等边三角形;else if(a=b|b=c|c=a)cout 等腰三角形;else if(a*a+b*b=c*c|b*b+c*c=a*a|c*c+a*a=b*b)cout 直角三角形(非等腰);elsecout 其它三角形;cout=90)cout=80&score 90)cout=70&score 80)cout=60&score 70)cout 及格;if(score 60)cout 不及格;第17页/共57页if 语句的歧义问题下面的if语句的含义是什么?if()if()else 1.if()if()else 2.if()if()else C+规定:else子句与它前面最近的、没有else子句的if配对。因此,上面的if语句解释为:if()if()else 若要按2来解释,则需要加上花括号(复合语句):if()if()else 第18页/共57页switch 语句程序中有时需要从两个(组)以上的语句中选择一个(组)来执行。C+提供了一条多路选择语句:switch语句(又称开关语句),它能根据某个表达式的值在多组语句中选择一组语句来执行。每一组语句的最后一个语句往往是break语句。第19页/共57页switch语句的格式 switch()case:case:case:default:第20页/共57页例例子、从键盘输入一个星期的某一天(从键盘输入一个星期的某一天(0 0:星期天;:星期天;1 1:星期一;:星期一;.),然后输出其对应的英语单词),然后输出其对应的英语单词#include using namespace std;int main()int day;cin day;switch(day)case 0:cout Sunday;break;case 1:cout Monday;break;case 2:cout Tuesday;break;case 3:cout Wednesday;break;case 4:cout Thursday;break;case 5:cout Friday;break;case 6:cout Saturday;break;default:cout Input error;cout endl;return 0;第21页/共57页switch语句中使用break语句在执行switch语句的某个分支时,需要用break语句结束该分支的执行。在switch语句的一个分支的执行中,如果没有break语句(最后一个分支除外),则该分支执行完后,将继续执行紧接着的下一个分支中的语句序列。在其它一些语言(如:Pascal)的多路选择语句中,一个分支执行完后将自动结束多路选择语句的执行。C+中的switch语句比其它一些语言中的多路选择语句更具有灵活性。当若干个分支具有部分重复功能时,C+的switch语句可以节省代码量。第22页/共57页switch(.).case:Acase:Bcase:Cbreak;.上面的语句中,分支1执行A、B和C;分支2执行B和C;分支3执行C。(假设A、B中没有break语句)第23页/共57页循环控制 如何编程计算n!(n是变量)?n!=n*(n-1)*(n-2)*.*2*1表达式中不允许有“.”上面的问题需要用重复操作控制来解决:对相同的操作重复执行多次,每一次操作的数据有所不同。f=1,对i=2n,重复执行:f=f*i;循环语句为解决重复操作提供了一种途径。循环一般由四个部分组成:循环初始化循环条件循环体下一次循环准备。第24页/共57页C+提供了三种实现重复操作的循环语句:while语句do-while语句for语句第25页/共57页while 语句while语句具有如下的格式:while()第26页/共57页用while语句求n!#include using namespace std;int main()int n;cin n;int i=2,f=1;/循环初始化while(i=n)/循环条件f*=i;i+;/下一次循环准备/循环体cout factorial of n =f endl;return 0;第27页/共57页do-while 语句do-while语句的格式如下:do while();第28页/共57页用do-while语句求n!#include using namespace std;int main()int n;cin n;int i=1,f=1;/循环初始化do/循环体f*=i;i+;/下一次循环的准备 while(i=n);/循环条件cout factorial of n =f endl;return 0;第29页/共57页for 语句forfor语句的格式如下:语句的格式如下:for(for(;)第30页/共57页#include using namespace std;int main()int n,i,f;cin n;for(i=2,f=1 /循环初始化;i=n /循环条件;i+)/下一次循环准备 f*=i;/循环体cout factorial of n =f endl;return 0;用for语句求n!第31页/共57页循环的种类计数控制的循环循环前就知道循环的次数,循环时重复执行循环体直到指定的次数 事件控制的循环循环前不知道循环的次数,循环的终止是由循环体的某次执行导致循环的结束条件得到满足而引起的 第32页/共57页三种循环语句的使用原则 三种循环语句在表达能力上是等价的,在解决某个具体问题时,用其中的一种可能会比其它两种更加自然。一般来说,计数控制的循环一般用for语句;事件控制的循环一般用while或do-while语句,其中,如果循环体至少要执行一次,则用do-while语句。由于for语句能清晰地表示“循环初始化”、“循环条件”以及“下一次循环准备”,因此,一些非计数控制的循环也用for语句实现。第33页/共57页例例 :计算从键盘输入的一系列整数的和,要求首计算从键盘输入的一系列整数的和,要求首先输入整数的个数。(计数控制的循环)先输入整数的个数。(计数控制的循环)#include using namespace std;int main()int n;cout n;cout 请输入 n 个整数:;int sum=0;for(int i=1;i a;sum+=a;cout 输入的 n 个整数的和是:sum endl;return 0;第34页/共57页例:计算从键盘输入的一系列整数的和,要求输例:计算从键盘输入的一系列整数的和,要求输入以入以-1-1结束。结束。(事件控制的循环(事件控制的循环 )#include using namespace std;int main()int a,sum=0;cout a;while(a!=-1)sum+=a;cin a;cout 输入的整数的和是:sum endl;return 0;第35页/共57页例:从键盘接收字符,一直到输入了字符例:从键盘接收字符,一直到输入了字符y(Y)y(Y)或或n(N)n(N)为止。为止。(事件控制的循环(事件控制的循环 )#include#include using namespace std;int main()char ch;docout ch;ch=tolower(ch);while(ch!=y&ch!=n);if(ch=y).else.return 0;第36页/共57页例:求第例:求第n n个费波那契个费波那契(Fibonacci)(Fibonacci)数数/1,1,2,3,5,8,13,.#include using namespace std;int main()int n;cin n;int fib_1=1;/第一个Fibonacci数int fib_2=1;/第二个Fibonacci数for(int i=3;i=n;i+)int temp=fib_1+fib_2;/计算新的Fibonacci数fib_1=fib_2;/记住新的前一个Fibonacci数fib_2=temp;/记住新的Fibonacci数cout 第 n 个费波那契数是:fib_2 endl;return 0;fib_2=fib_1+fib_2;/fib_2=fib_1+fib_2;/计算和记住新的计算和记住新的FibonacciFibonacci数数fib_1=fib_2-fib_1;/fib_1=fib_2-fib_1;/记住前一个记住前一个FibonacciFibonacci数数 第37页/共57页循环优化问题算法的优化:减少循环次数避免在循环中重复计算不变的表达式第38页/共57页#include using namespace std;int main()int n;cout n;/从键盘输入一个正整数for(int i=2;in;i+)/循环:分别判断2、3、.、n-1是否为素数int j=2;while(j i&i%j!=0)/循环:分别判断i是否能被2 i-1整除 j+;if(j=i)/i是素数 cout i ;cout endl;return 0;注意:1、上面的for循环中,偶数没有必要再判断它们是否为素数;2、上面的while循环没有必要到i-1,只需要到:sqrt(i)例:编程求出小于例:编程求出小于n n的所有素数(质数)的所有素数(质数)第39页/共57页#include#include using namespace std;int main()int n;cin n;/从键盘输入一个数if(n 2)return-1;cout 2 ,;/输出第一个素数for(int i=3;in;i+=2)/循环:分别判断3、5、.、是否为素数int j=2;while(j sqrt(i)/i是素数 cout i ,;cout endl;return 0;注意:上面程序中的sqrt(i)被重复计算!第40页/共57页.int j=2,k=sqrt(i);while(j k)/i是素数。.注意:对有些循环优化,编译器能实现!第41页/共57页无条件转移控制 除了有条件的选择语句(if和switch)外,C+还提供了无条件的转移语句:gotobreakcontinuereturn第42页/共57页goto语句goto语句的格式如下:goto;为标识符,其定义格式为:goto的含义是:程序转移到带有的语句第43页/共57页用goto语句求n!#include using namespace std;int main()int n;cin n;int i=1,f=1;loop:f*=i;i+;if(i=n)goto loop;cout factorial of n =f endl;return 0;第44页/共57页在使用goto语句时,应该注意:不能用goto语句从一个函数外部转入该函数的内部(函数体),也不能用goto语句从一个函数的内部转到该函数的外部。允许用goto语句从内层复合语句转到外层复合语句或从外层复合语句转入内层复合语句。goto语句不能掠过带有初始化的变量定义。第45页/共57页void f().goto L1;/Error.while(.)int x=0;L1:.goto L2;/Error.int y=10;L2:.第46页/共57页break语句 break语句的格式:break;break语句的含义有两个:结束switch语句的某个分支的执行退出包含它的最内层循环语句(由于循环可以嵌套)在循环体中只要执行了break语句,就立即跳出(结束)循环,循环体中跟在break语句后面的语句将不再执行,程序继续执行循环之后的语句。在循环体中,break语句一般作为某个if语句的子句,用于实现进一步的循环控制。第47页/共57页用goto语句实现break语句的功能while(.).break;.上述程序等价于:while(.).goto L;.L:.第48页/共57页例如,判断i是否为素数的循环也可写成:j=2;k=sqrt(i);while(j=k)if(i%j=0)break;/退出循环j+;或for(j=2,k=sqrt(i);j=k;j+)if(i%j=0)break;第49页/共57页continue语句 continue语句的格式如下:continue;continue语句只能用在循环语句的循环体中,其含义是:立即结束当前循环,准备进入下一次循环。对于while和do-while语句,continue语句将使控制转到循环条件的判断;对于for语句,continue语句将使控制转到:先计算,然后计算,并根据的计算结果来决定是进入下一次循环还是结束循环。第50页/共57页用空语句和goto语句实现continue语句的功能 while(.).continue;.上述程序等价于:while(.).goto end;.end:;第51页/共57页例:从键盘输入一些非零整数,然后输出其中所有正数的平方根。#include#include using namespace std;int main()int n;double square_root;cout n;n!=0;cinn)if(n 0)continue;/准备进入下一次循环square_root=sqrt(n);cout n 的平方根是:square_root endl;return 0;第52页/共57页程序设计风格 程序设计风格通常是指对程序进行静态分析所能确认的程序特性,它涉及程序的易读性。采用一致/有意义的标识符为程序实体(如:变量、函数等)命名。使用符号常量为程序书写注释采用代码的缩进格式,等除此之外,结构化程序设计就是一种良好程序设计风格的典范。第53页/共57页结构化程序设计 结构化程序设计(Structured Programming,简称SP)是指“按照一组能够提高程序易读性与易维护性的规则进行程序设计的方法”SP不仅要求所编出的程序结构良好,而且还要求程序设计过程也是结构良好的,后者是前者的基础。对程序设计过程而言,“结构良好”是指采用分解和抽象的方法来完成程序设计任务,具体体现为:“自顶向下、逐步精化”的程序设计过程。对程序而言,“结构良好”是指:每个程序单位应具有单入口、单出口的性质。不包含不会停止执行的语句,程序在有限时间内结束。程序中没有无用语句,程序中所有语句都有被执行的机会。第54页/共57页结构化程序设计(续)结构化程序设计通常可用三种基本结构来实现(顺序)(顺序)(选择)(选择)(循环)(循环)n n上面三种结构都具有单入口、单出口的性质。第55页/共57页关于goto语句 goto语句会使得程序的静态结构和动态结构不一致,导致程序难以理解、可靠性下降和不容易维护。有时会导致程序效率的下降。从结构化程序设计的角度讲,goto语句会破坏程序中的每一个结构所具有的单入口/单出口的性质。实际上,goto语句的使用可以分成两类:向下的转移(forward)(可用分支结构实现)往回的转移(backward)(可用循环结构实现)尽量不要使用goto语句。第56页/共57页感谢您的观看!第57页/共57页