第程序的流程设计PPT课件_第1页
第程序的流程设计PPT课件_第2页
第程序的流程设计PPT课件_第3页
第程序的流程设计PPT课件_第4页
第程序的流程设计PPT课件_第5页
已阅读5页,还剩145页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、他认为,“程序就是在数据的某些特定表示方式和结构的基础上对抽象算法的具体表述”。Wirth企图用这个公式来对程序进行一个概括性的定义。从今天的观点来看,它只能是对过程化程序的一个抽象定义,对面向对象的程序而言则不尽然。不过对学习C语言这样的面向过程的程序设计语言而言,是完全适用的。也就是说,面向过程的程序有两大要素:算法和数据结构。数据结构是程序所处理的对象数据的表示和组织形式。数据类型就是其重要内容。关于数据结构的概念在学习完第5、6、7章后,才会有较深的体验。第1页/共150页算法的组成要素与基本性质 算法含有两大要素: (1)操作算法是由一系列操作组成的。每个操作的确定不仅取决于问题的需

2、求,还取决于它们取自哪个操作集,它与使用的工具系统有关。如算盘上的操作集由进、退、上、下、去等组成;做菜的操作集包括坐锅、加油、炒、煮、炸、蒸、焖、加水、加调料等;驾驶汽车的操作包括踩离合器、踩油门、开电门、换档、左转、右转、开灯、关灯等。计算机算法要由计算机实现,组成它的操作集是计算机所能进行的操作。而且这些操作的描述与程序设计语言的级别有关。在高级语言中所描述的操作主要包括:算术运算(+、-、*、/)、逻辑运算(“与”、“或”、“非”等)、关系运算(=、=、=、!=等)、函数运算、位运算、I/O操作等。计算机算法是由这些操作所组成的。第2页/共150页 (2)控制结构算法的另一要素是其控制

3、结构。每一个算法都要由一系列的操作组成。同一操作序列,按不同的顺序执行,就会得出不同的结果。控制结构即如何控制组成算法的各操作的执行顺序。结构化程序设计方法要求:一个程序只能由三种基本控制结构(或由它们派生出来的结构)组成。1966年Bohm和Jacopini证明,由这三种基本结构可以组成任何结构的算法,解决任何问题。这三种基本结构是:第3页/共150页(1) 顺序结构。顺序结构中的语句是按书写的顺序执行的,即语句的执行顺序与书写顺序一致。这种结构像一串珍珠项链一样清晰可读。这是一种理想的结构,但是光有这样的结构不可能处理复杂的问题。 一般说来,程序中的语句是顺序执行的。但是,顺序执行的程序的

4、功能是非常有限的。为了提高程序的灵活性,必须采用不同的程序流程结构。 (2) 选择结构。最基本的选择结构是当程序执行到某一语句时,要进行一下判断,从两种路径中选择一条。例如,要在两个数a,b中取一个最大的数就要经过比较判断,决定是将a还是将b输出。选择结构给程序注入最简单的智能。 由二分支选择,可以派生出多分支选择结构。(3) 循环结构(或称重复结构)。这种结构是将一条或多条语句重复地执行若干遍。就像驴子拉磨一样,虽然每一圈的操作都比较简单,而且相同,但磨上若干圈后就能把麦子磨成面粉。众所周知,电子计算机的一大优势是速度快。当能把一个复杂问题用循环结构来实现时,就能充分地发挥计算机的高速度的优

5、势。第4页/共150页2. 算法的基本性质 简单地说,算法就是进行操作的方法和操作步骤。例如,菜谱实际上是做菜肴的算法,乐谱实际上是演奏的算法,计算机程序是用某种程序设计语言描述的解题算法。通常认为算法有如下一些性质:(1)有效性 有效性指算法所规定的操作都应当是能够有效执行的。例如,对于操作汽车的算法,有效的操作就是加速、刹车、换档、转动方向盘、鸣笛等,要让汽车执行“跳起”就是无效的操作。同样,一个计算机算法必须是计算机能够执行的。(2)确定性 确定性具有两重意义:一是所描述的操作应当具有明确的意义,不应当有歧义性。例如,不能发出这样的操作指令:“执行一个算术操作”。因为它既没有指出算术操作

6、的类型,也没有指出操作数。确定性的另一重意义: 操作作序列只有一个初始动作,序列中每一动作仅有一个后继动作; 序列终止表示问题得到解答或问题没有解答,不能没有任何结论。(3)有穷性 有穷性指算法所规定的操作序列必须在允许的时间内结束。例如,一个计算机算法要执行100年以上,就失去有穷性。第5页/共150页算法描述工具 为了描述算法,人们创建了许多算法描述工具。下面介绍程序设计中常用的几种方法,并主要介绍如何用这些工具描述算法的三种基本结构。1. 流程图 流程图是一种流传很广的算法描述工具。这种工具的特点是用一些图框表示各种类型的操作,用线表示这些操作的执行顺序。我国国家标准GB 152689中

