我们平时用c语言写题目时,代码长度通常不过十几行,几十行,最多也不过几百行。但是在编写大的项目时一个程序常常需要几千行,几万行的代码。其中常常有大量的数据需要重复的使用同一种方法处理,许多程序重复多遍使用。每次使用时都把代码复制一遍去执行,现实吗?很明显不现实吧。于是在c语言中出现了——函数。来解决这个问题。
说到函数,大家肯定不陌生吧?在学数学的时候,函数可是吧我们折磨的欲仙欲死的。但是说到函数的具体定义,有谁具体的知道嘞?函数的英文名是“function”,后来被中国人李善兰把“function”翻译成中文“函数”这一词。李善兰认为:凡式中含天,为天之函数(凡是公式中含有变量x,则该式子叫做x的函数)。即凡此变数中函彼变数者,则此为彼之函数。
什么?还是没搞懂函数的意思?那说通俗点,就是即给定一个数集A,假设其中的元素为x。现对A中的元素x施加对应法则f,记作f(x),得到另一数集B。而放在c语言中,法则f就是你编写的函数里面的程序。所以当你编写好了一个函数后,你要用到串代码的时候,直接调用函数就可以了。
一、函数的定义和调用
函数主要包括两种,一种叫库函数,还有一种叫自定义函数。
不论哪种函数,我们调用时只需要使用如下格式即可:
函数名(实参1,实参2,,....);
在使用库函数时,只需要在程序的开头声明
#include<math.h>
就可以直接调用了
例如
调用函数库中已有的函数pow(功能为求x的y次方)
代码实现
#include <stdio.h>
#include <math.h>/*声名调用函数库函数*/
#include<stdlib.h>
int main()
{
double x=2,y=3,z;/*pow函数为double形,所以我们用double形的z去储存函数返回的结果*/
z=pow(x,y);/*直接调用*/
printf("%.lf",z);
return 0;
}
输出
8
而自定义函数需要使用着自己编写,一般格式为:
返回值类型 函数名(参数类型1 形参1,参数类型2 形参2,,....)/*参数可以是一个,也可以是多个*/
{
函数体/*即你编写的处理程序*/
}
怎么样,来个自定义函数的例题耍耍吧?
例1:
编写一个函数,找到他们两个中较大的一个,打印输出。
解题思路
没啥思路,编写函数,直接怼!
代码实现
#include <stdio.h>
#include<stdlib.h>
void add(int a,int b)/*void指函数类型为不返回函数*/
{
if(a>b)
printf("%d",a);/*若a大于b,输出a*/
else if(a<b)
printf("%d",b);/*若b大于a,输出b*/
else
printf("一样大");/*a等于b,显示一样大*/
return 0;
}
int main()
{
int x,y;
scanf("%d %d",&x,&y);
add(x,y);/*调用函数*/
return 0;
}
样例输入
2 3
样例输出
3
二、函数的参数,声明及返回值
(1)函数的参数
看完函数的定义和调用后,大家会发现在定义函数时,参数是形参,而调用函数时,参数是实参。在调用时,实参的值会复制粘贴到形参中,而且形参变量只有在被调用时才分配内存单元,在调用结束时, 即刻释放所分配的内存单元。所以在函数内定义结束后,所有东西会在函数结束时被清除。
例如:
#include <stdio.h>
#include<stdlib.h>
int add(int x,int y)
{
int z;
z=x;
x=y;
y=z;/*通过变量z交换x,y的值*/
printf("函数中x=%d y=%d\n",x,y);
}
int main()
{
int x=2,y=3,z;
add(x,y);/*调用函数处理想x,y*/
printf("主函数中x=%d y=%d",x,y);/*输出此时x,y的值*/
return 0;
}
输出
函数中x=3 y=2
主函数中x=2 y=3
通过它可以很明显的发现,即使在函数中已经将x,y的值交换,但是主函数中x,y的值仍然没有交换。
(2)函数的声明
在学了控制结构后我们知道,c语言的一结构为顺序结构,即从前往后。所以在定义自定义函数的时候要注意,若定义的函数在主函数之后,主函数是无法知道这个函数的存在的,也就会无法调用,就像古代的人无法知道今天的事一样。这个时候,我们要就需要在主函数前面声明一下:
#include <stdio.h>
#include<stdlib.h>
返回值类型 函数名(参数类型1 形参1,参数类型2 形参2,,....)/*在主函数前声明*/
int main()/*主函数*/
{
主函数体
}
返回值类型 函数名(参数类型1 形参1,参数类型2 形参2,,....)/*你写的函数*/
{
函数体
}
这样就相当于你穿越到古代,告诉了古人今天发生的事情,古人自然就知道了今天有什么事情发生了。
(3)函数的返回值
由上面函数的参数我们可以知道,函数内部的运算是不会影响到主函数的值的,但是我们想得到函数运行后的值时,我们就可以用return语句来返回值。
return 变量名;/*可以为函数中的某个变量,也可以是某个具体的值*/
在使用return语句时,有几点是要注意的:
1、函数的返回值只能有一个;
2、函数的返回值可以使除了数组外的任意类型;
3、若函数返回类型为void,表示函数不返回值;
4、当函数运行遇到return时,会立即结束;
5、当函数返回值类型与return语句表达式中不同时,以函数返回值类型为标准。
话说大家数组感觉掌握的怎么样?来个数组配函数的题试试水?
例2:
输入一个3乘3的矩阵,使用函数算出最大值并返回到主函数中,打印输出。
解题思路
题目不难,还没有数组那一题难,只是综合性不错,需要在函数中使用简单的二维数组配合for循环即可完成。
代码实现
#include <stdio.h>
#include<stdlib.h>
int max(int a[3][3]);/*先声明函数,让主函数知道它的存在*/
int main()
{
int i,j,a[3][3],z;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
scanf("%d",&a[i][j]);/*输入数组*/
z=max(a);/*用z储存max函数返回的值*/
printf("最大值是%d",z);/*打印输出*/
return 0;
}
int max(int a[3][3])
{
int i,j,k;
k=a[0][0];
for(i=0;i<3;i++)
for(j=0;j<3;j++)
if(k<a[i][j])
k=a[i][j];/*简单的for循环找到数组最大值并用看k储存*/
return k;/*返回k值*/
}
输入
1 2 3
4 5 6
7 8 9
输出
最大值是9
三、变量的储存类型
变量的储存类型主要是一些概念性的东西,但是对我们编写代码十分的重要,它能帮助我们更加灵活的使用函数。它主要分为自动变量、外部变量、静态变量和寄存器变量。
(1)、自动变量
函数中,我们定义的变量,都默认为自动变量, 使用的时候系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空间。它是一种局部变量,即只能在函数内作用的变量。
(2)外部变量
外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。也就是说,当你定义了这个变量后,之后的所有函数都可以使用并且修改它,这个变量的名字在本程序中只有一个。声明时引用关键字 extern 对该变量进行“外部变量声明”。
(3)静态变量
有时希望函数中的局部变量的值在函数调用结束后不消失而保留原值,这时就应该指定局部变量为静态局部变量,用关键字 static 进行声明。
(4)寄存器变量
为提高效率,C 语言允许将局部变量的值存放在 CPU 的寄存器中,这种变量叫做寄存器变量,用关键字 register 声明。由于电脑cpu中寄存器很少,所以不建议大家使用这种变量,仅做了解。
四、函数的扩展——递归
说了这么多,大家应该对函数有了不少了解吧,既然学完了函数,那么我们就可以解锁一项非常“6”的技能了——递归。
其实在函数的使用过程中也可以调用函数的。但是你想象一下,如果在使用函数时,调用了它自身…嘿嘿,是不是感觉发现了新大陆?就像我们小时候要听故事时,被父母忽悠着讲的那个故事一样:从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山,山里有座庙,庙里有个和尚,和尚在讲故事,从前有座山…
递归就像上面那个故事一样,就是一次又一次的调用自己解决问题。我在网上找了许久,发现了一个人用这张图完美的阐释了递归的含义。
从图中我们可以看到,这张图的描述就是在不断的重复调用自身去描述图片内容。我们使用递归时也是如此,例如:
例3
输入一个数,求它的阶乘。要求使用递归解决。
题目分析:
递归嘛,参照上面的那张图,只要找到那只狗的动作“抱着”(也就是数据之间的关系)和小鲫鱼(也就是递归结束的点)那么递归就很好写了。我们再来看题目,阶乘嘛,就是第x个数的阶乘为x乘(x-1)!。一目了然,x乘(x-1)!就相当于动作”抱着“,当x等于1时,阶乘等于1,就相当于”小鲫鱼“。
代码实现:
#include <stdio.h>
#include<stdlib.h>
int digui(int x)
{
int z;
if(x==1)
z=1;/*递归结束的点,x=1时,就是1*/
else
z=x*digui(x-1);/*数据之间的关系,第x个的阶乘就是x乘(x-1)的阶乘*/
return z;
}
int main()
{
int x,y;
scanf("%d",&x);
y=digui(x);/*开始调用递归函数求阶乘*/
printf("%d",y);
return 0;
}
输入
3
输出
6
这就是递归的实现,我就先不给大家出难一点的题了,其实并不难,就是不要想太深,不然越想越迷糊。大家可以好好看下这道例题,想通了就好了。