C语言使用函数指针数组

  • Post category:C

下面我将为您详细讲解C语言使用函数指针数组的完整使用攻略。

什么是函数指针数组?

在C语言中,函数指针是指向函数的指针,它指向的是函数在内存中的地址。而函数指针数组则是一个数组,它的每个元素都是一个指向函数的指针。通过使用函数指针数组,我们可以更加方便地存储和调用一组函数。

如何定义函数指针数组?

定义函数指针数组的一般形式如下:

返回类型 (*函数指针数组名[数组长度])(参数列表);

比如,我们定义一个包含两个指向函数的指针的函数指针数组,可以这样写:

int (*func_ptrs[2])(int, int);

如何初始化函数指针数组?

函数指针数组的初始化也很简单,可以采取以下两种方式:

直接初始化

直接将函数的地址赋值给函数指针数组的对应元素即可。比如,我们定义的上述函数指针数组可以这样初始化:

int add(int x, int y) {
    return x + y;
}

int sub(int x, int y) {
    return x - y;
}

int (*func_ptrs[2])(int, int) = {add, sub};

动态初始化

动态初始化可以在程序运行时根据需要动态地将函数指针赋值给数组元素。比如,我们可以使用一个循环来动态初始化一个包含指向n个函数的指针的函数指针数组:

int (*func_ptrs[n])(int, int);
for (int i = 0; i < n; i++) {
    if (i % 2 == 0) {
        func_ptrs[i] = add;
    } else {
        func_ptrs[i] = sub;
    }
}

如何使用函数指针数组?

使用函数指针数组的一般方法是通过数组下标来调用相应的函数指针。比如,对于上面的例子,我们可以这样调用函数指针数组中的函数:

int result = (*func_ptrs[0])(2, 3);

这样可以调用add(2, 3)函数,并将结果赋值给result

示例1:函数指针数组计算平均数

下面我们通过一个简单的示例来说明如何使用函数指针数组。这个示例中,我们定义了一个函数指针数组calc_funcs,其中包含了averagemedianmode三个函数,分别用于计算一组数字的平均数、中位数和众数:

#include <stdio.h>
#include <stdlib.h>

double average(int *arr, int n) {
    double sum = 0;
    for (int i = 0; i < n; i++) {
        sum += arr[i];
    }
    return sum / n;
}

double median(int *arr, int n) {
    // 按从小到大排列
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (arr[i] > arr[j]) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }

    if (n % 2 == 0) {
        return (arr[n / 2] + arr[n / 2 - 1]) * 0.5;
    } else {
        return arr[n / 2];
    }
}

double mode(int *arr, int n) {
    int max_count = 0;
    int mode_num = arr[0];

    for (int i = 0; i < n; i++) {
        int count = 0;
        for (int j = i; j < n; j++) {
            if (arr[i] == arr[j]) {
                count++;
            }
        }
        if (count > max_count) {
            max_count = count;
            mode_num = arr[i];
        }
    }

    return mode_num;
}

double (*calc_funcs[3])(int *, int) = {average, median, mode};

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = 5;

    for (int i = 0; i < 3; i++) {
        double result = (*calc_funcs[i])(arr, n);
        printf("Result %d = %f\n", i, result);
    }

    return 0;
}

程序中,我们首先定义了三个计算函数averagemedianmode,然后将它们打包到一个函数指针数组calc_funcs中。在main函数中,我们定义了一个整型数组arr,并计算了它的平均数、中位数和众数。最后再通过函数指针依次调用这三个函数,输出相应的结果。

示例2:调用不同类型的排序算法

下面的示例中,我们定义了一个函数指针数组solve_funcs,其中包含了sort_array_ascsort_array_descsort_struct_by_agesort_struct_by_name四个函数。这些函数分别用于对一个整型数组进行升序排列、降序排列以及对一个包含名字和年龄的学生结构体按照年龄或者名字进行排序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_NAME_LEN 20

typedef struct {
    char name[MAX_NAME_LEN];
    int age;
} student;

void sort_array_asc(int *arr, int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (arr[i] > arr[j]) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

void sort_array_desc(int *arr, int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (arr[i] < arr[j]) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    }
}

void sort_struct_by_age(student *stu_arr, int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (stu_arr[i].age > stu_arr[j].age) {
                student temp = stu_arr[i];
                stu_arr[i] = stu_arr[j];
                stu_arr[j] = temp;
            }
        }
    }
}

void sort_struct_by_name(student *stu_arr, int n) {
    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (strcmp(stu_arr[i].name, stu_arr[j].name) > 0) {
                student temp = stu_arr[i];
                stu_arr[i] = stu_arr[j];
                stu_arr[j] = temp;
            }
        }
    }
}

void print_array(int *arr, int n) {
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

void print_struct_arr(student *stu_arr, int n) {
    for (int i = 0; i < n; i++) {
        printf("name: %s, age: %d\n", stu_arr[i].name, stu_arr[i].age);
    }
    printf("\n");
}

void (*solve_funcs[4])(void *, int) = {sort_array_asc, sort_array_desc, sort_struct_by_age, sort_struct_by_name};

int main() {
    int arr[] = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3};
    int n = 10;

    printf("Sort array ASC: ");
    (*solve_funcs[0])(arr, n);
    print_array(arr, n);

    printf("Sort array DESC: ");
    (*solve_funcs[1])(arr, n);
    print_array(arr, n);

    student stu_arr[] = {{"Alice", 21}, {"Bob", 18}, {"Charlie", 22}};
    int stu_num = 3;

    printf("Sort struct by age:\n");
    (*solve_funcs[2])(stu_arr, stu_num);
    print_struct_arr(stu_arr, stu_num);

    printf("Sort struct by name:\n");
    (*solve_funcs[3])(stu_arr, stu_num);
    print_struct_arr(stu_arr, stu_num);

    return 0;
}

在上述程序中,我们定义了四个排序函数,以及一个打印整型数组的函数print_array和一个打印学生结构体的函数print_struct_arr。然后,我们定义了一个函数指针数组solve_funcs,用于存放这些排序函数的地址。在main函数中,我们使用这个函数指针数组依次调用四个函数,分别对一个整型数组和一个学生结构体数组进行不同类型的排序,并打印出结果。

这个示例展示了使用函数指针数组的另一个重要应用:可以用来动态选择不同的算法实现。