这里说的函数,是指除了主函数以外的其他函数。
一、函数的作用
函数能多次调用,提高了代码利用率,还能在编程中遇到稍微复杂一点的程序时,把任务分给若干函数,让每个函数完成一项任务。
把程序拆分为若干函数的原则:
①每个函数都自成一体,功能简单、独立;
②函数与外界的耦合性要低弱,尽量少用或不用全局变量;
③函数要有较高的适用性,能满足尽量多的调用方法和场合,能被尽量多的程序调用。
例:分别找出(12,20)(30,42)(18,12)的最小公倍数。
#include<stdio.h>
int LCM(int m,int n) //求最小公倍数的函数
{
int i;
for(i=m;i<=m*n;i++){
if(i%m==0&&i%n==0) break;
}
return i;
}
int main()
{
printf("%d\n",LCM(12,20);
printf("%d\n",LCM(30,42);
printf("%d\n",LCM(18,12);
return 0;
}
二、函数的定义
1. 函数的格式
函数返回值的类型 函数名(函数参数列表)
{
定义数据、声明函数(可以没有)
输入数据(大多不需要)
计算或其他操作
结果返回或输出
}
2. 函数的返回值
定义应该函数的首要问题,就是确定函数的返回类型,而确定返回类型的前提是先确定函数需不需要返回值。
定义函数的目的是为了供其他函数调用,因此被调函数的设计应该满足主调函数的需求。
主调函数调用被调函数的目的有三种:
①主调函数仅仅让被调函数输出一些信息,没有什么需要计算,因此也就没有什么结果需要返回,这样的被调函数返回类型通常写成void;
②主调函数让被调函数计算一个结果并且直接把结果输出,那么也不需要把结果返回给主函数,所以返回类型也是void;
③主调函数希望被调函数计算出结果后,把结果返回给主函数,这时候就应该把被调函数设计成有返回值,设置返回类型的时候,返回字符就是char,返回整数就是int……
3. return 语句
对于不需要返回值的函数,可以不写return 语句,一个函数中可以不止一个return语句,但执行到其中任何一个return语句时,被调函数就会停止执行,给主调函数返回这个return语句返回的值。
4. 函数参数的设置
若被调函数需要从主调函数那里得到一些已知数据,则被调函数必须设参数以便存储它们,有几个已知数据就应该设几个参数。有些函数不需要从主调函数那里得到数据,那就不需要存储,也就没必要设置参数。
但是总的来说,设参数比不设参数好,多设参数比少设参数好。
例:找两个数字中更大的数字。
#include<stdio.h>
int max() //不设置参数
{
int m,n;
scanf("%d %d",&m,&n);
return m>n?m:n;
}
int main()
{
int m;
m = max();
printf("%d\n",m);
return 0;
}
#include<stdio.h>
int max(int m, int n) //设置参数
{
return m>n?m:n;
}
int main()
{
int m,n;
scanf("%d %d",&m,&n);
printf("%d",max(m,n)); //调用函数
return 0;
}
三、函数的调用
1. 函数声明
声明函数的方法很简单,就是把函数头复制到需要声明的地方,后面加上一个分号即可。
如上面的代码:int max(int m, int n);或者是int max(int, int);。
声明函数时参数名可写可不写,但参数类型不能忽略。
2. 函数调用的方式
函数名([实参列表])
四、函数的参数传递
1. 形参与实参
定义函数时,函数名后面括号中声明的参数称为形参。
调用函数时,函数名括号中写的参数成为实参。
函数调用时,实参与形参的个数必须相同,类型必须一致或兼容。
2. 参数的传递
参数的传递,其实就是把实参的值赋给形参。
实参和形参只是在主调函数调用被调函数的时候产生联系(实参赋值给形参),其它时候没有关联,对形参的任何操作都不会影响实参。
“单向传递”:实参的值可以传给形参,反过来则不可以。
五、函数嵌套调用
函数可以嵌套调用,如甲调用乙,乙调用丙……函数调用允许多层嵌套。
例:求1!+2!+3!+……+n!。
#include<stdio.h>
int sum(int);
int fac(int);
int main()
{
int n;
scanf("%d",&n);
printf("%d\n",sum(n)); //将sum()的返回值输出
return 0;
}
int sum(int n) //计算阶乘的和的函数
{
int i,s=0;
for(i=1;i<=n;i++)
s += fac(i);
return s;
}
int fac(int n) //计算阶乘的函数
{
int m=1,i;
for(i=0;i<=n;i++)
m *= i;
return m;
}
六、递归函数
调用自己的函数叫做递归函数。递归分两种:一种是函数直接调用自己,称为直接递归或者是简单递归;另一种是先调用别的函数,别的函数再调用自己,称为间接递归。
比如编写一个求阶乘的函数int fac(int n)以便求n!,而n!=n×(n-1)!,要计算n!,必须先求(n-1)!。而(n-1)!也可以int fac(int n)来求。
int fac(unsigned n)
{
return n*fac(n-1);
}
递归的过程中,必须存在一种能停止调用自己的情况或称结束递归的条件,就像上面的fac()函数,当需要fac(1)时,就已经可以结束递归了。
int fac(unsigned n)
{
if(n>1)
return n*fac(n-1);
else
return 1;
}
七、内部函数和外部函数
1. 内部函数
内部函数的特点:只允许被本源文件之中的函数调用。
内部函数在定义时前面有static关键字。
static int max(int a, int b)
{
//代码略
}
2. 外部函数
外部函数的特点:既允许被本源文件之中的函数调用,也允许被别的源文件中的函数调用。
外部函数在定义时前面可以用extern,也可以什么都没有。
extern int max(int a, int b)
{
//代码略
}