谭浩强《C程序设计》课件第4章.ppt
《谭浩强《C程序设计》课件第4章.ppt》由会员分享,可在线阅读,更多相关《谭浩强《C程序设计》课件第4章.ppt(65页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、一个较大的程序开发过程一个较大的程序开发过程:为了便于规划、组为了便于规划、组织、编程和调试,一般的做法是把一个大的程序划织、编程和调试,一般的做法是把一个大的程序划分为分为若干个程序模块若干个程序模块(即程序文件即程序文件),每一个模块实,每一个模块实现一部分功能现一部分功能。不同的程序模块可以由不同的人来。不同的程序模块可以由不同的人来完成。在程序进行编译时,以程序模块为编译单位,完成。在程序进行编译时,以程序模块为编译单位,即分别对每一个编译单位进行编译。如果发现错误,即分别对每一个编译单位进行编译。如果发现错误,可以在本程序模块范围内查错并改正。在分别通过可以在本程序模块范围内查错并改
2、正。在分别通过编译后,才进行连接,把各模块的目标文件以及系编译后,才进行连接,把各模块的目标文件以及系统文件连接在一起形成可执行文件。统文件连接在一起形成可执行文件。第第4章章 函数与预处理函数与预处理4.1 概述概述(1)无论把一个程序划分为多少个程序模块,无论把一个程序划分为多少个程序模块,只只能有一个能有一个main函数。函数。程序总是从程序总是从main函数开始执函数开始执行的。行的。(2)在程序运行过程中,由主函数调用其他函数,在程序运行过程中,由主函数调用其他函数,其他函数也可以互相调用。其他函数也可以互相调用。(3)一个一个C程序是由若干个函数组成的,程序是由若干个函数组成的,C
3、语言语言被认为是面向函数的语言。被认为是面向函数的语言。(4)C+面向过程的程序设计沿用了面向过程的程序设计沿用了C语言使用语言使用函数的方法。函数的方法。在在C+面向对象的程序设计中,面向对象的程序设计中,主函主函数以外的函数大多是被封装在类中的。数以外的函数大多是被封装在类中的。主函数或其主函数或其他函数可以通过类对象调用类中的函数。他函数可以通过类对象调用类中的函数。因此,读因此,读者必须掌握函数的概念以及学会设计和使用函数。者必须掌握函数的概念以及学会设计和使用函数。程序的组织形式:程序的组织形式:在实际应用的程序中,主函数写得很简单,它在实际应用的程序中,主函数写得很简单,它的作用就
4、是调用各个函数,程序各部分的功能全部的作用就是调用各个函数,程序各部分的功能全部都是由各函数实现的。都是由各函数实现的。主函数相当于总调度,调动主函数相当于总调度,调动各函数依次实现各项功能各函数依次实现各项功能。开发商和软件开发人员将一些常用的功能模块开发商和软件开发人员将一些常用的功能模块编写成函数,放在函数库中供公共选用。程序开发编写成函数,放在函数库中供公共选用。程序开发人员要人员要善于利用库函数善于利用库函数,以减少重复编写程序段的,以减少重复编写程序段的工作量。工作量。从从用户使用的角度看,函数有两种用户使用的角度看,函数有两种:(1)系统函数,即库函数。这是由编译系统提供系统函数
5、,即库函数。这是由编译系统提供的,用户不必自己定义这些函数,可以直接使用它的,用户不必自己定义这些函数,可以直接使用它们。们。(2)用户自己定义的函数。用以解决用户的专门用户自己定义的函数。用以解决用户的专门需要。需要。从函数的形式看,函数分两类从函数的形式看,函数分两类:(1)无参函数。调用函数时不必给出参数。无参函数。调用函数时不必给出参数。(2)有参函数。在调用函数时,要给出参数。在有参函数。在调用函数时,要给出参数。在主调函数和被调用函数之间有数据传递。主调函数和被调用函数之间有数据传递。在调用函数时,大多数情况下,函数是带参数在调用函数时,大多数情况下,函数是带参数的。主调函数和被调
6、用函数之间有数据传递关系。的。主调函数和被调用函数之间有数据传递关系。前面已提到:在定义函数时函数名后面括号中的变前面已提到:在定义函数时函数名后面括号中的变量名称为量名称为形式参数形式参数(formal parameter,简称形参简称形参),在主调函数中调用一个函数时,函数名后面括在主调函数中调用一个函数时,函数名后面括号中的参数号中的参数(可以是一个表达式可以是一个表达式)称为称为实际参数实际参数(actual parameter,简称实参简称实参)。4.3 函数参数和函数的值函数参数和函数的值 4.3.1 形式参数和实际参数形式参数和实际参数例例4.2 调用函数时的数据传递。调用函数时
7、的数据传递。#include using namespace std;int max(int x,int y)/定定义义有参函数有参函数max int z;z=xy?x:y;return(z);int main()int a,b,c;coutab;c=max(a,b);/调调用用max函数,函数,给给定定实实参参为为a,b。函数。函数值赋给值赋给c coutmax=cendl;return 0;运行情况如下:运行情况如下:please enter two integer numbers:2 3 max=3图图4.2有关形参与实参的说明:有关形参与实参的说明:(1)在定义函数时指定的形参,在未出
8、现函数调在定义函数时指定的形参,在未出现函数调用时,它们并不占内存中的存储单元,因此称它们用时,它们并不占内存中的存储单元,因此称它们是形式参数或虚拟参数,表示它们并不是实际存在是形式参数或虚拟参数,表示它们并不是实际存在的数据,的数据,只有在发生函数调用时,函数只有在发生函数调用时,函数max中的形中的形参才被分配内存单元,以便接收从实参传来的数据。参才被分配内存单元,以便接收从实参传来的数据。在调用结束后,形参所占的内存单元也被释放。在调用结束后,形参所占的内存单元也被释放。(2)实参可以是常量、变量或表达式,如实参可以是常量、变量或表达式,如max(3,a+b);但要求但要求a和和b有确
9、定的值。以便在调用函数时有确定的值。以便在调用函数时将实参的值赋给形参。将实参的值赋给形参。(3)在定义函数时,必须在函数首部指定形参的在定义函数时,必须在函数首部指定形参的类型类型(见例见例4.2程序第程序第3行行)。(4)实参与形参的类型应相同或赋值兼容。实参与形参的类型应相同或赋值兼容。(5)实参变量对形参变量的数据传递是实参变量对形参变量的数据传递是“值传递值传递”,即单向传递即单向传递,只由实参传给形参,而不能由形,只由实参传给形参,而不能由形参传回来给实参。在调用函数时,编译系统临时给参传回来给实参。在调用函数时,编译系统临时给形参分配存储单元。请注意:形参分配存储单元。请注意:实
10、参单元与形参单元实参单元与形参单元是不同的单元。是不同的单元。图图4.3表示将实参表示将实参a和和b的值的值2和和3传传递给对应的形参递给对应的形参x和和y。图图4.3 图图4.4调用结束后,形参单元被释放,实参单元仍保留并调用结束后,形参单元被释放,实参单元仍保留并维持原值。维持原值。(1)函数的返回值是通过函数中的函数的返回值是通过函数中的return语句获语句获得的。得的。return语句将被调用函数中的一个确定值带语句将被调用函数中的一个确定值带回主调函数中去。回主调函数中去。return语句后面的括号可以要,也可以不要。语句后面的括号可以要,也可以不要。return后面的值可以是一个
11、表达式。后面的值可以是一个表达式。(2)函数值的类型。既然函数有返回值,应当在函数值的类型。既然函数有返回值,应当在定义函数时指定函数值的类型。定义函数时指定函数值的类型。(3)如果函数值的类型和如果函数值的类型和return语句中表达式的语句中表达式的值不一致,则以函数类型为准,即函数类型决定返值不一致,则以函数类型为准,即函数类型决定返回值的类型。对数值型数据,可以自动进行类型转回值的类型。对数值型数据,可以自动进行类型转换。换。4.3.2 函数的返回值函数的返回值(1)首先被调用的函数必须是已经存在的函数。首先被调用的函数必须是已经存在的函数。(2)如果使用库函数,一般还应该在本文件开头
12、如果使用库函数,一般还应该在本文件开头用用include命令将有关头文件命令将有关头文件“包含包含”到本文件中到本文件中来。来。(3)如果使用用户自己定义的函数,而该函数与如果使用用户自己定义的函数,而该函数与调用它的函数调用它的函数(即主调函数即主调函数)在同一个程序单位中在同一个程序单位中,且且位置在主调函数之后,则必须在调用此函数之前对位置在主调函数之后,则必须在调用此函数之前对被调用的函数作声明。被调用的函数作声明。所谓所谓函数声明函数声明(declare),就是在函数尚在未定就是在函数尚在未定义的情况下,事先将该函数的有关信息通知编译系义的情况下,事先将该函数的有关信息通知编译系统,
13、以便使编译能正常进行。统,以便使编译能正常进行。4.4 函数的调用函数的调用例例4.3 对被调用的函数作声明。对被调用的函数作声明。#include using namespace std;int main()float add(float x,float y);/对对add函数作声明函数作声明 float a,b,c;coutab;c=add(a,b);coutsum=cendl;return 0;float add(float x,float y)/定定义义add函数函数 float z;z=x+y;return(z);运行情况如下:运行情况如下:please enter a,b:123.
14、68 456.45 sum=580.13调用函数时需要一定的时间和空间的开销。图调用函数时需要一定的时间和空间的开销。图4.5表示函数调用的过程:表示函数调用的过程:图图4.5*4.5 内置函数内置函数C+提供一种提高效率的方法,即在编译时将提供一种提高效率的方法,即在编译时将所调用函数的代码直接嵌入到主调函数中,而不是所调用函数的代码直接嵌入到主调函数中,而不是将流程转出去。这种嵌入到主调函数中的函数称为将流程转出去。这种嵌入到主调函数中的函数称为内置函数内置函数(inline function),又称又称内嵌函数内嵌函数。在有些。在有些书中把它译成书中把它译成内联函数内联函数。指定内置函数
15、的方法很简单,只需在函数首行指定内置函数的方法很简单,只需在函数首行的左的左端加一个关键字端加一个关键字inline即可。即可。例例4.4 函数指定为内置函数。函数指定为内置函数。#include using namespace std;inline int max(int,int,int);/声明函数,注意左端有声明函数,注意左端有inlineint main()int i=10,j=20,k=30,m;m=max(i,j,k);coutmax=ma)a=b;/求求a,b,c中的最大者中的最大者 if(ca)a=c;return a;由于在定义函数时指定它为内置函数,因此编由于在定义函数时指
16、定它为内置函数,因此编译系统在遇到函数调用译系统在遇到函数调用“max(i,j,k)”时,时,就用就用max函数体的代码代替函数体的代码代替“max(i,j,k)”,同时将实同时将实参代替形参。参代替形参。这样,程序第这样,程序第6行行“m=max(i,j,k);”就被置换成就被置换成:if(ji)i=j;if(ki)i=k;m=i;注意使用条件注意使用条件:使用内置函数可以节省运行时间,但却增加了使用内置函数可以节省运行时间,但却增加了目标程序的长度。目标程序的长度。因此一般只将规模很小因此一般只将规模很小(一般为一般为5个语句以下个语句以下)而使用频繁的函数而使用频繁的函数(如定时采集数据
17、的如定时采集数据的函数函数)声明为内置函数。声明为内置函数。内置函数中不能包括复杂的控制语句,如循环内置函数中不能包括复杂的控制语句,如循环语句和语句和switch语句。语句。归纳起来,归纳起来,只有那些规模较小而又被频繁调用只有那些规模较小而又被频繁调用的简单函数,才适合于声明为的简单函数,才适合于声明为inlineinline函数。函数。在编程时,有时我们要实现的是同一类的功能,在编程时,有时我们要实现的是同一类的功能,只是有些细节不同。只是有些细节不同。int max1(int a,int b,int c);/求求3个整数中的最大者个整数中的最大者double max2(double a
18、,double b,double c);/求求3个双精度个双精度数中最大者数中最大者long max3(long a,long b,long c);/求求3个长整数中的最个长整数中的最大者大者C+允许用同一函数名定义多个函数,这些函允许用同一函数名定义多个函数,这些函数的参数个数和参数类型不同。这就是数的参数个数和参数类型不同。这就是函数的重载函数的重载(function overloading)。即对一个函数名重新赋予即对一个函数名重新赋予它新的含义,它新的含义,使一个函数名可以多用。使一个函数名可以多用。*4.6 函数的重载函数的重载对上面求最大数的问题可以编写如下的对上面求最大数的问题可
19、以编写如下的C+程序。程序。例例4.5 求求3个数中最大的数个数中最大的数(分别考虑整数、双精度分别考虑整数、双精度数、长整数的情况数、长整数的情况)。#include using namespace std;int main()int max(int a,int b,int c);/函数声明函数声明 double max(double a,double b,double c);long max(long a,long b,long c);/函数声明函数声明 int i1,i2,i3,i;cini1i2i3;/输输入入3个整数个整数 i=max(i1,i2,i3);/求求3个整数中的最大者个整
20、数中的最大者 couti_max=id1d2d3;/输输入入3个双精度数个双精度数 d=max(d1,d2,d3);/求求3个双精度数中的最大者个双精度数中的最大者 coutd_max=dg1g2g3;/输输入入3个个长长整数整数 g=max(g1,g2,g3);/求求3个个长长整数中的最大者整数中的最大者 coutg_max=ga)a=b;if(ca)a=c;return a;double max(double a,double b,double c)if(ba)a=b;if(ca)a=c;return a;long max(long a,long b,long c)if(ba)a=b;if
21、(ca)a=c;return a;运行情况如下:运行情况如下:185 -76 567 (输入输入3个整数个整数)56.87 90.23 -3214.78 (输入输入3个实数个实数)67854 -912456 673456 (输入输入3个长整数个长整数)i_max=567 (输出输出3个整数的最大值个整数的最大值)d_max=90.23 (输出输出3个双精度数的最大值个双精度数的最大值)g_max=673456 (输出输出3个长整数的最大值个长整数的最大值)上例上例3个个max函数的函数体是相同的,其实重载函数的函数体是相同的,其实重载函数并不要求函数体相同。函数并不要求函数体相同。重载函数除了
22、允许参数重载函数除了允许参数类型不同以外,还允许参数的个数不同。类型不同以外,还允许参数的个数不同。重载的规则:重载的规则:v参数的个数和类型可以都不同。但不能只有函数参数的个数和类型可以都不同。但不能只有函数的类型不同而参数的个数和类型相同。的类型不同而参数的个数和类型相同。v在使用重载函数时,同名函数的功能应当相同或在使用重载函数时,同名函数的功能应当相同或相近,不要用同一函数名去实现完全不相干的功能相近,不要用同一函数名去实现完全不相干的功能多次调用同一函数时用同样的实参,多次调用同一函数时用同样的实参,C+提供提供简单的处理办法,给形参一个默认值,这样形参就简单的处理办法,给形参一个默
23、认值,这样形参就不必一定要从实参取值了不必一定要从实参取值了。如有一函数声明。如有一函数声明float area(float r=6.5);指定指定r的默认值为的默认值为6.5,如果在调用此函数时,如果在调用此函数时,确认确认r的值为的值为6.5,则可以不必给出实参的值,如,则可以不必给出实参的值,如:area();/相当于相当于area(6.5);如果不想使形参取此默认值,则通过实参另行如果不想使形参取此默认值,则通过实参另行给出。如给出。如:*4.8 有默认参数的函数有默认参数的函数函数原型如下:函数原型如下:float volume(float h,float r=12.5);/只对形参
24、只对形参r指定默认值指定默认值12.5函数调用可以采用以下形式:函数调用可以采用以下形式:volume(45.6);/相当于相当于volume(45.6,12.5)volume(34.2,10.4)/h的值为的值为34.2,r的值为的值为10.4实参与形参的结合是从左至右顺序进行的。实参与形参的结合是从左至右顺序进行的。在在调调用一个函数的用一个函数的过过程中又出程中又出现现直接或直接或间间接地接地调调用用该该函数本身,称函数本身,称为为函数的函数的递归递归(recursive)(recursive)调调用。用。C+C+允允许许函数的函数的递归调递归调用。例如:用。例如:int f(int x
25、)int y,z;z=f(y);/在调用函数在调用函数f的过程中,又要调用的过程中,又要调用f函函数数 return(2*z)以上是直接以上是直接调调用本函数,用本函数,见图见图4.94.9。图图4.104.10表示的是表示的是间间接接调调用本函数。在用本函数。在调调用用f1f1函数函数过过程中要程中要调调用用f2f2函数,而在函数,而在调调用用f2f2函数函数过过程程中又要中又要调调用用f1f1函数函数。4.104.10 函数的函数的递归调递归调用用图4.9图4.10 从从图图上可以看到,上可以看到,这这两种两种递归调递归调用都是无用都是无终终止止的自身的自身调调用。用。显显然,程序中不然,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C程序设计 谭浩强 程序设计 课件
限制150内