C语言学习-第七章 利用函数实现模块化程序设计④

171 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情

函数的递归调用

在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用

一个递归的问题可以分为“回溯”和“递推”两个阶段。

例1:有5个学生坐在一起,问第5个学生多少岁,他说比第4个学生大2岁。问第4个学生岁数,他说比第3个学生大2岁。问第3个学生岁数,他说比第2个学生大2岁。问第2个学生岁数,他说比第1个学生大2岁。最后问第1个学生,他说是10岁。请问第5个学生多大。

#include <stdio.h>

int main() {
    int age(int n); // 对age函数的声明
    printf("No.5, age:%d\n", age(5)); // 输出第5个学生的年龄
    return 0;
}
// 定义递归函数
int age(n) {
    int c;
    if (n == 1) {
        c = 10;
    } else {
        c = age(n - 1) + 2; // 年龄是前一个学生的年龄加2
    }
    return c; // 返回年龄
}

image.png

例2:用递归方法求n!

#include <stdio.h>

int main() {
    int fac(int n); // fac函数声明
    int n, y;
    printf("input a integer number:");
    scanf("%d", &n); // 输入要求阶乘的数
    y = fac(n);
    printf("%d! = %d", n, y);
    return 0;
}

// 定义fac函数
int fac(int n) {
    int f;
    if (n < 0) { // n不能小于0
        printf("n < 0, data error!");
    } else if (n ==0 || n== 1) { // n==0或1时,n!=1
        f = 1;
    } else {
        f = fac(n - 1) * n; // n>1时,n! = n * (n - 1)
    }
    return f;
}

数组作为函数参数

调用有参函数时,需要提供实参。实参可以是常量、变量或表达式。数组元素也可以用作函数实参,其用法与变量相同,向形参传递数组元素的值。数组名也可以作实参和形参,传递的是数组第一个元素的地址。

数组元素作函数实参

数组元素可以用作函数实参,但是不能用作形参。因为形参是在函数被调用时临时分配存储单元的,不可能为一个数组元素单独分配存储单元(数组是一个整体,在内存中占连续的一段存储单元)。数组元素作函数实参时,把实参的值传给形参,是“值传递”方式。数据传递的方向是从实参传到形参,单向传递

:输入10个数,要求输出其中值最大的元素和该数是第几个数。

#include <stdio.h>

int main() {
// Ⅶ:输入10个数,要求输出其中值最大的元素和该数是第几个数。
    int max(int x, int y); // 函数声明
    int a[10], m, n, i;
    printf("enter 10 integer numbers:");
    for (i = 0; i < 10; i++) {
        scanf("%d", &a[i]);
    }
    printf("\n");
    for (i = 1, m = a[0], n = 0; i < 10; i++){
        if (max(m, a[i]) > m) { // 若max函数返回的值大于m
            m = max(m, a[i]); // max函数返回的值取代m原值
            n = i; // 把此数组元素的序号记下来,放在n中
        }
    }
    printf("The largest number is %d \n it is the %dth number.\n", m, n + 1);

    return 0;
}

int max (int x, int y) { // 定义max函数,有两个参数
    int z;
    z = x > y ? x : y;
    return  z;
}

image.png

一维数组名作函数参数

用数组元素作实参时,向形参变量传递的是数组元素的值,而用数组名做函数实参时,向形参(数组名或指针变量)传递的是数组首元素的地址。

:有一个一维数组score,内放10个学生成绩,求平均成绩。

#include <stdio.h>

int main() {
    float average(float array[10]); // 函数声明
    float score[10], aver;
    int i;
    printf("input 10 scores: \n");
    for (i = 0; i < 10; i++) {
        scanf("%f", &score[i]);
    }
    printf("\n");
    aver = average(score);
    printf("average score is %5.2f\n", aver);


    return 0;
}
// 定义average函数
float average(float array[10]) {
    int i;
    float aver, sum = array[0];
    for (i = 0; i < 10; i++) {
        sum += array[i]; // 累加学生成绩
    }
    aver = sum / 10;
    return  aver;
}

image.png

编译系统把形参数组处理为指针变量,该指针变量用来接收从实参数组传过来的地址。

多维数组名作函数参数

可以用多维数组名作为函数的实参和形参,在被调用函数中对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明。例如:

int arrar[3][10];
或
int array[][10];
// 两者合法且等价,但是不能把第2维以及其他高维的大小说明省略

  • 为什么要用函数
  • 怎样定义函数
  • 调用函数
  • 对被调用函数的声明和函数原型
  • 函数的嵌套调用
  • 函数的递归调用
  • 数组作为函数参数
  • 局部变量和全局变量
  • 变量的存储方式和生存期
  • 关于变量的声明和定义
  • 内部函数和外部函数