函数指针数组与回调函数

目录

1.函数指针数组

2.回调函数

总结


1.函数指针数组

数组是一个存放相同类型数据的存储空间,字符数组是一个存放字符类型的数组,是用来存放字符的数组,而函数指针数组则是一个存放函数指针类型的数组。

首先,让我们来看看函数指针数组的定义。函数指针数组是一个数组,它的元素都是函数指针。函数指针是指向函数的指针变量,可以用来存储函数的地址。函数指针的定义方式如下:

返回值类型 (*函数指针变量名)(参数列表)

例如:

int (*parr1)();

在此基础上,我们可以定义一个函数指针数组,其中的函数指针都指向返回类型为int,参数列表为空的函数

int (*parr1[10])();

其中parr1 先和[] 结合,说明 parr1是数组,而数组中存储的类型是
是int (*)() 类型的函数指针。

那函数指针到底有什么用呢?有没有运用场景呢?答案是肯定的。

我们先来看一段代码

#include 

int add(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
int mul(int a, int b)
{
	return a * b;
}
int div(int a, int b)
{
	return a / b;
}
int main()
{
	int x, y;
	int input = 1;
	int ret = 0;
	do
	{
		printf("*************************\n");
		printf(" 1:add       2:sub \n");
		printf(" 3:mul       4:div \n");
		printf(" 0:exit\n");
		printf("*************************\n");
		printf("请输入你的选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("输入操作数:");
			scanf("%d %d", &x, &y);
			ret = add(x, y);
			printf("ret = %d\n", ret);
			break;
		case 2:
			printf("输入操作数:");
			scanf("%d %d", &x, &y);
			ret = sub(x, y);
			printf("ret = %d\n", ret);
			break;
		case 3:
			printf("输入操作数:");
			scanf("%d %d", &x, &y);
			ret = mul(x, y);
			printf("ret = %d\n", ret);
			break;
		case 4:
			printf("输入操作数:");
			scanf("%d %d", &x, &y);
			ret = div(x, y);
			printf("ret = %d\n", ret);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

 这一段代码实现了一个较为简单的,可以用于计算整数加减乘除的计算器,但是我们可以发现这段代码非常冗余,重复的代码非常多,代码拉的很长。对此我们可以想办法将重复的代码整理起来,减少使用的次数。如果简单的将代码封装成一个函数,那我们在switch语句中仍然要多次调用,显然达不到我们的目的。对此函数指针数组可以比较好的处理这种情况,如果我们使用函数指针数组将每个需要执行的函数存入数组中,再在特定的地方利用数组下标进行访问,便可以很好的解决问题。

下面是代码:

#include
int Add(int x, int y) {
	return x + y;
}
int Sub(int x, int y) {
	return x - y;
}
int Mul(int x, int y) {
	return x * y;
}
int Div(int x, int y) {
	return x / y;
}
void menu() {
	printf("*******************************\n");
	printf("***0.exit              1.Add***\n");
	printf("***2.Sub               3.Mul***\n");
	printf("***4.Div                    ***\n");
	printf("*******************************\n");
}
int main() {
	int input;
	do {
		menu();
		printf("请输入你的选择\n");
		scanf("%d", &input);
		if (input == 0) {
			printf("退出程序\n");
		}
		else if (input < 0 || input>4) {
			printf("输入有误,请重新输入\n");
		}
		else {
			printf("请输入两个计算数\n");
			int x, y;
			scanf("%d%d", &x, &y);
			int(*cal[5])(int, int) = {NULL,Add,Sub,Mul,Div};//函数指针数组,将函数和数字下标对应起来
			int ret=cal[input](x, y);//直接用下标访问数组里的函数
			printf("%d\n", ret);
		}
	} while (input);
	return 0;
}

这段代码展示了函数指针数组的基本用法。通过函数指针数组,我们不仅优化了代码的结构,降低了代码的冗余度和长度,同时我们还可以在此基础上实现不同的功能模块,根据用户的选择动态调用对应的函数。这种设计方式可以使程序更加灵活和可扩展。 

2.回调函数

回调函数就是一个通过函数指针调用的函数,可以作为参数传递给另一个函数,并在满足特定条件时由另一个函数调用。回调函数的作用是在特定的时刻执行特定的操作,从而实现程序的灵活性和可扩展性。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数
的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

#include 


void process(int data, void (*callback)(int) ) {
    // 执行某些操作
    printf("普通函数的调用: %d\n", data);

    // 调用回调函数
    callback(data);
}

void callbackFunc(int data) {
    printf("回调函数的调用: %d\n", data);
}

int main() {
    int data = 10;

    // 调用process函数,并传递回调函数作为参数
    process(data, callbackFunc);

    return 0;
}

在上述示例代码中,我们定义了一个process函数,该函数接受一个整数参数和一个回调函数参数。在process函数中,我们执行某些操作,并调用传递的回调函数来处理数据。在主函数中,我们定义了一个回调函数callbackFunc,并将其作为参数传递给process函数。当process函数执行完毕后,会调用回调函数来处理数据。

使用回调函数,我们可以自己实现qsort的功能,为了更加简单,采用冒泡排序的算法进行排序。

代码如下:

#include 
int int_cmp(const void* p1, const void* p2)
{
	return (*(int*)p1 - *(int*)p2);
}
void _swap(void* p1, void* p2, int size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *((char*)p1 + i);
		*((char*)p1 + i) = *((char*)p2 + i);
		*((char*)p2 + i) = tmp;
	}
}
void bubble(void* base, int count, int size, int(*cmp)(const void*, const void*))
{
	int i = 0;
	int j = 0;
		for (i = 0; i < count - 1; i++)
		{
			for (j = 0; j < count - i - 1; j++)
			{
				if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)//利用指针来访问数组
				{
					_swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
				}
			}
		}
}
int main()
{
	int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
	int i = 0;
	bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

这段代码实现了一个冒泡排序的函数bubble,可以对任意类型的数组进行排序。其中,int_cmp是一个回调函数,用于比较两个整数的大小。_swap函数用于交换两个元素的值。在main函数中,定义了一个整数数组arr,然后调用bubble函数对数组进行排序,最后打印排序后的结果。

总结:

回调函数是一种强大的工具,可以提升程序的灵活性和可扩展性。通过使用回调函数,我们可以将特定的操作封装在回调函数中,实现主程序与具体操作的解耦。回调函数可以根据不同的条件执行不同的操作,从而使程序具有更高的灵活性。

你可能感兴趣的:(算法)