结构化程序设计的基本思想是围绕系统功能自顶向下.ppt
《结构化程序设计的基本思想是围绕系统功能自顶向下.ppt》由会员分享,可在线阅读,更多相关《结构化程序设计的基本思想是围绕系统功能自顶向下.ppt(101页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、结构化程序设计的基本思想是围绕系统功能自顶向下 Still waters run deep.流静水深流静水深,人静心深人静心深 Where there is life,there is hope。有生命必有希望。有生命必有希望重点重点:函数的声明和函数调用;递归概念及其应用;数据的存储类别和作用域。课堂时数:1012学时上机时数:45学时课外上机时数:56学时数据的存储类别和作用域。内联函数和重载函数;4.1 函数的基本概念函数的基本概念我们从结构化程序设计的角度来讨论大程序的功能分解及其函数实现,进而给出函数的定义并讨论函数的作用。1什么叫函数什么叫函数把实现特定功能的相关数据和语句组织在一
2、起,并给出相应的名称、类型和参数集,成为程序的一个可调用部分和可共享部分,这种组合形式称为函数。1)分析我们将新建、打开、关闭、打印等文件处理功能描述成四个相对独立的函数,分别是:例4-1文件处理包括以下几个功能:新建、打开、关闭、打印,请给出有关文件处理的程序框架。new()、open()、close()、print()这些函数都包含了各自的数据和语句,并且都有各自的外部名称函数名。/程序头部程序头部void main();new();open();close();print()2)程序框架3)调用结构main函数分别调用了new、open、close、print四个函数。mainnewop
3、encloseprint注意:一个C+程序可以包含多个函数,这些函数在定义层次上必须是相同的,但调用层次却可以不相同。2函数的作用函数的作用函数是特定子功能的实现,也即将大程序分割成若干个小程序(子程序)。每个子程序就是一个函数,这样既便于理解也便于实现。当函数所实现的是程序中频繁使用的一些公共操作,那么该函数就可以重复调用,也就是所谓的“代码重用”。若干功能相关的函数可以组成一个模块。综上所述,合理地使用函数便于功能分解和程序实现;可以减少程序的重复编写;可以使程序结构清晰、增强易读性。这就是函数的三大作用。3函数的分类函数的分类通常分为:标准函数、用户自定义函数、类的成员函数三大类。标准函
4、数也称为库函数,是系统定义的函数,c+提供了种类繁多的库函数,具体可以分为:I/O类,处理I/O操作;文件类,处理二进制文件和缓冲型文件;字符串类,实现字符串运算和字符串操作;内存类,处理内存分配、释放、测试,传送等工作;系统类,实现系统调用、系统设置以及底层硬件操作等。4.2 函数定义函数定义程序中使用函数就象使用数据对象一样,必须先定义后使用。定义函数也称为声明函数。1作用作用给出函数的名称、类型、参数,描述函数内部的数据和语句。2语法语法C+的函数由函数头部(函数原型)和函数体两部分组成,其语法描述为:()数据说明部分;/函数体/函数头部解释:解释:类类型型标标识识符符:用来说明函数的数
5、据类型,也即函数调用后所返回的调用结果的数据类型,可以是int、char、float、double、void等。如果省略类型标识符的话,则缺省类型是int。如果该函数的类型无关紧要,一般表示成void。例如:voidmain(),doublemax(doublex,doubley),main的类型是void而max的类型是double。函函数数名名:C+用标识符作为函数名。函数名具有变量特征,它用来存放返回值。例如:sqrt(16)sqrt=4;upper(a)upper=A;参数表:参数表:用来说明函数的参数,函数的参数是函数所提供的数据接口,用来与调用者传递数据。因此参数说明必须给出参数的
6、名称、类型。允许一个函数包含0到多个参数,参数之间用逗号分隔。数据说明部分:数据说明部分:位于函数体内,用来说明函数内部所用到的数据对象(变量等),如果函数没有内部数据,则此部分可以省略。函数说明所定义的参数称为“形式参数”,而函数调用所提供的参数称为“实在参数”。例如:charupper(charc)只有一个参数,名称为c,类型是字符型。doublemax(doublex,doubley)有两个参数x和y,类型都是双精度型。执行部分,位于函数体内,由若干可执行语句组成,该部分不能省略。例4-2编写一个将小写英文字母转换成大写英文字母的函数。charupper(charc)charc1;if(
7、c=a&c=z)c1=c-32;elsec1=c;return(c1);函数名:upper,类型:字符型;形式参数:charc;内部数据说明:charc1;执行部分:if语句和return函数调用。例4-3编写计算字符串长度的函数strlenintstrlen(chars)inti=0;while(si!=0)i+;return(i);函数名:strlen,类型:整型;形式参数:chars;s是数组内部数据说明:inti;4.3 函数原型函数原型函数原型是一条特殊的说明语句,用来说明程序中所引用的函数的名称、函数返回值类型和参数类型。1什么叫函数原型什么叫函数原型函数原型格式上与函数定义的头部
8、大致相同,但因为是独立的语句,必须以分号结束,并且一般放在程序的顶部。例4-4在引用strlen函数的程序中加上其原型说明。#includeintstrlen(char*);main()strlen();intstrlen(chars)strlen函数的原型说明2函数原型的语法函数原型的语法函数原型的格式与函数定义的头部格式大同小异,其语法如下:();注意:注意:(1)参数类型表给出函数所有参数的数据类型(无须给出参数名);(2)函数原型和函数定义在函数类型(返回值类型)、函数名以及参数表这三部分上必须一致,否则就会发生编译错误;(3)标准库函数的原型都在对应的头文件中(*.h)。如果程序中使
9、用到某些标准库函数,必须在程序顶部,使用#include命令将对应的文件包含进来。3函数原型的作用函数原型的作用在程序中加入函数原型,有利于保证函数定义和调用上的一致性。这里的一致性是指定义和调用时,函数类型、参数个数和类型方面的一一对应。一致性的检测工作是由编译系统自动进行的,当程序中加入函数原型,一旦函数原型不正确,也即与函数定义不同,编译系统会报告出错,并给出相应的出错信息。例如在例4-4的main函数中按以下格式调用strlen函数:strlen(s1,n);编译程序在编译过程会检测到在调用strlen函数时提供的参数过多的错误,并提示:functiondoesnottake2para
10、meters(函数在调用中遇到过多的函数参数)voidfunc1(int,float);voidmain()inta;floatb;cinab;func1(a,b);voidfunc1(int,int)floatc;c=a+b;例4-5函数原型和函数定义其参数类型不一致的问题示例。分析:(1)程序中,func1函数原型和函数调用是一致的,能正确地通过编译。(2)因为函数原型的参数类型与函数定义的参数类型不一致,则不能通过连接,连接时会给出“不能确定的外部函数”这样的出错信息。注意:当所调用的函数是标准函数或该函数不在本程序中,定义和调用的一致性问题就更加重要了。函数的功能是通过调用实现的,调用
11、时必须提供与函数定义相对应的各个参数的实际值,调用的返回值存放在函数名中,因此函数调用结果可以视为一个数据对象。4.4 函数调用函数调用将函数调用视为数据对象并作为表达式的成员参加运算,这是函数调用的一般形式。1函数调用的格式(语法)函数调用的格式(语法)();解释:解释:(1)函数是“按按名名调调用用”的,所以函数名必须准确无误,尤其是在调用标准库函数时,一定要保证函数名一字无误。例如:len=strlen(s);sin(x)/con(x);例如:要调用scanf()函数,如果将函数名写成scan,便会出现“不能确定的外部函数”这样的错误。此类错误是初学者最容易犯的。(2)参参数数表表:给出
12、与函数定义所描述的形式参数相对应的各个实在参数。所谓相对应是指:类型一致,个数相等,顺序吻合。/strlen:函数名,s:参数(3)函数调用时所提供的实参其形式可以是常量、变量、表达式、函数调用等。但其值必须是确定的。请看以下一些函数调用:2函数调用的形式函数调用的形式sqrt(30)sqrt(a)sqrt(a*100)sqrt(abs(x)前面已提到函数调用的一般形式是将其视为数据对象,在参加运算时实现调用。这种数据对象可以出现在以下三种场合,分别对应三种不同的调用形式:实参是常量;实参是变量;实参是表达式;实参是另一函数调用。1)表达式)表达式函数调用出现在表达式中,参加所在表达式的运算。
13、例如:2*sqrt(56)2*56 2)函数调用语句函数调用语句函数调用语句实际上是仅含单个“函数调用数据对象”的特殊表达式,因此是1)的特例。例如:scanf(),printf()等。3)函数参数)函数参数函数调用所提供的实参是某一函数调用,这种情况称为函数参数。3函数调用机制和调用过程函数调用机制和调用过程例如:max(a,max(b,c)sqrt(abs(x)。设程序p1具有三个函数,main(),f1(),f2(),其调用关系是main函数调用f1函数,f1函数调用f2函数,程序如下:void main()int a,b;f1(a);/main调用f1p1程序的执行过程如下图所示:vo
14、id f1(int x1)char c f2(c);void f2(char x2)float d /f1调用f2分析程序的执行过程,可以发现以下特征:(1)main最先执行、最后结束,f2最后执行却最先结束,正所谓“先进后出”;mainf1f2由f2返回f1由f1返回main(2)每一函数在调用另一函数时必须暂时中断自身的执行;(3)每一个被调用的函数执行结束后,必须能返回主调函数调用处的下一执行点,也即调用前必须保留返回地址。能够满足以上要求的函函数数调调用用机机制制可以概括为:中中断断+运运行行栈栈,也即c+借助于中断机制和栈来实现函数调用。1)中断)中断中断是指主调函数暂时中止自身的运
15、行,转入被调函数的执行部分,待被调用函数运行结束,主调函数又开始余下部分的执行。2)运行栈)运行栈栈是一种“先进后出”的数据结构,也即先压进去的数据最后弹出。C+在处理函数调用时,所使用的栈称为运行栈。运行栈用来存放返回地址、函数参数以及函数内部定义的数据等。运行栈随着程序的运行而动态变化。程序p1当运行至的f2被调用时的运行栈如下图所示。向上增长3)调用过程)调用过程(1)在运行栈的栈顶建立被调函数的栈空间;每一个函数的调用过程都包括:调用初始化,执行,善后以及返回三个阶段,具体分为以下步骤:(2)保护主调函数的运行状态和返回地址(保存在栈区内);(3)传递参数;(4)将运行控制权交给被调函
16、数;(5)被调函数的执行;(6)恢复主调函数的运行状态;(7)取出返回地址;(8)返回主调函数。初始化执行善后及返回4)参数传递)参数传递可以看出(1)(4)属于初始化阶段、(5)是执行阶段、(6)(8)是善后阶段。所谓参数传递就是将实参存入函数栈空间的参数区,用来代替函数定义所描述的形式参数。(1)参数的传递顺序按参数表中参数的排列顺序自左向右逐一传递。例如:函数调用f1(a,b,c),其参数的传递顺序是:先传递a再传递b最后传递c。(2)参数的传递方式)参数的传递方式将实参的值存入对应形参的参数区中。实参可以是变量、常量、表达式。a.传值传值有三种传递方式:注意:此种方式,被调函数对参数的
17、修改不会影响主调函数用做实参的数据对象。换句话说,参数的此种传递方式,只能实现数据的单向传递,也即无法由实参带回函数对参数的任何修改。b.传地址传地址所谓传地址是将实参的地址存入对应形参的参数区中。实参可以是变量、数组。传地址与传值的不同之处在于:传递的不是实参的值而是实参这一数据对象的内存地址。简而言之,这样的参数传递方式,可以实现数据的双向传递,也即可以由实参带回函数对参数的任何修改。引入这种传递方式目得在于“使得被调函数对参数的修改能够影响主调函数用做实参的数据对象”,并且可以减少数据的传送量。例:以借书为例,将书直接借给你传值;告诉你借书的地方传地址。例例4-64-6试问在下面程序段中
18、,调用函数试问在下面程序段中,调用函数f1f1后,后,a,b,ca,b,c的值分别是什么?的值分别是什么?int a=1,b,c;c=f1(a,&b);cout a b c;f1(int a,int*b)a=5;*b=a+5;return(0);分析:(1)参数a采用传值方式,参数b采用传地址方式。&b表示取b的地址。(2)调用函数参数f1后,a,b,c的值分别是:a=1,b=10,c=0。为什么?注意:f1虽然修改了a却无法返回给主调函数,因为a是值参。c.传名传名5)实例下面我们给出两个函数应用的实例,来进一步阐明函数的定义和调用过程。例例4-74-7编写一个程序。分别求两个字符串编写一个
19、程序。分别求两个字符串s1s1和和s2s2的的长度。长度。(1)分析我们可以在例4-3所编写的strlen函数的基础上增加一个主函数,该函数两次调用strlen函数。(2)程序函数的参数是函数指针,对应的参数必须是函数名。函数的参数是函数指针,对应的参数必须是函数名。#include#includeintstrlen(char*);intstrlen(char*);voidmain()voidmain()intlen;intlen;len=strlen(abcdefg);len=strlen(abcdefg);couts1couts1的长度是:的长度是:lenendl;lenendl;len=
20、strlen(aaa123456);len=strlen(aaa123456);couts2couts2的长度是:的长度是:lenendl;lenendl;intstrlen(chars)intstrlen(chars)inti=0;inti=0;while(si!=0)while(si!=0)i+;i+;return(i);return(i);/第2次调用strlen函数/第1次调用strlen函数1)分析:)分析:我们可以在例4-2所编写的upper函数的基础上增加一个主函数,该函数循环循环调用upper函数。例例4-84-8编写一个程序,用来将输入的字符串编写一个程序,用来将输入的字符串
21、s1s1中的中的小写字母转换成大写字母。小写字母转换成大写字母。2)程序:)程序:#include#includeintstrlen(char*);intstrlen(char*);charupper(char);charupper(char);voidmain()voidmain()chars30;chars30;intn.i;intn.i;coutcouts;cins;n=strlen(s);n=strlen(s);for(i=0;i=n-1;i+)for(i=0;i=n-1;i+)si=upper(si);si=upper(si);coutendlcoutendl转换后的字符串转换后的字
22、符串:sendl:s=a&c=a&c=z)c1=c-32;c1=c-32;elseelsec1=c;c1=c;return(c1);return(c1);;/循环调用upper函数/调用strlen函数,计算串长4函数的嵌套调用函数的嵌套调用虽然C+不允许在函数内部定义新的函数(嵌套定义),但却允许函数内部调用另一函数,也即允许函数之间相互调用,这种调用形式称为嵌套调用。/strlen/strlenintstrlen(chars)intstrlen(chars)inti=0;inti=0;while(si!=0)while(si!=0)i+;i+;return(i);return(i);通过嵌
23、套调用动态地建立函数之间的关系,使得程序的层次化的功能结构得以实现。1)概念)概念所谓函数的嵌套调用是指:在函数的执行部分包含对一个或一些函数的调用。嵌套可以是单重的也可以是多重的,如果被调函数的执行部分不再出现对另一函数的调用,就是单重嵌套。相反,如果被调函数的执行部分也包含对另一函数的调用,就构成多重嵌套。注意:注意:将函数调用作为实参,不能视为嵌套调用。例如sin(abs(x),不是sin函数调用abs函数,因为abs函数的调用并没有出现在sin函数的执行部分中。相反是在参数传递的时候就实现的。2)实例)实例例4-8所给的程序是函数的单重嵌套调用,并且是并列单重调用。下面分析其调用关系和
24、调用过程。调用关系:main函数调用strlen函数和upper函数,注意strlen和upper是并列调用。调用过程:mainstrlenuppervoidmain()inta,bf1(a);voidf1(intx1)charcf2(c);voidf2(charx2)floatd下面的程序包含着函数的多重嵌套调用,main函数调用f1函数,而f1函数又调用f2函数。4.5 递归函数递归函数在客观世界中,很多问题的处理方法是递归的,例如“折半查找”问题,其处理方法描述为:(1)取n个有序数据正中间的一个数据dm与查找关键字Key比较,如果dmkey,则可以确定接下去的查找范围是m+1n之间;如
25、果dm=key,则查到所须对象,查找结束。该方法告诉我们,在查找范围不断变化的情况下,后一步可以使用与前一步相同的方法来进行查找。这种现象是递归调用现象后一步骤调用前一步骤所使用的方法。(2)用新的查找范围替代上一次的查找范围,重复(1)。再比如阶乘问题,n!=n*(n-1)*(n-2)*1,这种递推问题也可以用递归调用来实现,即:n!=n*(n-1)!例4-9计算阶乘n!#includelongfact(int);voidmain();longfact(intn)if(n=1)return(1);elsereturn(fact(n-1)*n);/在fact函数中调用fact函数递归调用voi
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 结构 程序设计 基本 思想 围绕 系统 功能 向下
限制150内