7、推荐的一套流程图标准化符号,它与国际标准化组织ISO(International Standard Organization)提出的ISO流程图符号是一致的。图3.2为其中常用的一些符号。第6页/共150页过程判断数据预定义过程起止流程线连接注释图图3.2 常用的流程图标准化符号常用的流程图标准化符号 第7页/共150页2. 算法的基本性质 简单地说,算法就是进行操作的方法和操作步骤。例如,菜谱实际上是做菜肴的算法,乐谱实际上是演奏的算法,计算机程序是用某种程序设计语言描述的解题算法。通常认为算法有如下一些性质:(1)有效性 有效性指算法所规定的操作都应当是能够有效执行的。例如,对于操作汽车的

8、算法,有效的操作就是加速、刹车、换档、转动方向盘、鸣笛等,要让汽车执行“跳起”就是无效的操作。同样,一个计算机算法必须是计算机能够执行的。(2)确定性 确定性具有两重意义:一是所描述的操作应当具有明确的意义,不应当有歧义性。例如,不能发出这样的操作指令:“执行一个算术操作”。因为它既没有指出算术操作的类型,也没有指出操作数。确定性的另一重意义: 操作作序列只有一个初始动作,序列中每一动作仅有一个后继动作; 序列终止表示问题得到解答或问题没有解答,不能没有任何结论。(3)有穷性 有穷性指算法所规定的操作序列必须在允许的时间内结束。例如,一个计算机算法要执行100年以上,就失去有穷性。第8页/共1

9、50页 下面对其中一些主要符号作简要说明。平行四边形表示数据,其中可注明数据名称、来源、用途或其它的文字说明。处理矩形表示各种处理功能。例如,执行一个或一组特定的操作,从而使信息的值、信息形式或所在位置发生变化。矩形内可注明处理名称或其简要功能。预定义过程带有双竖边线的矩形,表示已命名的处理。该处理为在另外地方已得到详细说明的一个操作或一组操作。例如库函数或其它已定义的函数等。矩形内可注明特定处理名称或其简要功能。判断菱形表示判断。菱形内可注明判断的条件。它只有一个入口,但可以有若干个可供选择的出口,在对定义的判断条件求值后,有一个且仅有一个出口被选择。求值结果可在表示出口路径的流线附近写出。

10、流线直线表示执行的流程。当流程自上向下或由左向右时,流程线可不带箭头,其它情况应加箭头表示流程。端点。扁圆形表示转向外部环境或从外部环境转入的端点符。例如,程序流程的起、始点。注解。注解是程序的编写者向阅读者提供的说明。注解符由纵边线构成,它用虚线连接到被注解的符号或符号组上。 第9页/共150页 图3.3(a)、(b)、(c)中的虚线框,分别为用流程图表示的三种基本流程控制结构。这三种基本结构有一个明显的特征:单入口和单出口。从整体上看都相当于一个处理框。用它们所组成的程序来龙去脉十分清晰。S1S2S3PS1S2真假PS2假真(a)顺序结构)顺序结构 (b)选择结构)选择结构 (c)重复结构

11、)重复结构 图图3.3 用流程图描述的三种流程基本结构用流程图描述的三种流程基本结构 第10页/共150页例3.1 用流程图描述从三个数中取最大数的算法。从三个数中取最大数的算法思路是:假定这三个数是a,b,c,则首先可以比较a,b两数,从中选大者;然后再用这个大数与数c比较,从中取大者。这时得到的大数,就是三个数中的最大数。这个算法用流程图描述如图3.4(a)所示。通常,求解一个问题的算法不是唯一的。例如图3.4(b)也是一个三数中取大的算法。它的基本思路是,先设max=0,然后依次输入i个数,每输入一个数,与max比较一次,把大的放入max中。当输完i个数时,max中存放的就是这i个数中的

12、最大数。这里,i是一个计数器,用于统计输入数的个数,所以每输入一个数,要执行一次自增操作。这个算法与图3.4(a)所示算法的不同在于: 算法结构不同:图3.4(a)所示算法采用了两个选择结构,而图3.4(b)所示算法采用了一个循环结构和一个选择结构。 算法的灵活性不同:图3.4(b)中的算法可以用来求任意个数中的最大数。第11页/共150页a=b输入a,b,cmax=a真假max=bmax=c真假输出max输出c开始结束i=maxmax=n(a)一个三数中取大的算法)一个三数中取大的算法 (b)另一个三数中取大的算法)另一个三数中取大的算法 图图3.4 三数中取大算法的流程图描述三数中取大算法

