《第3章C程序设计教程与实验指导杨国兴函数》由会员分享,可在线阅读,更多相关《第3章C程序设计教程与实验指导杨国兴函数(29页珍藏版)》请在金锄头文库上搜索。
1、C+语言程序设计杨国兴张东玲彭涛中国水利水电出版社第3章函数3.1函数的递归调用3.2内联函数3.3函数重载3.4带默认参数值的函数3.5变量的存储类别3.6程序实例3.1 函数的递归调用一个函数在它的函数体内,一个函数在它的函数体内,直接或间接地调用它自身直接或间接地调用它自身,称为,称为递递归调用归调用。这种函数称为。这种函数称为递归函数递归函数。直接或间接调用函数自身的情况如图直接或间接调用函数自身的情况如图直接或间接调用函数自身的情况如图直接或间接调用函数自身的情况如图:第3章 函数f函数调用f函数f1函数调用f2函数f2函数调用f1函数直接调用间接调用这两种递归调用都是无中止地调用自
2、身,显然是不正确的。为了这两种递归调用都是无中止地调用自身,显然是不正确的。为了防止递归调用无终止地进行,必须在函数内有防止递归调用无终止地进行,必须在函数内有终止递归调用的手段终止递归调用的手段。例3.1用递归的方法求n!分析:计算分析:计算分析:计算分析:计算n!n!的公式为的公式为的公式为的公式为:1n=11n=1或或或或 0 0y=y=n*(n-1)!n1n*(n-1)!n1可以将求可以将求可以将求可以将求n!n!转化为求转化为求转化为求转化为求(n-1)!(n-1)!,再继续转化为求,再继续转化为求,再继续转化为求,再继续转化为求(n-2)!(n-2)!,到,到,到,到1 1时应停止
3、递归时应停止递归时应停止递归时应停止递归#includeusingnamespacestd;longpower(intn);voidmain()intn;longy;coutn;y=power(n);coutn!=y1)f=n*power(n-1);elsef=1;returnf;例3.1的递归过程分析第3章 函数例3.2Hanoi塔问题有三根针有三根针A A、B B、C C,A A针上有针上有n n个盘子,盘子大小不等,大的个盘子,盘子大小不等,大的在下,小的在上,如图所示。要求将这在下,小的在上,如图所示。要求将这n n个盘子从个盘子从A A针移到针移到C C针,针,在移动过程中可以借助在
4、移动过程中可以借助B B针,每次只能移动一个盘子,并且在移针,每次只能移动一个盘子,并且在移动过程中三根针上的盘子都保持大盘在下,小盘在上。动过程中三根针上的盘子都保持大盘在下,小盘在上。分析:将分析:将n n个盘子从个盘子从A A针移到针移到C C针可以分解为以下三个步骤:针可以分解为以下三个步骤:(1 1)将)将A A针上的针上的n-1n-1个盘子借助个盘子借助C C针移到针移到B B针上;针上;(2 2)将)将A A针上剩下的一个盘子移到针上剩下的一个盘子移到C C针上;针上;(3 3)将)将B B针上的针上的n-1n-1个盘子借助个盘子借助A A针移到针移到C C针上。针上。第3章 函
5、数ABCn-1n-1个盘子的个盘子的个盘子的个盘子的HanoiHanoi问题问题问题问题例3.2Hanoi塔问题源程序#includeusingnamespacestd;voidMove(charx,chary);voidHanoi(intn,charone,chartwo,charthree);voidmain()intn;coutn;coutn个盘子的移动过程为:endl;Hanoi(n,A,B,C);/函数Move()将一个盘子从x针移到y针voidMove(charx,chary)coutxyendl;第3章 函数例3.2Hanoi塔问题源程序(续)/函数Hanoi()将n-1个盘子从
6、one针借助two针移到three针voidHanoi(intn,charone,chartwo,charthree)if(n=1)Move(one,three);elseHanoi(n-1,one,three,two);Move(one,three);Hanoi(n-1,two,one,three);第3章 函数程序运行结果:程序运行结果:A AC CA AB BC CB BA AC CB BA AB BC CA AC C 返 回运行演示运行演示3.2 内联函数内联函数内联函数与一般函数的区别在于它不是在调用时发生控制转移与一般函数的区别在于它不是在调用时发生控制转移,而是在编译时将被调函数
7、体嵌入到每一个函数调用处,节省了,而是在编译时将被调函数体嵌入到每一个函数调用处,节省了参数传递、控制转移等开销。对于一些规模较小、频繁调用的函参数传递、控制转移等开销。对于一些规模较小、频繁调用的函数可声明为内联函数,能提高程序运行效率。数可声明为内联函数,能提高程序运行效率。内联函数的定义内联函数的定义内联函数的定义内联函数的定义:inlineinline 类型说明符类型说明符 函数名(参数及类型表)函数名(参数及类型表) 函数体函数体 注意:注意:只有简单的函数才能成为内联函数,如函数体中不能有只有简单的函数才能成为内联函数,如函数体中不能有循环语句和循环语句和switchswitch语
8、句等。语句等。内联函数的定义必须出现在内联函数第一次被调用之前。内联函数的定义必须出现在内联函数第一次被调用之前。 第3章 函数例3.3使用内联函数#includeusingnamespacestd;inlineintAdd(inta,intb)intx;x=a+b;returnx;第3章 函数程序运行结果:程序运行结果:10+20=3010+20=3010+50=6010+50=6050+50=10050+50=100 返 回voidmain()inta,b,c;a=10;b=20;c=Add(a,b);couta+b=cendl;c=Add(a,50);couta+50=cendl;c=A
9、dd(50,50);cout50+50=cendl; 3.3 函数重载在在C+C+中可以定义多个相同名字的函数,只要它们中可以定义多个相同名字的函数,只要它们形参的个形参的个数或类型不完全一致数或类型不完全一致即可,编译程序根据实参与形参的类型及个即可,编译程序根据实参与形参的类型及个数自动确定调用哪一个同名函数,这就是数自动确定调用哪一个同名函数,这就是函数重载函数重载,这些同名函,这些同名函数称为数称为重载函数重载函数。 例例3.43.4 定义两个函数,分别求两个整数及两个实数的最大值。定义两个函数,分别求两个整数及两个实数的最大值。分析:在分析:在C C语言中,要定义题中的函数,只能使用
10、两个不同名语言中,要定义题中的函数,只能使用两个不同名函数实现,即定义函数实现,即定义intintmax1(intx,max1(intx,intinty)y)doublemax2(doublex,doubley)doublemax2(doublex,doubley)在在C+C+中,可通过定义两个重载函数实现,二者同名,如下:中,可通过定义两个重载函数实现,二者同名,如下:intintmax(intmax(intx,x,intinty)y)doubledoublemax(doublemax(doublex,doubley)x,doubley)第3章 函数例3.5源程序#includeusingn
11、amespacestd;intmax(intx,inty);doublemax(doublex,doubley);voidmain()inta=10,b=20,c;doublex=200.3,y=400.6,z;c=max(a,b);z=max(x,y);coutczendl; 第3章 函数程序运行结果:程序运行结果:intintfunctionfunctionfloatfunctionfloatfunction20,400.620,400.6 返 回intmax(intx,inty)coutintfunctiony)returnx;elsereturny;doublemax(doublex,
12、doubley)coutfloatfunctiony)returnx;elsereturny; 3.4 带默认参数值的函数3.4.1带默认参数值的函数在函数的声明或定义中可以预先给出默认的形参值,函数调用在函数的声明或定义中可以预先给出默认的形参值,函数调用时,按时,按从左到右从左到右的次序将实参和形参结合,如给出对应的实参,的次序将实参和形参结合,如给出对应的实参,则采用实参值,否则采用预先给出的默认形参值则采用实参值,否则采用预先给出的默认形参值 。例例3.63.6使用带默认参数值的函数求使用带默认参数值的函数求x x的的n n次方(次方(n n是正整数)。是正整数)。 第3章 函数#in
13、cludeusingnamespacestd;doublepower(doublex=10.0,intn=2);voidmain()coutpower(3,5)endl;coutpower(3)endl;coutpower()endl;doublepower(doublex,intn)inti;doubles=1.0;for(i=1;i=n;i+)s*=x;returns;3.4 带默认参数值的函数3.4.1带默认参数值的函数(续)注意:注意:默认形参值必须默认形参值必须由右向左由右向左的顺序定义。如果某个参数有的顺序定义。如果某个参数有默认值,则其右面的参数必须都有默认值;如果某个参数没有默
14、默认值,则其右面的参数必须都有默认值;如果某个参数没有默认值,则其左面的参数都不能有默认值。例如:认值,则其左面的参数都不能有默认值。例如:intint max(intmax(inta,a,intintb=10,b=10,intintc=20);/c=20);/正确正确intint max(intmax(inta,a,intintb=10,b=10,intintc);/c);/错误错误intint max(intmax(inta=5,a=5,intintb,b,intintc=30);/c=30);/错误错误在后两种情况下,调用语句在后两种情况下,调用语句 x=max(20,30);x=max
15、(20,30);会出错!会出错!注意:注意:在使用带默认参数值的函数时,只能在函数定义或函数在使用带默认参数值的函数时,只能在函数定义或函数声明中的一个位置给出默认值,不能在两个位置同时给出。还要声明中的一个位置给出默认值,不能在两个位置同时给出。还要保证在保证在函数调用之前给出默认值函数调用之前给出默认值。第3章 函数3.4 带默认参数值的函数3.4.2带默认参数值函数产生的二义性例例3.73.7程序程序第3章 函数#includeusingnamespacestd;intadd(intx=5,inty=6);floatadd(intx=5,floaty=10.0);voidmain()in
16、ta;floatb;a=add(10,20);b=add(10);couta=aendl;coutb=bendl;intadd(intx,inty)returnx+y;floatadd(intx,floaty)returnx+y;b=add(10)b=add(10)语句产生二义性,可以认为该语句是调用第一个函数,也可以语句产生二义性,可以认为该语句是调用第一个函数,也可以语句产生二义性,可以认为该语句是调用第一个函数,也可以语句产生二义性,可以认为该语句是调用第一个函数,也可以是第二个,因此编译器不能确定调用的是哪一个函数。是第二个,因此编译器不能确定调用的是哪一个函数。是第二个,因此编译器不
17、能确定调用的是哪一个函数。是第二个,因此编译器不能确定调用的是哪一个函数。 返 回3.5 变量的存储类别3.5.1内部变量与外部变量1.1. 内部变量内部变量内部变量内部变量在一个函数内部定义的变量是内部变量(也称为局部变量),在一个函数内部定义的变量是内部变量(也称为局部变量),它只在该函数范围内有效。它只在该函数范围内有效。 例如例如: : 第3章 函数voidf1(inta)intb,c;voidmain()intm,n;a,b,ca,b,c的有效范围的有效范围的有效范围的有效范围m,nm,n的有效范围的有效范围的有效范围的有效范围inti,a;for(i=0;i10;i+)intb;b
18、 b的有效范围的有效范围的有效范围的有效范围注意:在不同的作用范围内允许声明同名的变量注意:在不同的作用范围内允许声明同名的变量注意:在不同的作用范围内允许声明同名的变量注意:在不同的作用范围内允许声明同名的变量3.5 变量的存储类别3.5.1内部变量与外部变量(续)2.2. 外部变量外部变量外部变量外部变量在函数外部定义的变量是外部变量(也称为全局变量),它不在函数外部定义的变量是外部变量(也称为全局变量),它不属于任何一个函数。它的作用范围是:从外部变量的定义位置开属于任何一个函数。它的作用范围是:从外部变量的定义位置开始,到本文件的结尾。始,到本文件的结尾。 例如例如: : 第3章 函数
19、inta,b;voidf1()intx,y;voidmain()x,yx,y的有效范围的有效范围的有效范围的有效范围a,ba,b的有效范围的有效范围的有效范围的有效范围例3.8使用全局变量和局部变量#includeusingnamespacestd;inti=1;/全局变量,文件作用域voidmain()cout全局变量i=iendl;/输出1inti=5;/函数局部变量,块作用域inti;/块局部变量,块作用域i=7;cout块局部变量i=iendl;/输出7cout全局变量i=:iendl;/输出1,:使用全局变量cout函数局部变量i=iendl;/输出5cout全局变量i=:iendl
20、;/输出1,:使用全局变量第3章 函数程序运行结果:程序运行结果:全局变量全局变量 i=1i=1块局部变量块局部变量 i=7i=7全局变量全局变量 i=1i=1函数局部变量函数局部变量 i=5i=5全局变量全局变量 i=1i=13.5 变量的存储类别3.5.2变量的存储类别变量在内存中的存储方式可以分为两大类,即变量在内存中的存储方式可以分为两大类,即静态存储方式静态存储方式与与动态存储方式动态存储方式。静态存储方式静态存储方式是指在程序运行期间,分配固定的存储空间。是指在程序运行期间,分配固定的存储空间。全全局变量局变量和和静态局部变量静态局部变量是静态存储方式。是静态存储方式。动态存储方式
21、动态存储方式是在程序执行过程中,根据需要动态地分配存储是在程序执行过程中,根据需要动态地分配存储空间。空间。局部变量局部变量是动态存储方式。是动态存储方式。 1.1. 静态变量静态变量静态变量静态变量定义形式定义形式: :staticstatic数据类型数据类型变量名变量名特点:特点:程序运行过程中变量始终存在,每次调用函数结束的值程序运行过程中变量始终存在,每次调用函数结束的值都被保留下来。都被保留下来。仅初始化一次,每次调用它所在的函数时,不再重新初始化。仅初始化一次,每次调用它所在的函数时,不再重新初始化。若不指定初值,自动指定初值为若不指定初值,自动指定初值为0 0。第3章 函数例8.
22、9输出14的阶乘#includeusingnamespacestd;intfact(intn);voidmain()inti;for(i=1;i=4;i+)couti!=fact(i)endl;intfact(intn)staticintf=1;/仅在第一次调用函数时执行一次f*=n;returnf;第3章 函数程序运行结果:程序运行结果:1!=11!=12!=22!=23!=63!=64!=244!=243.5 变量的存储类别3.5.2变量的存储类别(续)2.2. 自动变量自动变量自动变量自动变量定义形式定义形式: :autoauto数据类型数据类型变量名变量名特点:特点:定义变量时,若不指
23、定定义变量时,若不指定staticstatic或或autoauto,则默认为自动变,则默认为自动变量。自动变量是量。自动变量是动态存储方式动态存储方式。 每次调用它所在的函数时,都要重新分配存储空间,并初始化每次调用它所在的函数时,都要重新分配存储空间,并初始化。函数调用结束,存储空间就释放。函数调用结束,存储空间就释放。若不初始化,则初值是不确定的。若不初始化,则初值是不确定的。第3章 函数例3.10静态变量与动态变量的使用#includeusingnamespacestd;voidother(void);inti=1;/i为全局变量,具有静态生存期。voidmain(void)static
24、inta;/a为静态局部变量,具有全局寿命,局部可见。intb=-10;/b,c为动态局部变量,具有局部生存期。intc=0;cout-MAIN-n;couti:ia:ab:bc:cendl;c=c+8;other();cout-MAIN-n;couti:ia:ab:bc:cendl;i=i+10;other(); 第3章 函数例3.10静态变量与动态变量的使用(续)voidother(void)/a,b为静态局部变量,具有全局寿命,局部可见,/只第一次进入函数时被初始化。staticinta=2;staticintb;intc=10;/C为动态局部变量,每次进入函数时都初始化。a=a+2;i
25、=i+32;c=c+5;cout-OTHER-n;couti:ia:ab:bc:cendl;b=a; 第3章 函数程序运行结果:程序运行结果:-MAIN-MAIN-i:1a:0b:-10c:0i:1a:0b:-10c:0-OTHER-OTHER-i:33a:4b:0c:15i:33a:4b:0c:15-MAIN-MAIN-i:33a:0b:-10c:8i:33a:0b:-10c:8-OTHER-OTHER-i:75a:6b:4c:15i:75a:6b:4c:15例3.11输出摄氏温度与华氏温度对照表分析:编写一个函数求出指定摄氏温度对应的华氏温度值,分析:编写一个函数求出指定摄氏温度对应的华氏
26、温度值,在主函数中通过循环求出摄氏温度从在主函数中通过循环求出摄氏温度从099099度对应的华氏温度对应的华氏温度值,并输出。转换公式为:度值,并输出。转换公式为:F=9/5*C+32F=9/5*C+32其中其中F F表示华氏温度,表示华氏温度,C C为摄氏温度。程序如下:为摄氏温度。程序如下: #include#include #include#includeusingnamespacestd;intint Convert(intConvert(intc)c) intintf;f;f=(f=(intint)(9.0/5*c+32);)(9.0/5*c+32);returnf;returnf;
27、 第3章 函数例3.11(续一)# #voidmain()voidmain() coutcout|0123456789|0123456789endlendl; ;coutcout-|-|-endlendl; ;for(intfor(inti=0;i10;i+)i=0;i10;i+) coutcoutsetw(2)i*10|;setw(2)i*10|;for(intfor(intj=0;j10;j+)j=0;j10;j+) coutcoutsetw(3)setw(3)Convert(iConvert(i*10+j);*10+j); coutcout0k0第3章 函数例3.12(续)#includ
28、e#include usingnamespacestd;intint comm(intcomm(intn,n,intintk);k);voidvoidmain(voidmain(void) ) intintn,k;n,k;coutcoutnk;nk;coutcoutcomm(n,kcomm(n,k)n)n)return0;return0;elseelseif(nif(n=k)|(k=0)=k)|(k=0)return1;return1;elseelsereturncomm(n-1,k)+comm(n-1,k-1);returncomm(n-1,k)+comm(n-1,k-1); 第3章 函数 返 回程序运行结果:程序运行结果:请输入请输入请输入请输入n n n n和和和和k k k k的值:的值:的值:的值:10 310 310 310 3120120120120谢谢!