资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第,4,章 函数,4.1,函数的定义和使用,4.2,函数的参数传递,4.3,函数的嵌套调用,4.4,函数的递归调用,4.5,内联函数,4.6,函数重载,4.7,带默认形参值的函数,4.8,函数的存储类别,4.1,函数的定义与使用,系统库函数:需要包含相应的头文件,如,#include,系统所提供的库函数都是完成一些通用功能的函数,在实际的程序设计中,自己还需要编写大量完成特殊功能的函数,我们称之为用户自定义函数。,4.1.1,函数的定义,函数定义的一般格式为:,函数类型 函数名(形式参数表),语句组,第,4,章 函数,函数头,函数体,例,4.1,求两个整数中较大的值的函数,#include,int,max(int,x,int,y);,void main(),int,a,b,c,;,cout,a b;,c=,max(a,b,);,cout,a,b,中较大的数是:,c y)m=x;,else m=y;,return m;,程序运行结果为:,请输入两个整数,用空格分隔:,20 30,a,b,中较大的数是:,30,第,4,章 函数,函数调用语句,主调函数,被调函数,4.1,函数的定义与使用,4.1.1,函数的定义(续一),1.,函数类型与返回值,函数的类型,就是函数返回值的类型,可以是,C+,中的任何数据类型。,函数的返回值,由函数体中的,return,语句给出。,return,语句的一般格式为:,return,(表达式);,或,return,表达式;,或,return,;,函数的类型要与,return,语句的返回值,类型相同,。若不一致则以函数类型为准,将返回值类型转换为函数类型,若不能转换,则编译过程会出错!,若函数不需要返回值,则应将类型指定为,void,。,第,4,章 函数,执行该语句时,不带回返回值,只是返回主调函数,4.1,函数的定义与使用,4.1.1,函数的定义(续二),2.,函数的参数,函数通过参数接收数据。,函数头中的参数为,形式参数,(或形参),在函数调用时给出的参数称为,实际参数,(或实参)。,实参必须是一个实际的值,而形参只有在发生实际调用时才有具体的值。,如果不需要为函数提供数据,则可以没有参数,称之为无参函数。,第,4,章 函数,4.1,函数的定义与使用,4.1.2,函数的声明与调用,函数调用的一般格式:,函数名(实际参数表),注意:,若无形参,也不必给出实参,但括号不能省略。,实参与形参个数应一致,类型要一一对应。,函数原型声明,:在调用函数前,对函数进行说明。通常用于函数定义出现在函数调用之后的情况。,函数原型声明的一般格式:,函数类型 函数名(形式参数表);,注意:,函数原型中可以不写出参数名。,如:,double,power(double,int,);,第,4,章 函数,例,4.2,编写一个求,x,的,n,次方的函数,#include,double,power(double,x,int,n);,void main(),double x;,int,n;,cout,x n;,cout,x ,的,n ,次方是:,power(x,n,),endl,;,double,power(double,x,int,n),double a=1.0;,int,i;,for(i,=1;i=n;i+),a*=x;,return a;,程序运行结果为:,请输入,X,和,N,的值,用空格分隔:,3.0 4,3,的,4,次方是:,81,第,4,章 函数,返 回,4.2,函数的参数传递,根据函数的功能,函数的形参可以选择为数值、引用或指针三种形式。,4.2.1,值传递,C+,中参数的传递是,单向,的,即,只能将实参的值传递给形参,,而,形参值的改变对实参没有影响,。,例,4.3,写一个函数交换主函数中两个变量的值,考虑:使用值传递,将需要交换的变量作为实参传递给函数的形参,在函数体中完成交换值的过程,这种做法能否实现程序要求?,第,4,章 函数,例,4.3,源程序,#include,void,swap(int,x,int,y);,void main(),int,a,b;,a=10;,b=20;,swap(a,b);,cout,a ,b,endl,;,程序运行结果为:,10,,,20,10,a,10,x,20,b,20,y,10,20,x,y,10,temp,20,20,x,y,10,temp,20,10,x,y,10,temp,void,swap(int,x,int,y),int,temp;,temp=x;,x=y;,y=temp;,第,4,章 函数,注意:值传递时,函数的实参与形参在内存中占用不同的存储空间,值只能由实参传递给形参,而形参的变化并不会影响实参。因此不能完成程序功能。,4.2,函数的参数传递,4.2.2,使用引用,1.,引用的概念,引用是一种特殊的变量,可以认为是一个变量的别名。,定义引用的一般格式,:,类型说明符,&,引用名 变量名;,如:,int,a=1;,int,首先定义变量,a,,并初始化为,1,,然后定义引用,b,,并初始化为,a,,即,b,是,a,的别名,因此,a,和,b,是同一个单元。,注意,:定义引用时一定要初始化,指明该引用变量是谁的别名。,第,4,章 函数,例,4.4,引用的使用,#include,void main(),int,a=1;,int,c=10;,int,cout,a ,b,c,endl,;,b=c;,cout,a ,b,c,endl,;,b=20;,cout,a ,b,c,endl,;,程序运行结果:,1,,,1,,,10,10,,,10,,,10,20,,,20,,,10,定义引用,b,,并将其作为,a,的别名,第,4,章 函数,将,c,的值赋给,b,,不是将,b,作为,c,的别名,4.2,函数的参数传递,4.2.2,使用引用(续一),2.,引用作为函数的参数,例,4.5,写一个函数,用引用作为参数,交换函数中两个变量的值。,第,4,章 函数,#include,void,swap(int,x,int,y);,void main(),int,a,b;,a=10;,b=20;,swap(a,b);,cout,a ,b,endl,;,void,swap(int,&x,int,&y),int,temp;,temp=x;,x=y;,y=temp;,程序运行结果为:,20,,,10,4.2,函数的参数传递,4.2.2,使用引用(续二),例,4.5,程序运行过程中参数值的变化图示,第,4,章 函数,10,a,x,b,y,20,a,x,b,y,10,temp,20,a,x,b,y,10,temp,10,a,x,b,y,10,temp,20,20,20,10,注意:引用作参数时,函数的实参与形参在内存中共用存储单元,因此形参的变化会使实参同时变化。,返 回,4.3,函数的嵌套调用,函数的,嵌套调用,是指,在执行被调用函数时,被调用函数又调用了其它函数。,嵌套调用的执行过程,:,第,4,章 函数,例,4.6,求,1!+2!+n!,#include,long f1(int n);,long f2(int m);,void main(),int,n;,long s;,cout,n;,s=f1(n);,cout,s,endl,;,第,4,章 函数,long f1(int n),/,求,1!+2!+,+,n!,int,i;,long sum=0;,for(i,=1;i=n;i+),sum+=f2(i);,return sum;,long f2(int m),/,求,m!,int,i;,long s=1;,for(i,=1;i=m;i+),s*=i;,return s;,程序运行结果:,请输入,n,的值:,5,153,例,4.7,输入两个整数,求平方和,#include,int,fun2(int m);,int,fun1(int,x,int,y);,void,main(void,),int,a,b,;,cout,a b;,cout,a,、,b,的平方和:,fun1(a,b)0,可以将求,n!,转化为求,(n-1)!,,再继续转化为求,(n-2)!,,到,1,时应停止递归,#include,long,power(int,n);,void main(),int,n;,long y;,cout,n;,y=,power(n,);,cout,n !=y 1),f=n*power(n-1);,else,f=1;,return f;,例,4.8,的递归过程分析,第,4,章 函数,例,4.9 Hanoi,塔问题,有三根针,A,、,B,、,C,,,A,针上有,n,个盘子,盘子大小不等,大的在下,小的在上,如图所示。要求将这,n,个盘子从,A,针移到,C,针,在移动过程中可以借助,B,针,每次只能移动一个盘子,并且在移动过程中三根针上的盘子都保持大盘在下,小盘在上。,分析:将,n,个盘子从,A,针移到,C,针可以分解为以下三个步骤:,(,1,)将,A,针上的,n-1,个盘子借助,C,针移到,B,针上;,(,2,)将,A,针上剩下的一个盘子移到,C,针上;,(,3,)将,B,针上的,n-1,个盘子借助,A,针移到,C,针上。,第,4,章 函数,A,B,C,n-1,个盘子的,Hanoi,问题,例,4.9 Hanoi,塔问题源程序,#include,void,Move(char,x,char y);,void,Hanoi(int,n,char one,char two,char three);,void main(),int,n;,cout,n;,cout,n ,个盘子的移动过程为:,endl,;,Hanoi(n,A,B,C);,/,函数,Move(),将一个盘子从,x,针移到,y,针,void,Move(char,x,char y),cout,y,endl,;,第,4,章 函数,例,4.9 Hanoi,塔问题源程序(续),/,函数,Hanoi(),将,n-1,个盘子从,one,针借助,two,针移到,three,针,void,Hanoi(int,n,char one,char two,char three),if(n,=1),Move(one,three);,else,Hanoi(n-1,one,three,two);,Move(one,three);,Hanoi(n-1,two,one,three);,第,4,章 函数,程序运行结果:,A,C,A,B,C,B,A,C,B,A,B,C,A,C,返 回,运行演示,4.5,内联函数,内联函数,与一般函数的区别在于它不是在调用时发生控制转移,而是在编译时将被调函数体嵌入到每一个函数调用处,节省了参数传递、控制转移等开销。对于一些规模较小、频繁调用的函数可声明为内联函数,能提高程序运行效率。,内联函数的定义,:,inline,类型说明符 函数名(参数及类型表),函数体,注意:,只有简单的函数才能成为内联函数,如函数体中不能有循环语句和,switch,语句等。,内联函数的定义必须出现在内联函数第一次被调用之前。,第,4,章 函数,例,4.10,使用内联函数,#include,inline,int,Add(int,a,int,b),int,x;,x=,a+b,;,return x;,第,4,章 函数,程序运行结果:,10+20=30,10+50=60,50+50=100,返 回,void main(),int,a,b,c;,a=10;,b=20;,c=,Add(a,b,);,cout,a +b =c,endl,;,c=Add(a,50);,cout,a +50 =c,endl,;,c=Add(50,50);,cout,50+50 =c,endl,;,4.6,函数重载,在,C+,中可以定义多个相同名字的函数,只要它们,形参的个数或类型不完全一致,即可,编译程序根据实参与形参的类型及个数自动确定调用哪一个同名函数,这就是,函数重载,,这些同名函数称为,重载函数,。,例,4.12,定义两个函数,分别求两个整数及两个实数的最大值。,分析:在,C,语言中,要定义题中的函数,只能使用两个不同名函数实现,即定义,int,max1(int x,int,y),double max2(double x,double y),在,C+,中,可通过定义两个重载函数实现,二者同名,如下:,int,max(int,x,int,y),double,max(double,x,double y),第,4,章 函数,例,4.12,源程序,#include,int,max(int,x,int,y);,double,max(double,x,double y);,void main(),int,a=10,b=20,c;,double x=200.3,y=400.6,z;,c=,max(a,b,);,z=,max(x,y,);,cout,c z,endl,;,第,4,章 函数,程序运行结果:,int,function,float function,20,400.6,返 回,int,max(int,x,int,y),cout,int,function y)return x;,else return y;,double,max(double,x,double y),cout,float function y)return x;,else return y;,4.7,带默认参数值的函数,4.7.1,带默认参数值的函数,在函数的声明或定义中可以预先给出默认的形参值,函数调用时,按,从左到右,的次序将实参和形参结合,如给出对应的实参,则采用实参值,否则采用预先给出的默认形参值。,例,4.13,使用带默认参数值的函数求,x,的,n,次方(,n,是正整数)。,第,4,章 函数,#include,double,power(double,x=10.0,int,n=2);,void main(),cout,power(3,5),endl,;,cout,power(3),endl,;,cout,power(),endl,;,double,power(double,x,int,n),int,i;,double s=1.0;,for(i,=1;i=n;i+),s*=x;,return s;,4.7,带默认参数值的函数,4.7.1,带默认参数值的函数(续),注意:,默认形参值必须,由右向左,的顺序定义。如果某个参数有默认值,则其右面的参数必须都有默认值;如果某个参数没有默认值,则其左面的参数都不能有默认值。例如:,int,max(int,a,int,b=10,int,c=20);/,正确,int,max(int,a,int,b=10,int,c);/,错误,int,max(int,a=5,int,b,int,c=30);/,错误,在后两种情况下,调用语句,x=max(20,30);,会出错!,注意:,在使用带默认参数值的函数时,只能在函数定义或函数声明中的一个位置给出默认值,不能在两个位置同时给出。还要保证在,函数调用之前给出默认值,。,第,4,章 函数,4.7,带默认参数值的函数,4.7.2,带默认参数值函数产生的二义性,例,4.14,程序,第,4,章 函数,#include,int,add(int,x=5,int,y=6);,float,add(int,x=5,float y=10.0);,void main(),int,a;,float b;,a=add(10,20);,b=add(10);,cout,a=a,endl,;,cout,b=b,endl,;,int,add(int,x,int,y),return,x+y,;,float,add(int,x,float y),return,x+y,;,b=add(10),语句产生二义性,可以认为该语句是调用第一个函数,也可以是第二个,因此编译器不能确定调用的是哪一个函数。,返 回,4.8,变量的存储类别,4.8.1,内部变量与外部变量,1.,内部变量,在一个函数内部定义的变量是内部变量(也称为局部变量),它只在该函数范围内有效。,例如,:,第,4,章 函数,void f1(int a),int,b,c,;,void main(),int,m,n,;,a,b,c,的有效范围,m,n,的有效范围,int,i,a,;,for(i,=0;i10;i+),int,b,;,b,的有效范围,注意:在不同的作用范围内允许声明同名的变量,4.8,变量的存储类别,4.8.1,内部变量与外部变量(续),2.,外部变量,在函数外部定义的变量是外部变量(也称为全局变量),它不属于任何一个函数。它的作用范围是:从外部变量的定义位置开始,到本文件的结尾。,例如,:,第,4,章 函数,int,a,b,;,void f1(),int,x,y,;,void main(),x,y,的有效范围,a,b,的有效范围,例,4.15,使用全局变量和局部变量,#include,int,i=1;,/,全局变量,文件作用域,void main(),cout,全局变量,i=i,endl,;,/,输出,1,int,i=5;,/,函数局部变量,块作用域,int,i;,/,块局部变量,块作用域,i=7;,cout,块局部变量,i=i,endl,;,/,输出,7,cout,全局变量,i=:i,endl,;,/,输出,1,,,:,使用全局变量,cout,函数局部变量,i=i,endl,;,/,输出,5,cout,全局变量,i=:i,endl,;,/,输出,1,,,:,使用全局变量,第,4,章 函数,程序运行结果:,全局变量,i=1,块局部变量,i=7,全局变量,i=1,函数局部变量,i=5,全局变量,i=1,4.8,变量的存储类别,4.8.2,变量的存储类别,变量在内存中的存储方式可以分为两大类,即,静态存储方式,与,动态存储方式,。,静态存储方式,是指在程序运行期间,分配固定的存储空间。,全局变量,和,静态局部变量,是静态存储方式。,动态存储方式,是在程序执行过程中,根据需要动态地分配存储空间。,局部变量,是动态存储方式。,1.,静态变量,定义形式,:,static,数据类型 变量名,特点:,程序运行过程中变量始终存在,每次调用函数结束的值都被保留下来。,仅初始化一次,每次调用它所在的函数时,不再重新初始化。若不指定初值,自动指定初值为,0,。,第,4,章 函数,例,4.16,输出,14,的阶乘,#include,int,fact(,int,n);,void main(),int,i;,for(i,=1;i=4;i+),cout,i !=,fact(i,),endl,;,int,fact(int,n),static,int,f=1;,/,仅在第一次调用函数时执行一次,f*=n;,return f;,第,4,章 函数,程序运行结果:,1!=1,2!=2,3!=6,4!=24,4.8,变量的存储类别,4.8.2,变量的存储类别(续),2.,自动变量,定义形式,:,auto,数据类型 变量名,特点:,定义变量时,若不指定,static,或,auto,,则默认为自动变量。自动变量是,动态存储方式,。,每次调用它所在的函数时,都要重新分配存储空间,并初始化。函数调用结束,存储空间就释放。,若不初始化,则初值是不确定的。,第,4,章 函数,例,4.17,静态变量与动态变量的使用,#include,void,other(void,);,int,i=1;,/i,为全局变量,具有静态生存期。,void,main(void,),static,int,a;,/a,为静态局部变量,具有全局寿命,局部可见。,int,b=-10;,/b,c,为动态局部变量,具有局部生存期。,int,c=0;,cout,-MAIN-n;,cout,i:i a:a b:b c:c,endl,;,c=c+8;,other();,cout,-MAIN-n;,cout,i:i a:a b:b c:c,endl,;,i=i+10;,other();,第,4,章 函数,例,4.17,静态变量与动态变量的使用,(,续,),void,other(void,),/,a,b,为静态局部变量,具有全局寿命,局部可见,,/,只第一次进入函数时被初始化。,static,int,a=2;,static,int,b;,int,c=10;,/C,为动态局部变量,每次进入函数时都初始化。,a=a+2;,i=i+32;,c=c+5;,cout,-OTHER-n;,cout,i:i a:a b:b c:c,endl,;,b=a;,第,4,章 函数,程序运行结果:,-MAIN-,i:1 a:0 b:-10 c:0,-OTHER-,i:33 a:4 b:0 c:15,-MAIN-,i:33 a:0 b:-10 c:8,-OTHER-,i:75 a:6 b:4 c:15,例,4.18,输出摄氏温度与华氏温度对照表,分析:编写一个函数求出指定摄氏温度对应的华氏温度值,在主函数中通过循环求出摄氏温度从,099,度对应的华氏温度值,并输出。转换公式为:,F=9/5*C+32,其中,F,表示华氏温度,,C,为摄氏温度。程序如下:,#include,#include,int,Convert(int,c),int,f;,f=(,int,)(9.0/5*c+32);,return f;,第,4,章 函数,例,4.18,(续一),#,void main(),cout,|0 1 2 3 4 5 6 7 8 9,endl,;,cout,-|-,endl,;,for(int,i=0;i10;i+),cout,setw(2)i*10|;,for(int,j=0;j10;j+),cout,setw(3),Convert(i,*10+j);,cout,0,第,4,章 函数,例,4.19,(续),#include,int,comm(int,n,int,k);,void,main(void,),int,n,k;,cout,n k;,cout,comm(n,k,)n),return 0;,else,if(n,=k)|(k=0),return 1;,else,return comm(n-1,k)+comm(n-1,k-1);,第,4,章 函数,返 回,程序运行结果:,请输入,n,和,k,的值:,10 3,120,谢 谢!,
展开阅读全文