13、的流程图描述 第12页/共150页用流程图表示算法灵活、自由、形象、直观,可以表示任何算法。它允许用流线使流程任意转移。但这却是程序设计中的一个隐患,程序中如果允许流程毫无限制地任意转移,就会使程序如同一团乱麻一样难以阅读和维护,如图3.5所示。这种程序叫做BS程序(a Bowl of Spaghetti的缩写,意为“一碗面条”似的)。图图3.5 无限制地使用流线形成无限制地使用流线形成BS流程结构流程结构 结构化程序设计主张限制这种无规律的任意转向,采用三种基本结构作为构成程序的基本单位。这样就必须限制流线的使用。第13页/共150页 2. N-S图描述灵活的流线是程序中隐藏错误的祸根。针对

14、这一弊病,1973年美国学者I. Nassi和B. Shneiderman提出了一种无流线的流程图,称为N-S图。它的三种基本结构如图3.6所示。N-S图的每一种基本结构都是一个矩形框,整个算法可以像堆积木一样堆成。其中,(a)为三个操作组成的顺序结构;(b)为二分支的选择结构;(c)为当型重复结构,即当命题P 为“真”时,就重复执行S。由于N-S图中没有了流线,所以绝对不会出现由于乱用流线造成的BS算法结构。第14页/共150页S1S2S3PS1S2当PS假真(c)当型重复结构)当型重复结构(a)顺序结构)顺序结构 (b)选择结构)选择结构图图3.6 用用N-S图描述三种基本流程结构图描述三

15、种基本流程结构 第15页/共150页 图3.7(a)、(b)给出了用与图3.4(a)、(b)流程图对应的N-S图。注意,空白的处理框表示没有操作。a=bmax=amax=b输入a,b,c假真max=c输出max输出c真假当i=maxmax=n真假输入n初始化:max=0,i=1输出max(a)采用选择结构)采用选择结构 (b)采用当型重复结构)采用当型重复结构 图图3.7 三数中取大算法的三数中取大算法的N-S图描述图描述 第16页/共150页 3. 伪代码伪代码(pseudo code)是用介于自然语言与计算机语言之间的文字符号算法描述的工具。它无固定的、严格的语法规则,通常是借助某种高级语

16、言的控制结构,中间的操作可以用自然语言(如中文或英文),也可以用程序设计语言,或使用自然语言与程序设计语言的混合体。一般专业人员习惯用伪代码进行算法描述。下面是与图3.7相对应的三数中取大算法的伪代码描述。 (1)与图3.7(a)相对应的三数中取大算法的伪代码描述:输入输入a,b,c;if(a=b)max=a;else max=bif(max=c) 输出输出max;else 输出输出c;第17页/共150页(2)与图3.7(b)相对应的三数中取大算法的伪代码描述:初始化:初始化:mac=0,i=1;当(当(i=max) max=n;)输出输出max;(3)与图3.7(c)相对应的三数中取大算法

