今天给大家在更新一下指针类型的知识,这里讲到了一个库函数sqort,以及回调函数的理解。
望喜欢
目录
回调函数
qsort函数
qsort模拟实现
回调函数
回调函数就是⼀个通过函数指针调用的函数。 如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被用来调用其所指向的函数 时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条 件发生时由另外的⼀方调用的,用于对该事件或条件进行响应。
其实我们之前也讲过一点有关这点的内容,那么今天就更详细的来讲解一下,下面我们先看一下两段代码
我们先写出加减乘除的各个函数,用来做一个简单计算器的基本函数。
#include <stdio.h>
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("******************");printf(" 1:add ");printf(" 3:mul ");printf("******************");printf("请选择:");scanf("%d", &input);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;
}
我们是否一眼就看出里面的重复部分(scanf x ,y 和打印结果的过程)比较多,我们是否能想出一个办法来解决这个问题,竟然我们要讲到回调函数了那么我们的解决方法就是我们要说的回调函数了,下面我就来讲讲如何·使用回调函数来实现简便。
注:这里简化的方法不仅可以用回调函数来实现,还可以使用转移表的方法来实现即函数指针数组来完成。
那么我们再来看一下经过使用回调函数的方法来进行化简的代码:
int main()
{int input = 1;do{printf("******************");printf(" 1:add ");printf(" 3:mul ");printf("******************");printf("请选择:");scanf("%d", &input);switch (input){case 1:calc(add);break;case 2:calc(sub);break;case 3:calc(mul);break;case 4:calc(div);break;case 0:printf("退出程序\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}
那我们仔细对比就会发现哦我们这里多了一个我们不知道的函数,就是calc 函数 那么这便是回调函数,大家可以看到我们在输入想使用的计算方法后,我们都会向回调函数传进去一个相应计算方法的指针,那么这时我们就会再回调函数中通过对应的指针调用这个计算方法的函数。
讲了那么多那么我们看看我们这里的回调函数的代码是怎么样的:
void calc(int(*pf)(int, int))
{int ret = 0;int x, y;printf("输⼊操作数:");scanf("%d %d", &x, &y);ret = pf(x, y);printf("ret = %d\n", ret);
}
这里难点在于函数指针即pf,我们这里的形参就是一个函数指针 pf。然后就是根据传进来的函数指针调用计算函数。
这便是回调函数的理解与解析了。
qsort函数
我们看一下cplusplus的解析:
我们现在借助一下图来理解此函数:
相信图解已经可以大概理解这个函数了,那么下面我们来用它实现一下冒泡排序的函数:
int cmp_int(void* p1, void* p2)
{return *(int*)p1 - *(int*)p2;}void print(int* p1,int sum)
{for (int i = 0; i < sum; i++){printf("%d ", p1[i]);}}int main()
{int arr[10] = { 11,2,3,4,66,34,13,15,16,10 };qsort(arr, 10, sizeof(arr[1]), cmp_int);print(arr, 10);return 0;
}
们先定义一个cmp_int函数然后按照上图进行传参就可以正常运行了。
大家通过运行结果截图 就可以看到,代码就已经可以完美的运行成功了,完成了排序了。这里我
qsort模拟实现
那么为了更好的理解qsort函数那么接下来我们来模拟实现一下qsort函数:
int cmp_int(void* p1, void* p2)
{return *(int*)p1 - *(int*)p2;}void print(int* p1,int sum)
{for (int i = 0; i < sum; i++){printf("%d ", p1[i]);}}void swap(char* p1, char* p2, size_t with)
{for (int i = 0; i < with; i++){char tem = *p1;*p1 = *p2;*p2 = tem;p1++;p2++;}}void Subble_sort(void* base, size_t sz, size_t with, int (*cmp)(void* p1, void* p2))
{int i, j;for (i = 0; i < sz - 1; i++){for (j = 0; j < sz - 1 - i; j++){if (cmp((char*)base + j * with, (char*)base + (j + 1) * with) > 0){swap((char*)base + j * with, (char*)base + (j + 1) * with, with);}}}}int main()
{int arr[10] = { 11,2,3,4,66,34,13,15,16,10 };Subble_sort(arr, 10, sizeof(arr[1]), cmp_int);print(arr, 10);return 0;
}
代码解析:
这里我们模拟实现的代码中我们仔细一想其实冒泡的趟数是不变的 ,所以冒泡的趟数代码我们就不修改这里的代码了,那么我们要改动的就是比较函数,因为在传进来的数据中不一定是都是整形数组,也可能是字符串数组或结构体数组,我们都需要对此进行改变一下比较函数。这里的交换函数其实我们不需要 不断根据数组类型而改变,因为我们这里是一个一个字节的对两个元素进行交换,只要我们知道元素类型的大小那么我们就可以进行交换任何类型的数组元素。
这里函数用整形数据是成功运行的,其他类型的数组就不进行尝试了,在这之前我也尝试过了。
文章已到末尾,望喜欢。