当前位置: 首页 > article >正文

C语言基础20:函数的递归调用、数组做函数的参数

函数的递归调用

  • 递归调用的含义:在一个函数中,直接或者间接调用了函数自身,就称之为函数的递归调用。

    //直接调用
    a()a();
    
    //间接调用
    a()b()a();
    a()b()..a();
    
  • 递归调用的本质:

    是一种循环结构,它不同于我们之前所学的while,do…while,for这样的循环结构,这些循环结构是借助于循环变量;而递归调用是利用函数自身实现循环结构,如果不加以控制,很容易产生死循环。

  • 递归调用的注意事项:

    1.递归调用必须要有出口,一定要终止递归(否则就会产生死循环)。

    2.对终止条件的判断一定要放在函数递归之前(先判断,再执行)

    3.进行函数的递归调用。

    4.函数递归的同时一定要将函数调用向出口逼近。

案例

案例1:

  • 需求:

    递归案例-有5个人坐在一起,
    问第5个人多少岁?他说比第4个人大2岁。
    问第4个人岁数,他说比第3个人大2岁。
    问第3个人,又说比第2个人大2岁。
    问第2个人,说比第1个人大2岁。
    最后问第1个人,他说是10岁。请问第5个人多大。

  • 分析:

在这里插入图片描述

  • 代码:

    /*************************************************************************
    > File Name:demo02.c
    > Author:ZK
    > Description: 递归案例
    > Created Time: 2025年02月20日 星期四 14时21分51秒
    ************************************************************************/
    
    #include <stdio.h>
    
    /**
    * 求年龄的递归函数
    * @param n 第几个人
    */
    int age(int n)
    {
        // 创建一个变量,存储函数返回值,返回的是每个人的年龄
        int c;
        
        // 第1个人的年龄是已知的,10岁
        if(n == 1)
        {
            c = 10;
        }
        else if (n > 1) // 只过滤正数,也就是非第1人
        {
            c = age(n-1) + 2; // 当前这个人的年龄 = 上一个人的年龄 + 2
        }
        
        return c;
    }
    
    int main(int argc,char *argv[])
    {
        printf("%d\n",age(5));
        
        return 0;
    }
    
    

案例2:

  • 需求:求阶乘(n!)

  • 分析:

在这里插入图片描述

  • 代码:

    /*************************************************************************
    > File Name:demo03.c
    > Author:ZK
    > Description: 递归案例:求阶乘(5的阶乘:5×4×3×2×1)
    > Created Time: 2025年02月20日 星期四 14时43分45秒
    ************************************************************************/
    
    #include <stdio.h>
    
    /**
    * 定义一个函数,用来求n的阶乘
    * @param n 上限
    */
    long fac(int n)
    {
        // 定义一个变量,用做这个函数的返回值,也就是乘积
        long f;
        
        // 出口校验
        if(n < 0)
        {
            printf("n的范围不能是0以下的数\n");
            return -1;
        }
        else if(n == 0 || n == 1)
        {
            f = 1; // 出口
        }
        else // 递归
        {
            f = fac(n-1) * n;
        }
        
        return f;
    }
    
    int main(int argc,char *argv[])
    {
        
        int n;
        printf("请输入一个整数:\n");
        scanf("%d",&n);
        printf("%d的阶乘结果是%ld\n",n,fac(n));
        return 0;
    } 
    
    

数组做函数的参数

当用数组做函数实参时,则形参应该也要用数组或指针变量来接受(函数实参是数组,形参一定是数组或者指针),注意的是,此次传递并不代表传递了数组中所有的元素数据,而是传递了第一个元素的内存地址(数组首地址),形参接收到这个地址后,则形参和实参就代表了同一块内存空间,则形参的数据修改会改变实参的。这种数据传递的方式,我们称之为地址传递

在这里插入图片描述

如果用数组作为函数的形参,那我们提供另一个形参表示数组的元素个数。原因是数组形参代表的仅仅是实际数组的首地址。也就是说形参只获取到了实参数组的第一个元素的地址,并不确定传递了多少个数据。所以提供另一个形参表示数组元素的容量,可以防止在被调函数对实际数组访问时产生的下标越界。举例:

//定义一个函数,将数组作为形参
void fun(int arr[],int len)//数组传参,形参只能接受到实参数组的首地址,并不是完整的数组
{
    //int l = sizeof(arr) / sizeof(arr[]);此时编译报错,因为无法确定arr的实际大小,所以无法通过sizeof进行计算
    for(int i = 0; i < len; i++)//len就是传递过来的实参数组的大小
    {
        printf("%-4d",arr[i]);
    }
    printf("\n");
}

void main()
{
    int arr[] = {11,22,33,44,55};
    int len = sizeof(arr) / sizeof(arr[0]);
    funa(arr,len);
}

但有一个例外,如果是用字符数组做形参,且实参数组中存放的是字符数据(形参是字符数组,实参是字符常量)。则不用表示数组元素的个数的形参,原因是字符本身会自动结束\n,举例:

//定义一个函数,将数组作为形参
void fun(chararr[])//数组传参,形参只能接受到实参数组的首地址,并不是完整的数组
{
    char c;
    int i = 0;
    while((c = arr[i])!='\0')
    {
        printf("%c",c);
          i++;
    }
    printf("\n");
}