17、的伪代码描述:初始化:初始化:mac=0,i=1; (输入输入n; i+;if(n=max) max=n;) 直到(直到(i3)输出输出max;第18页/共150页自顶向下,逐步细化的算法设计过程算法设计是一个的智力过程。设计复杂问题的算法更是一个高强度的智力劳动。实践证明,保证算法设计正确的一个方法是要让问题的复杂性能够在人的智力容易控制范围之内。为此人们提出了一种自顶向下、逐步细化的算法设计方法。按照这种方法,解题之初不要一下子就力图触及到问题解法的细节,而应当从问题的全局出发,给出高度概括、抽象的算法,通常是把这些问题的求解分成可以独立求解的若干子问题;接着对每一个子问题,再进行分解;最

18、后对不可再分的子问题分别设计算法,而且设计的过程也是从概括逐步细化。一般说来,上层解决的是“做什么”的过程,逐步细化的过程是解决“怎么做”的过程。在用伪代码描述算法时,随着逐步细化,最终可以用程序设计语言代替算法中的伪代码。等到全部伪代码都用某种程序设计语言描述了,程序设计也就基本完成了。第19页/共150页例3.2 用自顶向下、逐步细化的方法设计三数中取大算法的过程。 这里,仅考虑采用伪代码描述的方法。 (1) 首先,把该问题分析为: s1: 输入三数输入三数a,b,c;s2: 从从a,b,c中找出大数赋给中找出大数赋给max;s3: 输出输出max。这一阶段算法是用汉语描述的,描述了按顺序

19、要完成的三个“做什么”。可以用s1,s2,s3代表第1步、第2步、第3步。s是步(step)的缩写。 (2) 在前一阶段的基础上考虑各个“做什么”的实现途径,把算法细化为:s1: 调用调用scanf()函数;函数;s2: 设计一个函数设计一个函数max3 (a,b,c);s3: 调用调用printf()函数。函数。这一阶段是用混合语言写算法。第20页/共150页(3) 写主函数的条件已经成熟。int main(void) /*三数中取大数三数中取大数*/float a,b,c, max;float max3(float x,float y, float z);printf (Input 3 n

20、umbers a b c:);scanf (%f%f%f, &a,&b,&c);max=max3(a,b,c);printf (The max is: %fn, max);return 0;第21页/共150页(4) 设计max 3()的算法。仍按逐步细化的方法,先给出概要算法。设三个参数为float x, float y, float z。s2.1: 从从x与与y中取大数送中取大数送m中;中;s2.2: 从从m与与z中取大数送中取大数送m中;中;s2.3: 返回返回m给主调函数。给主调函数。进一步细化得 s2.1:if(xy)m=x;elsem=y;s2.2: if(

21、mz)m=m;elsem=z;s2.3: return (m); 第22页/共150页这就很容易用C语言立刻写出函数max3()了:float max 3 (float x, float y, float z)float m;if (xy)m=x;elsem=y;if (mz)m=m;elsem=z;return (m);一次执行结果:Input 3 numbers a b c: 34.7 45.9 678The max is: 678.000000第23页/共150页命题的“真”、“假”与C语言中的逻辑值不论是选择结构,还是循环结构,流程的改变都是由判断决定的。即需要根据判断决定选择,根据判

22、断决定是否循环以及循环的结束。通常,判断是针对命题的“真”、“假”进行的。例如,下面是一些命题: (行驶中)前面的交通信号灯是红色的。 今天下雨。 ab。 abc,即ab 且bc。 ab 或cb。 如果a不能被b整除。这些命题的值都只能是一个逻辑(布尔)值:“真”或“假”。早期的C语言不提供专门的逻辑(布尔)类型,规定用非0值表示“真”,用0值表示“假”。这样,不管任何表达式,只要其值为非0(包括负数),就说明其为“真”;只要其值为0,就说明其为“假”。从而给判断带来很大的灵活性。在C99中,增加了_Bool类型,并增加了头文件,在其中定义了宏bool、true和false,用true存储1,

23、用false存储0。第24页/共150页关系运算与关系表达式 关系表达式和逻辑表达式是C语言中描述命题的两种基本形式。 1. C语言的关系运算符关系运算是指对两个表达式值的大小比较。C语言中提供有如下6个关系运算符: (大于) =(大于或等于) (小于) =(小于或等于) =(等于)!=(不等于)后两个(=和!=)的优先级小于前4个,但它们都低于纯算术类,高于赋值类,并且它们结合方式都是从左向右的。例如: a+bc+d 应理解为 (a+b)(c+d)第25页/共150页 2. 关系运算符的值关系表达式的值只有两个:关系表达式成立,即为“真”(通常为1);关系表达式不成立,即为“假”(0)。例如

24、对于声明: int x=2, y=3,z; 表达式 x=y 的值为0。而表达式 xy 的值为1。那末表达式 z=3-1=x+1=y+2 的值呢?在这个表达式中有赋值、关系、算术三种运算。其中“赋值”的优先级最低,其次为“关系”,“算术”的优先级最高。因此,先进行算术运算得 z=2=3=5 然后计算2=3,其值为0(假),得 z=0=5 再计算0=5,值为1(真),故有z的值为1。第26页/共150页 应当注意:(1)表达式5278在数学上是不允许的,而在C中是允许的。按自左而右的结合求解: 52值为1; 17值为0; 08的值为0。 即整个关系表达式的值为0。(2)由于关系表达式的值是整型数0

25、或1,故也可以将其看成是一种整型表达式。例如,若有: int i=1, j=7,a; a=i+(j%4!=0); 由于j%4的值为3,而3!=0的值为1(真),故a的值为2。但这种表达式的含义不易被理解,初学时不宜多用。第27页/共150页(4)在判定两个浮点数是否相等时,由于存储上的误差,会得出错误的结果。例如: 在数学上显然应该是一个恒等式,但由于1.0/3.0得到的值的有效位数是有限的,并不等于0.3333333333333,因此上面关系表达式的值为0(假),并不为1(真)。所以应避免对两个实数表达式作“相等”或“不相等”的判别。上式可改写为: fabs (1.0/3.0* 3.0-1.

26、0)1e-5 fabs是求绝对值函数。只要1.0/3.0与1.0之间的差小于10-5(或一个其它的很小的数),就认为与1.0相等。(5)要表示x在区间a,b中,在数学中使用表达式axb。但在C语言中使用表达式“a=x=b”会与原来的意义不同。假设a=0;b=0.5。若x=0.3,则执行a=x=b时先求出“a=x”的值得1(真),再计算“1=b”得0(假)。因此,为了判别x是否在a,b范围内,应写成: a=x & x=b “&”是下面将要介绍的逻辑运算符“与”。a=x的值为1(真)且x=b的值亦为1(真),则整个表达式的值为1(真)。第28页/共150页逻辑运算与逻辑表达式1.

27、逻辑运算的基本概念 C语言有三个逻辑运算符,它们是: & (逻辑与) |(逻辑或) !(逻辑非) 为了说明“与”、“或”、“非”的概念,先看一下图3.8。 当图3.8(a)中的开关a和b都合上时,灯泡c才亮。这就是“与”的概念,即只有a和b均为真时,c才为“真”(1)。在C语言中,“与”运算用“&”运算符表示。下面是逻辑“与”的简单应用:if (a & b)c=1;elsec=0; 图3.8(b)中c灯亮的条件是a“或”b之一合上(二者都合上也行),即至少a或b之一为“真”(1)。在C语言中,“或”运算用“|”运算符表示。下面是逻辑“或”的简单应用:if (a|b)c=

28、1;else c=0;第29页/共150页ABBAA(a)逻辑)逻辑“与与” (b)逻辑)逻辑“或或” (c)逻辑)逻辑“非非” 图图3.8 三个基本逻辑运算三个基本逻辑运算 第30页/共150页 从图3.8(c)中可以看出,当a合上时c灯不亮,只有a不合上灯才亮,即a“非”,c才为“真”(1)。在C语言中,“非”运算用“!”运算符表示。下面是逻辑“非”的简单应用: if (!a)c=1;elsec=0; &和|是二元运算符,结合方向为自左至右;!为一元运算符, 结合方向为自右至左。&和|的优先级低于关系运算符,而!的优先级高于关系运算符。例如表达式!31,应先计算!3,得0;

