1、函数的概述
C源程序是由函数组成的。虽然在前面各章的程序中大都只有一个主函数main(),但实用程序往往由多个
函数组成。函数是C源程序的基本模块,通过对函数模块的调用实现特定的功能。
C语言不仅ᨀ供了极为丰富的库函数(如Turbo C,MS C都ᨀ供了三百多个库函数),还允许用户建立自己
定义的函数。用户可把自己的算法编成一个个相对独立的函数模块,然后用调用的方法来使用函数。可以说C
程序的全部工作都是由各式各样的函数完成的,所以也把C语言称为函数式语言。
2、函数的分类
在C语言中可从不同的角度对函数分类。
1) 从函数定义的角度看,函数可分为库函数和用户定义函数两种。
库函数:由C系统ᨀ供,用户无须定义,也不必在程序中作类型说明,只需在程序前包含有该函数原型的
头文件即可在程序中直接调用。在前面各章的例题中反复用到printf、scanf、getchar、putchar、gets、puts、strcat等函数均属此类。
用户定义函数:由用户按需要写的函数。对于用户自定义函数,不仅要在程序中定义函数本身,而且在主调函数模块中还必须对该被调函数进行类型说明,然后才能使用。
2) 语言的函数兼有其它语言中的函数和过程两种功能,从这个角度看,又可把函数分为有返回值函数和无
返回值函数两种。
有返回值函数:此类函数被调用执行完后将向调用者返回一个执行结果,称为函数返回值。如数学函数即属于此类函数。由用户定义的这种要返回函数值的函数,必须在函数定义和函数说明中明确返回值的类型。
无返回值函数:此类函数用于完成某项特定的处理任务,执行完成后不向调用者返回函数值。这类函数类似于其它语言的过程。由于函数无须返回值,用户在定义此类函数时可指定它的返回为“空类型”,空类型的说明符为“void”。
3) 从主调函数和被调函数之间数据传送的角度看又可分为无参函数和有参函数两种。
无参函数:函数定义、函数说明及函数调用中均不带参数。主调函数和被调函数之间不进行参数传送。此类函数通常用来完成一组指定的功能,可以返回或不返回函数值。
有参函数:也称为带参函数。在函数定义及函数说明时都有参数,称为形式参数(简称为形参)。在函数调用时也必须给出参数,称为实际参数(简称为实参)。进行函数调用时,主调函数将把实参的值传送给形参,供被调函数使用。
4) C语言ᨀ供了极为丰富的库函数,这些库函数又可从功能角度作以下分类
字符类型分类函数、转换函数、目录路径函数、诊断函数、图形函数、输入输出函数、接口函数、字符串函数、内存管理函数数学函数、日期和时间函数、进程控制函数、其它函数。
3、函数的定义
①无参无返回值
一般形式如下:
void 函数名(){
声明部分 //定义局部变量
语句
}
Void 无返回值函数:此类函数用于完成某项特定的处理任务,执行完后不向调用者返回执行结果,这类函数类似于其他语言的过程;由于函数无返回值,用户在定义此类函数时可指定其函数返回值为“空类型”
②有参无返回值
一般形式如下:
void 函数名(形式参数表列){
声明部分
语句
}
形式参数表列表的格式:类型 变量名,类型 变量2,…….
③无参有返回值函数定义
一般形式如下:
返回值类型 函数名(){
声明部分
语句
return 返回值类型变量或常量; //返回给主调函数
}
④有参有返回值函数定义
一般形式如下:
返回值类型 函数名(形式参数表列){
声明部分
语句
return 返回值类型变量或常量;
}
注意:定义函数时注意函数名不能重复
4、函数参数
①、形式参数
定义函数的时候,函数名后面小括号中的参数,简称形参形式参数是什么样类型的数据,那么实际参数也必须是什么样的类型函数内部不可以定义与函数形参同名的变量,因为形参与函数的代码是一个代码块
②、实际参数
调用函数的时候,函数名后面小括号中的参数,简称实参实参出现在主调函数中,进入被调函数后,实参变量也不能使用。形参和实参的功能是作数值的传递。发生函数调用时,主调函数把实参的值传送给被调函数的形参从而实现主调函数向被调函数的数据传送。
③函数形参和实参的传值过程
1)形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只有在函数内部有效。函数调用结束返回主调函数后则不能再使用该形参变量。
2)实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使实参获得确定值。
3)实参和形参在数量上,类型上,顺序上应严格一致,否则会发生类型不匹配”的错误。
5、函数的返回值
①、函数的返回值
函数的值(或称函数返回值)是指函数被调用之后,执行函数体中的程序段所取得的返回给主调函数的值。
②使用注意
1) 函数的值只能通过return语句返回主调函数。
return语句的一般形式为:return 表达式;
或者为:return (表达式);
该语句的功能是计算表达式的值,并返回给主调函数。在函数中允许有多个return语句,但每次调用只能有一个return 语句被执行,因此只能返回一个函数值。
2) 函数返回值的类型和函数定义中函数的类型应保持一致。如果两者不一致,则以函数类型为准,自动进行类型转换。
3) 如函数值为整型,在函数定义时可以省去类型说明。也就是说如果没有指定返回类型,那么C语言默认是int的类型(开发中不要省略返回值类型)
4) 不返回函数值的函数,可以明确定义为“空类型”,类型说明符为“void”。为了使程序有良好的可读性并减少出错, 凡不要求返回值的函数都应定义为空类型。
6、函数的调用
①、函数的声明
在主调函数中调用某函数之前应对该被调函数进行说明(声明),这与使用变量之前要先进行变量说明是一样的。
在主调函数中对被调函数作说明的目的是使编译系统知道被调函数返回值的类型,以便在主调函数中按此种类型对返回值作相应的处理。其一般形式为:
返回值类型 被调函数名( 类型 形参, 类型 形参… );
或为:
返回值类型 被调函数名( 类型, 类型…);
如:
int max( int a, int b );
int max( int, int );
注意:
1) 如果被调函数的返回值是整型或字符型时,可以不对被调函数作说明,而直接调用。这时系统将自动对被调函数返回值按整型处理。
如:
Int main()
{
Intz=0;
Z=max(33,44);
printf(“%d\n”,z);
printf(“%d\n”,max(11,82));
return0;
}
Int max(int num1,int num2){
Returnnum1>num2?num1:num2;
}
2) 当被调函数的函数定义出现在主调函数之前时,在主调函数中也可以不对被调函数再作说明而直接调用。
如:
Int max(int num1,int num2){
Returnnum1>num2?num1:num2;
}
Int main()
{
Intz=0;
printf(“%d\n”,z);
printf(“%d\n”,max(11,82));
return0;
}
②、函数的调用
1) 函数表达式
函数作为表达式中的一项出现在表达式中,以函数返回值参与表达式的运算这种方式要求函数是有返回值的。
int z=0;
z = max(23,80)+1;
2) 函数语句
函数调用的一般形式加上分号即构成函数语句。
printf("%d",a);
scanf("%d",&b);
3) 函数实参
函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的。
printf("%d\n",max(20, 30));
③、函数的嵌套调用
C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用。这样就出现了函数的嵌套调用。即在被调函数中又调用其它函数。这与其它语言的子程序嵌套的情形是类似的。
7、递归函数
①递归函数概述及用法
一个函数在它的函数体内调用它自身称为递归调用。这种函数称为递归函数。C语言允许函数的递归调用。在递归调用中,主调函数又是被调函数。执行递归函数将反复调用其自身,每调用一次就进入新的一层
如:
Int f(intx){
Int y;
Z=f(y);
Return z;
}
这个函数是一个递归函数。但是运行该函数将无休止地调用其自身,这当然不正确的。为了防止递归调用无终止地进行,必须在函数内有终止递归调用的手段。用的办法是加条件判断,满足某种条件后就不再作递归调用,然后逐层返回。
②、递归函数应用举例
有5个人坐在一起,问第5个人多少岁?他说比第4个人大两岁。问第4个人岁数,他说比第3个人大两岁。问第3个人,又说比第2个人大两岁。问第2个人,说比第1个人大两岁。最后问第1个人,他说是10岁。请问第5个人多大?
分析:
每一个人的年龄都比其前1个人的年龄大两岁。即:
age(5)=age(4)+2
age(4)=age(3)+2
age(3)=age(2)+2
age(2)=age(1)+2
age(1)=10
可以用式子表述如下:
如果(n=1)
age(1)=10
如果(n>1)
age(n)=age(n-1)+2
int getAge(int n){
intage ;
if(n==1){
age =10;
}else{
age =age(n-1)+2;
}
returnage;
}
/**
* 计算n的阶乘
* @return 返回阶乘的值
*/
int jieCheng(int n){
int jc; //定义变量用于存放阶乘的结果
if (n==1) { //如果n=1的时候,1!的结果还是1
jc = 1;
}else{
jc = jieCheng(n-1)*n;//如果不是1,阶乘=(n-1)!*n;
}
return jc;
}
int main(){
int a =jieCheng(8);
printf("%d\n",a);
return 0;
}