《函数—模块化程序设计.ppt》由会员分享,可在线阅读,更多相关《函数—模块化程序设计.ppt(51页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、高级语言程序设计第5章 函数模块化程序设计 福建工程学院 鲍春波学习目标l模块化程序设计的思想,l自顶向下的实现方法,l系统函数库的使用方法,l自定义函数的方法,l参数传递方式,l函数调用过程,l接口与实现的分离,l开发大规模程序引言l如何对比较复杂、庞大的问题进行程序设计?例如:绘制一个动物图案l头 正方型l躯干菱形l下肢矩型 建立一个学生信息管理系统l界面l建立信息l维护信息l查询信息解决比较大的问题要成千上万行代码怎么实现呢?l每个软件只有一个main(),main()当中能放多少行程序?l读多少行的程序能让你不头疼?l如果所有代码都在main()当中,怎么团队合作?l如果代码都在一个文
2、件中,怎么团队合作?模块化程序设计思想l复杂问题分解成若干子问题模块,逐个解决每个子问题l模块各司其职每个模块只负责一件事情,它可以更专心一个模块一个模块地完成,最后再将它们集成便于开发、调试、测试和维护等工作l开发人员各司其职按模块分配任务,职责明确并行开发,缩短开发时间l分而治之(Wirth,1971)信息隐藏(Parnas,1972)C语言用函数表示模块l分而治之分而治之函数把较大的任务分解成若干个较小的任务,并提炼出公用任务l代码代码复用复用程序员可以在其他函数的基础上构造程序,而不需要从头做起l信息隐藏信息隐藏(黑盒子)(黑盒子)设计得当的函数可以把具体操作细节对程序中不需要知道它们
3、的那些部分隐藏掉,从而使整个程序结构清楚l如把编程比做制造一台机器,函数就好比其零部件可将这些“零部件”单独设计、调试、测试好,用时拿出来装配,再总体调试。这些“零部件”可以是自己设计制造/别人设计制造/现在的标准产品函数的定义形式l返回值类型 函数名(参数列表)ll 函数体变量声明部分语句部分l l函数可以没有返回值,也可以没有参数,均用void表示如:void funcname(void)l参数列表的形式:参数类型 参数名称1,参数类型 参数名称2,如:int maxium(int a,int b,int c)具有三个参数,返回类型为int的函数或 void print(int a,int
4、 b)如大家熟悉的 int main(void)printf(。);实际上 printf,scanf也是这样定义的我们可以根据需要定义各种自己的函数。函数调用已经定义的函数要在某个地方使用才有意义,使用一个函数称为函数调用。可以在main()中调用其它函数在任意一个函数中均可以调用其它函数。调用的形式:函数名(实际参数)-有参数时 或 函数名()-无参数时问题1 绘制一个动物图案。l定义无参数、无返回类型的函数定义无参数、无返回类型的函数l如打印矩型的函数l void Rectangle(void)。使用已经定义的函数测试lvoid Rectangle(void)/这种函数叫做stub 树桩或
5、存根 printf(“rectangle okn”);/仅供测试 void diamond(void)printf(“diamond okn”);lint main(void)ll rectangle();/函数调用l diamond();l rectangle();l return 0;l l被调用的函数必须先定义,即各个函数的定义现在一定要放在主函数之前(等会我们会有另外的方法)问题2 学生信息系统l 同样每个功能模块用一个函数表示void create(void)void display(void)void modify(void)void query(void)void delete(
6、void)l写一个main测试它们问题3:设计一个能求某个自然数以内的自然数之和的函数模块有参数和返回值的函数l分析:首先取名 sum确定是否有返回值?如果有,是什么类型?确定是否有参数?几个?什么类型?l函数定义int sum(int n)int s=0;for(int i=1;i=n;i+).s=s+i;return s;l此函数有一个整型参数,有一个整型的返回值l在函数定义中的参数称为形参,只是一个形式定义,这个参数的具体值由调用者通过实参给定,实参可以是一个与形参类型一致的表达式。测试sum函数 驱动程序l#includelint sum(int n)ll llint main(voi
7、d)l int m,s;scanf(“%d”,&m);/准备一个实参m s=sum(m);/调用sum printf(“%dn”,s);/输出结果 /或者直接 printf(“%dn”,sum(m);return 0;函数调用的注意事项1l有返回值时调用结果可以放到一个数值表达式中,如s=sum(m);也可以作为另一个函数调用的参数,如printf(%dn,sum(m);l无返回值时函数调用只能独立使用 rectangle();函数调用的注意事项2l实参可以是符合参数类型的常量l如 s=sum(100);变量l如 s=sum(m);表达式l如 s=sum(m+10);实参与形参必须一致l函数调
8、用时实参与形参必须保持参数个数相同参数类型相同,如果不同将自动转换参数顺序相同l当函数有多个表达式参数时,函数调用时实参求值的顺序可能是从左到右或从右到左,举例funcpara.cpp为了清楚起见,需要对函数接口加以注释说明/*函数功能:实现功能 函数参数:参数1,表示 参数2,表示 函数返回值:*/返回值类型 函数名(参数表)函数体return 表达式;问题4 设计一个求两个数的平均值的函数模块/*函数功能:计算平均数 函数入口参数:整型x,存储第一个运算数 整型y,存储第二个运算数 函数返回值:平均数*/int average(int x,int y)int result;result=(
9、x+y)/2;return result;函数执行的过程l函数调用时,实参值传递给形参变量l暂时离开调用者,去执行函数体l函数执行完毕后,回到调用的位置,继续执行调用者的语句使用了average函数的main()main()int a=12;int b=24;int ave;ave=average(a,b);printf(“average of%d and%d is%d.n,a,b,ave);int Average(int x,int y)int result;result=(x+y)/2;return result;main()int a=12;int b=24;int ave;ave=Av
10、erage(a,b);printf();数据传递执行顺序问题5 设计一个判断某个数是否是素数的函数模块问题6 设计一个求某个数a的n次幂的函数模块l可以定义各种各样的函数模块当问题比较复杂时,需要很多函数l所有自定义的函数都要放在main的前面,这将喧宾夺主,本末倒置l解决的方法是解决的方法是在使用之前,先有在使用之前,先有函数的原型声明函数的原型声明l实际上,头文件中包含了要使用的函数的函数的原型声明原型声明l 如stdio.h中包含了printf,scanf等跟I/O相关的函数原型l某一模块定义为一个函数之后,在使用它(函数调用)之前,先用函数原型声明。l使用函数原型声明,重写上述例题函数
11、原型的作用l函数原型 如 int sum(int n);可以写成 int sum(int)l函数原型告诉编译器函数返回的数据类型,函数接收的参数个数,参数类型及参数顺序l强制转换参数类型小结:函数三要素l函数原型l函数调用l函数定义函数的分类l库函数ANSI/ISO C定义的标准库函数l符合标准的C语言编译器必须提供这些函数l函数的行为也要符合ANSI/ISO C的定义第三方库函数l由其它厂商自行开发的C语言函数库。不在标准范围内,能扩充C语言的功能(图形、网络、数据库等)l自定义函数自己编写的函数l包装后,也可成为函数库,供别人使用数学函数库使用l常用的数学函数l sqrt(x)l exp(
12、x)l log(x)自然对数l log10(x)l fabs(x)l ceil(x)不小于x的最小整数l floor(x)不大于x的最大整数l pow(x,y)l sin(x)x为弧度l.#includel找出所有小于500的构成直角三角形的三条边input a,b,cc=sqrt(pow(a,2)+pow(b,2)l求一元二次方程的根 a,b,c sqrt(b*b 4*a*c)0 sqrt(b*b 4*a*c)0 sqrt(b*b 4*a*c)=0l打印02PI之间sin(x)对照表l例sinecurve.cpp 随机数的产生l rand()产生一个0到 RAND_MAX(32767)之间的
13、一个整数,伪随机数l需要包含 stdlib.hl l模拟掷硬币和骰子l缩放 rand()%6lsrand(unsigned)为rand()设置种子ltime(NULL)参数NULL返回秒为单位的计算机系统的当前时间。time.hl srand(time(NULL)l例rand.cppvoid Print(int flag)void Print(int flag)if(flag)if(flag)printf(Right!n);printf(Right!n);else else printf(Not correct!n);printf(Not correct!n);小学生加法考试题/*函数功能:计
14、算两整型数之和,如果与用户输入的答案相同,则返回1,否则返回0 函数参数:整型变量a和b,分别代表被加数和加数 函数返回值:当a加b的结果与用户输入的答案相同时,返回1,否则返回0*/int AddTest(int a,int b)int answer;printf(%d+%d=,a,b);scanf(%d,&answer);if(a+b=answer)return 1;else return 0;只答1次main()int a,b,answer;printf(Input a,b:);scanf(%d,%d,&a,&b);answer=AddTest(a,b);Print(answer);do
15、 while(answer=0);小学生加法考试题小学生加法考试题 直到做对为止main()int answer,chance=0;do answer=AddTest(a,b);Print(answer);chance+;while(answer=0&chance 3);小学生加法考试题小学生加法考试题 最多给3次机会 int a,b;int error=0;int score=0;srand(time(NULL);for(int i=0;i10;i+)a=rand()%10+1;b=rand()%10+1;answer=AddTest(a,b);Print(answer);if(answer
16、=1)score=score+10;else error+;实验实验4 4:小学生加法考试题:小学生加法考试题 随机出题连续做10道题统计分数通用小学生算术软件碰运气游戏-掷双骰子l游戏规则l 掷两个骰子,点数相加。第一次时如果和为7或11则玩家赢;如果得到的和适2、3或12,玩家输;如果和为4、5、6、8、9或10,用这个和作为游戏的点数。要想赢,继续掷,直到取得自己的点数为止。但是如果掷出了7点玩家则输。返回多个值的函数l可以通过函数的返回语句返回某个类型的计算值,但是只能返回一个。l实例研究:交互两个数的函数如何交换两个数swap.cppl可见函数的参数传递是单向的,不能通过简单的函数参
17、数传递实现实参值的改变l为什么不能,其原因是传值怎么样才能反向传递呢?l参数用变量的地址lrefswap.cppl怎么声明存放变量地址的变量参数?指针变量声明符*int*aPtr;int a;二者不同 aPtr=&a;二者联系起来l怎么访问指针变量指向的内存变量?间接引用运算符*aPtr=10;a=10;二者效果相同l可以看出,通过指针参数可以实现返回多个结果l再看一个实例l设计一个函数,可以处理学生成绩的简单计算和求平均值。void gradeStatistics(int*numbers,float*ave)变量的作用域l变量是有生命的,有范围的l指在源程序中定义变量的位置及其能被读写访问的
18、范围l分为局部变量(Local Variable)全局变量(Global Variable)局部变量(Local)l局部变量在语句块内定义的变量形参也是局部变量l特点定义时不会自动初始化,除非程序员指定初值进入语句块时获得内存,仅能由语句块内语句访问,退出语句块时释放内存,不再有效 并列语句块各自定义的同名变量互不干扰 全局变量(Global)l全局变量在所有函数之外定义的变量l特点在程序中定义它的位置以后都有效在定义点之前或在其他文件中引用,应该进行如下声明:extern 类型名 变量名;从程序运行起即占据内存,程序运行过程中可随时访问,程序退出时释放内存 使函数之间的数据交换更容易,也更高
19、效l但是并不推荐使用,尽量少用l因为谁都可以改写全局变量,所以很难确定是谁改写了它存储类型l一个完整的变量说明格式如下:存储类型 数据类型 变量名如:static int x,y;lC程序的存储类别有:auto型(自动变量型)static型(静态变量型)register型(寄存器型)自动变量(auto)l“自动”体现在进入语句块时自动申请内存,退出时自动释放内存 l标准定义格式 auto 类型名 变量名;动态局部变量缺省的存储类型不初始化时,值是不确定的静态变量(static)l函数的内部变量在函数退出后失效(内存释放)。再次进入函数,变量重新定义每次函数执行都建立一个全新的执行环境,不受其它
20、函数的干扰l把此变量定义为static,则变量的值可以保存到下次进入函数static int i;l静态变量自动初始化为0寄存器变量(register)l寄存器是CPU内的高速但容量有限的存储器l使用频率比较高的变量声明为register,可以使程序更小、执行速度更快register 类型名 变量名;register int i;l它只是一个建议编译器有权决定变量是否是register编译器的决定往往更科学所以,通常用不着它变量的生存期l静态存储区中的变量与程序“共存亡”l动态存储区中的变量与语句块“共存亡”l寄存器中的变量同动态存储区 程序的调试与测试小结与作业l1.设计一个打印10行10列的直角三角形图案的函数,要求无参数无返回值。l2.设计一个判断一个数是否是素数的函数,是返回1,不是返回0。l3.设计模拟掷硬币的程序。每投掷一次硬币,程序要打印出正面还是反面,投掷100次,计算出现正面的次数。其中投掷硬币调用一个函数叫flip,自己定义,不带参数,正面返回1,反面返回0。l4.设计一个小学生乘法练习程序。