29、再计算01,得0。第31页/共150页 2. 常用的逻辑运算规律 逻辑运算中有很多有趣的规律。例如:(1) 在一个&表达式中,若&的一端为0,则不必再计算另一端,该表达式的值肯定为0(在C语言中由于&是从左向右结合的,所以只考虑左端,即当&号的左端为0时,不再计算其右端),可以把它记为: 0 & a=0(2) 在一个|表达式中,若|的一端为1,则不必计算另一端,该|表达式的值必为1。现把它记为: 1|a=1 诸如此类关于表达式的值的规律有如下一些: 0|a=a1&a=a1|a=10&a=0 a|!a=1 0&!a=0 以及 a|a

30、=aa&a=a!(a|b)=!a&!b!(a&b)=!a|!b !(!a)=a记住这些规律,能使复杂的逻辑运算简化、清晰。第32页/共150页 表3.1为基本逻辑运算的真值表:两个操作数为不同的逻辑值时,基本逻辑运算的运算结果。 ab!a!ba|ba&bTTFFTTTFFTFTFTTFFTFFTTFF表表3.1 基本逻辑运算的真值表基本逻辑运算的真值表 第33页/共150页选择型程序描述了求解规则:在不同的条件下所应进行的相应操作。 下面分别介绍C语言中用来实现选择结构的三种语句。结构的应用 if (表达式) 语句1 else 语句2ifelse构造了一种二路分

31、支选择结构,它具有如下格式:这里,语句1和语句2就是两路分支。执行这个结构,首先对表达式进行判断,若为“真”(非零),就执行if分结构(语句1);否则(值为0),就执行else分结构(语句2)。if (表达式)语句1else语句2第34页/共150页例3.3 求一个数的绝对值。 设有任意数x,它的绝对值为 判断内容:x0是否成立。 两路分支:x=x (当x0) ; x= -x (当x0 ) C函数如下:-x (x0)x (x0)x=/* 文件名:文件名:ex030301.c */* 求绝对值求绝对值 */double abstr (double x)if (x0.0)x=-x;elsex=x;

32、return (x);第35页/共150页下面是函数abstr被调用执行的情况:#include int main(void)double a, abstr (double a);printf (Enter real number a please:);scanf (%1f,&a);printf (abstr(%1f)=%1 fn, a, abstr (a);rerurn 0;运行情况如下 Enter real number a please: -98.7654 abstr (-98.765400)=98.765400第36页/共150页C语言还允许使用缺省else分结构的ifelse

33、结构。其形式为:如上述abstr()函数可以改写为:double abstr (double x)if (x0.0)x=-x;return (x); 这种结构称为不平衡if结构。它不如平衡的if结构容易理解和清晰。下面看一个稍复杂的例子。if (表达式)语句第37页/共150页例3.4 三数中取大数。 有人按照图3.9所示的算法逻辑设计了下面的函数:/* 文件名:文件名:ex030401.c */* 三数取大三数取大 */float max3 (float x, float y, float z)float max=x;if (zy)if (zx)max=z;elseif (yx)max=y;

34、return (max);然而,它被main()函数调用时的的一次运行情况如下: Enter 3 real numbers a,b,c:12.34 5.67 34.56 The max is 12.300000这就因为使用不平衡if结构时,没有搞清ifelse结构的语法规则。第38页/共150页zxmax=z(空)max = x假真yxmax=y(空)真假zy真假return(max)图图3.9 例例3.4的设计者使用的算法的设计者使用的算法 第39页/共150页C语言不规定程序的书写格式,允许以灵活的格式书写。在编译时完全不考虑程序的书写格式,只凭语法规则来确定程序中的逻辑关系。当程序中存在