void main()
{
    funa("hello");
}
案例

案例1:

  • 需求:

有两个数组a和b,各有5个元素,将它们对应元素逐个地相比(即a[0]与b[0]比,a[1]与b[1]比……)。如果a数组中的元素大于b数组中的相应元素的数目多于b数组中元素大于a数组中相应元素的数目(例如,a[i]>b]i]6次,b[i]>a[i] 3次,其中i每次为不同的值),则认为a数组大于b数组,并分别统计出两个数组相应元素大于、等于、小于的个数。

int a[10] = {12,12,10,18,5};
int b[10] = {111,112,110,8,5};
  • 代码:

    /*************************************************************************
    > File Name:demo04.c
    > Author:ZK
    > Description: 数组作为函数参数
    > Created Time: 2025年02月20日 星期四 16时09分05秒
    ************************************************************************/
    
    #include <stdio.h>
    #define LEN 5
    
    /**
    * 定义一个函数,实现两个数的比较
    * @param x,y 参与比较的两个数字
    * @return 比较结果,x > y 返回1; x < y 返回 -1; x == y 返回 0
    */
    int large(int x, int y)
    {
        int flag = 0;
        if (x > y) flag = 1;
        else if(x < y) flag = -1;
        return flag;
    }
    
    int main(int argc,char *argv[])
    {
        // 定义两个数组,循环变量,最大,最小,相等
        int a[LEN],b[LEN],i,max=0,min=0,k=0;
        
        printf("请给数组a添加5个整数:\n");
        for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
        {
            scanf("%d",&a[i]);
        }
        printf("\n");
        
        printf("请给数组b添加5个整数:\n");
        for(i = 0; i < sizeof(b)/sizeof(b[0]); i++)
        {
            scanf("%d",&b[i]);
        }
        printf("\n");
        
        // 遍历
        for(i = 0; i < LEN; i++)
        {
            // 比较两个数组中,同一位置两个元素的大小
            int value = large(a[i],b[i]);
            if(value == 1) max++; // 记录a比b大的次数
            else if(value == -1) min++; // 记录a比b小的次数
            else k++;
            // 记录a和b相等的次数
        }
        
        printf("max=%d,min=%d,k=%d\n",max,min,k);
        
        return 0;
    }
    
    

案例2:

  • 需求:编写一个函数,用来分别求数组score_1(有5个元素)和数组score_2(有10个元素)各元素的平均值 。

  • 代码:

    /*************************************************************************
    > File Name:demo05.c
    > Author:ZK
    > Description: 数组作为函数参数
    > Created Time: 2025年02月20日 星期四 16时28分25秒
    ************************************************************************/
    
    #include <stdio.h>
    
    /**
    * 定义一个函数,用来求数组中个元素的平均值
    */
    float avg(float scores[],int len)
    {
        int i;
        
        float aver,sum = scores[0];// 保存平均值和总分
        
        // 遍历数组
        for(i = 1; i < len; i++)
        {
            sum += scores[i];
        }
        
        // 求平均分
        aver = sum / len;
        
        return aver;
        
        // return sum / len; 等价于上面写法
    }
    
    int main(int argc,char *argv[])
    {
        
        // 准备俩测试数组
        float scores1[] = {66,78,86,56,46};
        float scores2[] = {77,88,67,78,98,32,78,88,77,39};
        
        printf("这个班的平均分:%6.2f\n",avg(scores1,sizeof(scores1)/sizeof(float)));
        printf("这个班的平均分:%6.2f\n",avg(scores2,sizeof(scores2)/sizeof(float)));
        
        return 0;
    }
    
    

http://www.kler.cn/a/554553.html

相关文章:

  • VSCode配置C/C++开发环境|最新教程202502
  • 【Spring详解一】Spring整体架构和环境搭建
  • 【Matlab】Matlab基于遗传算法的指纹识别(源码)【独一无二】
  • 如何在Windows 10操作系统中安装并配置PHP集成软件XAMPP
  • HTML5 面试题
  • AI大模型驱动的智能音视频通信:视频通话SDK工具EasyRTC在嵌入式设备中的应用探索
  • 深入理解 NoSQL 数据库:MongoDB 与 Cassandra
  • TCP 三次握手与四次挥手:构建与终止可靠通信的核心机制
  • 调用click.getchar()时Windows PyCharm无法模拟键盘输入
  • RT-Thread+STM32L475VET6实现红外遥控实验
  • HTTP请求状态码
  • RV1126解码—ffmpeg_read_thread线程的讲解
  • 什么是pytest.ini及如何在Pytest中应用以提升配置效率
  • 万能头文件
  • Profinet 转 EtherNet/IP 如何解锁西门子 1500 与罗克韦尔 PLC 通讯潜能
  • Emacs折腾日记(十三)——函数、宏以及命令
  • java每日精进 2.13 MySql迁移人大金仓
  • uniapp 使用unplugin-auto-import 后, vue文件报红问题
  • 一文讲清 AIO BIO NIO的区别
  • hive迁移补数脚本细粒度 表名-分区唯一键