c语言基础之函数


我们平时用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

这就是递归的实现,我就先不给大家出难一点的题了,其实并不难,就是不要想太深,不然越想越迷糊。大家可以好好看下这道例题,想通了就好了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值