35、嵌套的ifelse结构时,由后向前使每一个else都与其前面的最靠近它的if配对。如果一个else的上面又有一个未经配对的else,则先处理上面的(内层的)else的配对。这样反复配对,直到把全部else用完为止。按照这一规则,例3.4中的函数max3实际上具有如图3.10所示的逻辑关系。显然,这是一个错误的算法,因为当x,y,z分别为(2,3,1)和(1,3,2)时,结果是错误的。(空)zxmax=z假真yxmax=y真假max = xzy真假return(max)图图3.10 例例3.4程序实际使用的算法程序实际使用的算法 第40页/共150页 通过这个例子可以看到:(1) 不平衡的ife

36、lse结构会增加阅读和理解程序的困难。(2) 正确的缩进格式(即锯齿形书写格式)可以帮助人们理解程序,但错误的缩进格式反而会使人迷惑。(3) 不要太相信自己的判断,要严格按语法关系检查程序。在不易弄清的地方可以加花括号来保证自己构思的逻辑关系的正确性。如上述程序可以改写为:float max3 (float x, float y, float z) float max=x;if (zy)if (zx)max=z;elseif (yx)max=y;return (max);第41页/共150页例3.5 求一元二次方程ax2+bx+c=0的根。 算法设计:一元二次方程式的根有下列情况: 当a=0,

37、b=0时,方程无解; 当a=0,b0时,方程只有一个实根-c/b; 当a0时,方程的根为x=(-bb2-4ac)/(2*a)。其中, 当b2-4ac0时有两个实根;当b2-4ac0时,有两个虚根。图3.12为上述算法的N-S图表示,它把上述逻辑关系表示得更为清晰。b=0输出“无解”输出单根:x=-c/b假真disc0输出两复数根输出两实根真假a=0真假 disc=b*b - 4*a*c图图3.12 求一元二次方程根的算法求一元二次方程根的算法第42页/共150页/* 文件名:文件名:ex030501.c */* 求解一元二次方程求解一元二次方程 */include void solv_quad

