赞
踩
回调函数就是一个通过函数指针调用的函数。
如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
在上一节中我们所写的转移表中,我们虽然采用的是函数数组调用的形式,但是实际上是根据用户的输入来调取不同的函数,而我们今天学习了回调函数后,就可以把函数数组的部分优化掉,只采用一个函数作为接口,然后根据函数指针参数,调取不同的函数,更加的直观,简便。
- #define _CRT_SECURE_NO_WARNINGS
- #include <stdio.h>
- void menu()
-
- {
-
- puts("*********************************");
-
- puts("**********1.add 2.sub********");
-
- puts("*********************************");
-
- puts("**********3.mul 4.div********");
-
- puts("*********************************");
-
- puts("**************0.exit*************");
-
- puts("*********************************");
-
- }
-
- 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 calc(int (*pf)(int, int))
- {
- printf("输入操作数:");
- int x, y;
- scanf("%d %d", &x, &y);
- int ret = pf(x, y);
- printf("%d\n", ret);
- }
-
-
- int main()
-
- {
-
- menu();
-
- int x, y;
- int input;
-
- do
-
- {
- 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);
- case 0:
- break;
- default:
- printf("选择错误\n");
- break;
- }
-
- } while (input);
- }

qsort是c语言中stdlib.h库中的一个排序函数,可以根据我们所给的参数,排列大小,底层实现是快速排序,通过下面的参数,我们可以看到void* 说明qsort 函数是适用于所有任意类型的函数
base: 指向要排序的数组的第一个对象的指针
num: 数组中排序的元素数量
size: 数组中每个元素的大小(以字节为单位)
compar: 指向两个元素的函数指针
将两个指针作为参数(均转化为const void*)。函数通过返回定义元素的顺序:
- //这里需要注意参数,最好写成const void* 的形式 适配其他类型
- int int_cmp(const void* p1, const void* p2)
- {
- return (*(int*)p1) - (*(int*)p2);
- }
-
- int main()
- {
- int arr[] = { 1,3,5,4,8,9,12,2,3 };
- int i = 0;
- size_t sz = sizeof(arr) / sizeof(arr[0]);
- qsort(arr, sz, sizeof(arr[0]), int_cmp);
- for (int i = 0; i < sz; i++)
- {
- printf("%d ", arr[i]);
- }
- printf("\n");
- return 0;
- }

- struct Stu
- {
- char name[20];
- int age;
- };
-
- int cmp_stu_by_age(const void* p1, const void* p2)
- {
- return (*(struct Stu*)p1).age - (*(struct Stu*)p2).age;
- }
-
- int cmp_stu_by_name(const void* p1, const void* p2)
- {
- return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
- }
-
-
- void test2()
- {
- struct Stu s[] = { {"zhangsan",20},{"lisi",30},{"wangwu",15} };
- int sz = sizeof(s) / sizeof(s[0]);
- qsort(s, sz, sizeof(s[0]), cmp_stu_by_name);
- for (int i = 0; i < sz; i++)
- {
- printf("%s\t", s[i].name);
- printf("%d\n", s[i].age);
- }
- }
-
-
- void test1()
- {
- struct Stu s[] = { {"zhangsan",20},{"lisi",30},{"wangwu",15} };
- int sz = sizeof(s) / sizeof(s[0]);
- qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
- for (int i = 0; i < sz; i++)
- {
- printf("%s\t", s[i].name);
- printf("%d\n", s[i].age);
- }
-
- }
-
- int main()
- {
- test1(); //按照年龄排序
- printf("\n");
- test2(); //按照名字排序
- return 0;
- }

需要注意 strcmp 是string.h的库函数,专门用来比较两个字符串的大小的,且比较的是字典序,也就是依次比较ASCII码,返回值正好与我们构建的函数返回值规则一致。
使用回调函数,模拟实现qsort(采用冒泡的方式)
基本核心:
- void qsort(
- void* base,//base 指向了要排序的数组的第一个元素
- size_t num, //base指向的数组中的元素个数(待排序的数组的元素的个数)
- size_t size,//base指向的数组中元素的大小(单位是字节)
- int (*compar)(const void* p1, const void* p2)//函数指针 - 指针指向的函数是用来比较数组中的2个元素的
- )
- {
- if (compar(x, y) > 0)
- {
- //交换
- }
- }
实现代码:
注意其中的字节交换,以及排序时对于元素的变更,都是怎么具体实现的
- void swap(void* p1, void* p2,size_t size)
- {
- //由于不知道类型,所以需要根据参数类型,一个一个字节交换字节里的值来达到元素交换的效果
-
- for (int i = 0; i < size; i++)
- {
- char temp = *((char*)p1+i);
- *((char*)p1+i) = *((char*)p2+i);
- *((char*)p2 + i) = temp;
- }
- }
- int int_cmp(const void * p1, const void* p2)
- {
- return (*(int*)p1 - *(int*)p2);
- }
- //size_t 是字节类型 是无符号整型数据
- void bubble(void* base, int count, size_t size, int (*cmp)(const void*, const void*))
- {
- int i, j;
- i = j = 0;
- for (i = 0; i < count-1; i++)
- {
- for (j = 0; j < count - i - 1; j++)
- {
- //因为我们不知道传入的数组是什么类型的
- // 所以就需要转成char* 然后移动 j*size来移动指针来达到选其他数组元素的目的
- if (cmp((char*)base + j * size, (char*)base + (j + 1) * size)>0) // 大于0 说明 前者大于后者
- {
- swap((char*)base + j * size, (char*)base + (j + 1) * size,size);
- }
- }
- }
- }
-
- int main()
- {
- int arr[] = { 1,3,5,4,8,9,12,2,3 };
- int i = 0;
- int sz = sizeof arr / sizeof arr[0];
- bubble(arr,sz , sizeof(int), int_cmp);
- for (int i = 0; i < sz; i++)
- {
- printf("%d ", arr[i]);
- }
- printf("\n");
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。