38、r_equa (float a, float b, float c)if (a=0.0)if (b=0.0)printf (no answer due to input errorn);elseprintf (the single root is %fn, -c/b);elsedouble disc, twoa, term1, term2;disc=b*b-4*a*c;twoa=2*a;term1=-b/twoa;term2=sqrt (fabs (disc)/twoa;if (disc0.0printf (complex root:n real part=%f,imag part=%fn,

39、term1, term2);elseprintf (real root:n root1=%f, root2=%fn,term1+term2, term1-term2);由此N-S图可以编写出以下的函数:第43页/共150页程序第2行第一个单词void表示函数solv_quadr_equa的类型为“空类型”,即该函数无返回值,因为求出的方程解都是在执行该函数时输出的,不需要将方程解带回主程序中输出。所以函数值为“空”。程序solv_quadr_equa 的第15行中fabs是一个标准数学函数名,输出一个实数的绝对值。请读者自己编写出测试此函数的main函数。第44页/共150页结构的应用if(表

40、达式1)if-else if是一种多分支选择结构,用流程图描述如图3.13所示,用N-S图描述如图3.14所示,C语言中的格式如下:if(表达式1) 语句1else if(表达式2) 语句2else if(表达式n) 语句nelse语句n+1第45页/共150页真假表达式1表达式2表达式n语句n+1语句n语句2语句1真真假假图图3.13 if-else if结构的流程图描述结构的流程图描述第46页/共150页图图3.14 else if结构的结构的N-S图描述图描述语句1语句2语句3真假表达式1假真表达式2真假表达式3第47页/共150页例3.6 根据百分制分数决定成绩的等级: 80分以上为A

41、级; 70分及以上,80分以下,B级; 60分及以上,70分以下,C级; 60分以下,D级。图3.15为用if-else if结构描述的上述规则。真假score=80score=70等级A真假输入scorescore=60等级B等级D等级C图图3.15 根据百分制分数决定成绩的等级根据百分制分数决定成绩的等级第48页/共150页程序如下:/* 文件名:文件名:ex031701.c */* 按成绩分等按成绩分等 */include int main(void)float score;printf(“Input a scre:”);scanf(“%f”,&score);if (score

42、= 80)printf (%f is An,score);else if (score = 70)printf (%f is Bn,score);else if (score = 60)printf (%f is Cn,score);elseprintf (%f is Dn,score);return 0;第49页/共150页可以看到,if-else if是通过一连串的判断,来寻找问题的解。它排列了一系列操作,每一种操作都是在相应的条件下才能执行的。该结构开始执行后,便依次去对各个条件进行判断测试,符合某一条件,则转去执行该条件下的操作,其它部分将被跳过;如无一条件为真,就执行最后一个else

43、所指定的操作。这个else可以看作“其它”。若最后一个else不存在,并且所有条件的测试均不成功,则该else if结构将不执行任何操作。第50页/共150页结构的应用 switch是一种多分支选择结构,其形式如右。 switch结构也称标号分支结构,它用花括号括起了一系列case子结构。每个case子结构都以一个常量表达式作为标志的标号,并按照下面的规则匹配:计算switch的判断表达式,并以此值去依次找与之相等的case标号值,找到后就将流程转到该标号处,执行后面各语句;如果找不到符合的case子结构,就只执行default子结构中的语句序列。default子结构对于switch结构不是必

44、须的。当没有default子结构,并且没有相符合的case时,该switch结构就不被执行。switch(表达式表达式)case 常量表达式常量表达式1:语句序列语句序列1case 常量表达式常量表达式2:语句序列语句序列2case 常量表达式常量表达式n:语句序列语句序列ndefault:语句序列语句序列n+1第51页/共150页请注意如果switch的判断表达式的值与case常量表达式i的值相等(称为匹配),在执行后面的语句序列i之后,并不立即退出switch结构,而是继续执行语句序列i+1,语句序列i+2,语句序列n语句序列n+1如图3.16所示,这种流程往往不是编程者所希望的。编程者希

45、望在执行匹配的常量表达式后面的语句序列 i 之 后 , 应 立 即 退 出switch结构。为了解决这一问题,可以在各语句序列后面加一条break语句,使流程脱离switch结构。如图3.17所示。表达式语句序列1常量表达式1:语句序列2常量表达式2:语句序列i常量表达式i:语句序列n常量表达式n:语句序列n+1default图图3.16 switch3.16 switch控制结构控制结构1 1第52页/共150页这里,break语句的作用是中断该switch结构,即将流程转出switch结构。所以,执行switch结构的就相当于只执行与判断表达式相匹配的一个case子结构中的语句。其实,可以

46、将break看作为语句序列中必要的成分(位置在语句序列中的最后)。 switch(表达式表达式)case 常量表达式常量表达式1:语句序列语句序列1break;case 常量表达式常量表达式2:语句序列语句序列2break;case 常量表达式常量表达式n:语句序列语句序列nbreak;default:语句序列语句序列n+1break;图图3.17 switch3.17 switch控制结构控制结构2 2表达式语句序列1常量表达式1:语句序列2常量表达式2:语句序列i常量表达式i:语句序列n常量表达式n:语句序列n+1defaultbreak;break;break;break;break;第

47、53页/共150页例3.7 将一个月份数字转换成英文月份名称。 用函数实现这个功能如下:/* 文件名:文件名:ex030701.c */* 输出月份名称输出月份名称 */void MonthName(int month)(switch (month)case 1: priontf(“Januaryn”);break;case 2: priontf(“Februaryn”);break;case 3: priontf(“Marchn”);break;case 4: priontf(“Apriln”);break;case 5: priontf(“Mayn”);break;case 6: prio

48、ntf(“Junen”);break;case 7: priontf(“Jaulyn”);break;case 8: priontf(“Augustn”);break;case 9: priontf(“Septembern”);break;case 10: priontf(“Octobern”);break;case 11: priontf(“Novembern”);break;case 12: priontf(“Decembern”);break;default: priontf(“Illegal monthn”);break;return;第54页/共150页这个例子中,每一个case子结

49、构的最后一个语句都是break。下面的例子中,是部分case子结构中有break语句。例3.8 测试是数字、空白还是其它字符的函数(假设测试的对象只限于以上几种字符)。/* 文件名:文件名:ex030801.c */* 测试字符类型测试字符类型 */int test_char (int c)switch (c)case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9:printf (its a digit n);break;case :case n:case t:printf (it s a whiten);br

50、eak;default:printf (it s a charn);break;第55页/共150页这个函数的执行过程如下:switch的条件表达式是一个已有整数值的c(今设c=8),于是从上至下找各case后的常数0,1,2,3,4,5,6,7,8,于是从case 8入口开始执行下面的语句(采用了结构1)。case 8后面没有语句,就执行case 9后面的printf函数语句,然后遇到break语句时跳出switch结构。当测试都失败时,即default以上的各case都不匹配,default则囊括了“除上述各case之外的一切情形”,于是执行default子结构,直到遇到break退出sw

51、itch结构。从语法上讲,default子结构中的break语句并不是必须的,执行完default子结构中的各语句后,则后面已无可执行的语句了,会自动退出switch结构。这里使用了一个break语句是为了排列上的整齐及理解上的方便。default子结构考虑了各case所列出的情形以外的其它情形。这样就能在进行程序设计时,把出现频率低的特殊情形写在case的后面,而将其余情况写在default后面作“统一处理”。如果只考虑对个别情况的处理,则可将各个情况分别写在各个case的后面,此时default子结构可以省略。第56页/共150页 使用switch结构须注意以下几点:(1) 一个switc

52、h结构的执行部分是一个由一些case子结构与一个可缺省的default子结构组成的复合语句,它们位于一对花括号之中。(2) switch的判断表达式只能对整数求值,可以使用字符或整数,但不能使用浮点表达式。case表达式应当是整型常数表达式,不能含有变量与函数的常数表达式。例如可以是:case 3+4:但不允许写为:int x=3,y=4;switch (z)case x+y:第57页/共150页 (3) 一个switch结构中不可以出现两个具有相同值的常量表达式。例如: case 3+2: case 8-3: 是不允许的。(4)switch的匹配测试,只能测试是否相等,不能测试关系或逻辑。(

53、5)C89要求C编译系统应当实现 一个switch最少可以包含257个case子结构,而C99要求最少支持1023个case子结构。(6)switch结构允许嵌套。第58页/共150页/* 文件名:文件名:ex030901.c */* 联想猜词游戏联想猜词游戏 */include stdio.hint main(void)int c;c=getchar(); getchar(); /* 为接收一个字符,再接收一为接收一个字符,再接收一个分隔符个分隔符换行或空格换行或空格*/例3.9 联想猜词游戏 这个游戏是:游戏者心中想好一个单词,并先在键盘上输入第1个字母,然后让计算机猜所选的是哪个单词;如

54、果计算机显示出的单词不只一个,游戏者就要再输入第2个字母,如此操作,知道计算机猜出这个单词或得出“猜不出”的结果为止。 下面的程序以猜“计算机语言名称”为例。第59页/共150页switch (c)case a:case A:printf (Ada, Algol?n);c=getchar(); getchar();switch (c)case d:case D:printf (Ada n);break;case l:case L:printf (Algol n);break;default:printf (input errorn);break;break;case b:case B:prin

55、tf (Basic, BCDL?n);c=getchar(); getchar();switch (c)case a:case A:printf (Basicn);break;case c:case C:printf (BCDLn);break;default:printf (I am sorry!n);break;break;第60页/共150页case c:case C:printf (C,Cobol,C+,C#? n);c=getchar(); getchar();switch (c)case c:case C:printf (Cn);break;case o:case O:printf

56、 (Coboln);break;case +:printf (C+n);break;case #:printf (C#n);break;default:printf (I am sorry!n);break;break;default:printf (I am sorry!n);break;return 0;这是一个简单的switch嵌套。输入2个字母后就可找出唯一的单词。如果单词量大而且两个字母还不能区分出单词时,嵌套层次就要增加,程序也就复杂了。第61页/共150页条件表达式 条件表达式也称问号表达式,它的一般形式为:表达式1?表达式2:表达式3它的操作过程为:若表达式的值为真(非0),则

57、以表达式2的值作为该条件表达式的值;否则取表达式3的值作为该条件表达式的值。第62页/共150页例3.10 计算a+b的值。/* 文件名:文件名:ex031001.c */* 计算绝对值计算绝对值 */#include int main(void) /*计算计算a+b的值的值*/float a,b;printf (input 2 reals please:);scanf (%f%f,&a,&b);printf (n%f+%f=%f,a,b,b=0?a+b:a-b);return 0;第63页/共150页运行情况如下:input 2 reals please: 10-9010.0

58、00000+-90.000000=100.000000printf()函数中b=0? a+b a-b,当b0(b为正值)时,取值a+b;当b0(b为负)时,取值a-b。条件运算符“?:”共要求三个运算量,是C语言中唯一的三元运算符。第64页/共150页例3.11 输入两数,输出大者。/* 两数中取大两数中取大 */* 文件名:文件名:ex031101.c */#include int main(void)float a,b, max;printf (input 2 reals please:);scanf (%f%f,&a,&b);max=ab?a b;printf (The

59、max is %fn, max);return 0;运行情况如下:input 2 reals please: -100 89The max is 89.000000第65页/共150页因为条件运算符的优先级很低,仅仅比赋值操作符的级别高。其结合方式与赋值操作一样是从右至左的。因此,表达式max=ab? a b相当于:max=(ab?a:b);还须注意,C语言程序设计中,要求尽量避免使用“多余的临时变量”,尽量把程序表述得简洁。如上述程序中可以省去一个变量max,写为:#include int main(void)float a,b;printf (input 2 relas please:);

60、scanf (%f%f,&a,&b);printf (The max is %fn,ab?a:b);return 0;第66页/共150页 迭代与穷举算法采用循环(或称重复)结构是计算机程序的一个重要特征。计算机运算速度快,最宜于用于重复性的工作。在程序设计时,人们也总是把复杂的不易理解的求解过程转换为易于理解的操作的多次重复。这样,一方面可以降低问题的复杂性,减低程序设计的难度,减少程序书写及输入的工作量;另一方面可以充分发挥计算机运算速度快、能自动执行程序的优势。在循环算法中,穷举与迭代是两类具有代表性的基本应用。这一节的主要内容就是引导读者如何用C语言的三种循环结构来实现这两种基本算法。第67页/共150页1. 迭代 迭代是一个不断用新值取代变量的旧值,或由旧值递推出变量的新值的过程。例3.12 人口增长问题。 按年0.2%的增长速度,现有13亿人,10年后将有多少人? 设现人口数为

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论