回调函数就是一个通过指针调用的函数。
如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
下面用代码进行理解当a等于1的时候才会打印hehe。
#include
void function() {
printf("hehe");
}
void test(void(*pf)(),int n) {
if (n==1)
{
pf();
}
}
int main() {
int a = 0;
scanf("%d", &a);
test(function,a);
return 0;
}
首先我们将function函数的地址作为参数传递给test函数,此时我们的function函数就是回调函数,这个function函数并不是直接调用实现,而是当我们输入值为1的时候满足发生条件,通过test函数调用function函数。
我们在深入理解指针4里面用代码解决过简单的加减乘除;如果不用转移表的形式,我们能否用回调函数来解决这个问题呢。下面就是解决办法。
#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 test(int (*pf)(int,int) ){
int a = 0, b = 0;
scanf("%d %d", &a, &b);
int r = pf(a,b);
printf("%d\n", r);
}
void menu1() {
printf("******************************\n");
printf("******1.加法******2.减法******\n");
printf("******3.乘法******4.除法******\n");
printf("******************************\n");
}
int main() {
int input = 0;
int a=0, b=0,r=0;
do
{
menu1();
scanf("%d", &input);
switch (input)
{
case 1:
test(add);
break;
case 2:
test(sub);
break;
case 3:
test(mul);
break;
case 4:
test(div);
break;
default:
input = 0;
break;
}
} while (input);
return 0;
}
当我们想实现加法时,我们将add函数作为地址传递给test函数 ,再通过test函数来调用add函数。
这个方法虽然没有用转移表写出来的代码简单,但是它也解决了switch函数过于冗长的问题。
头文件:#include
语法结构:
void qsort(void* base, size_t num, size_t size,
int (*compar)(const void*, const void*));
/*我们把它拆成一段一段来理解
void qsort(void* base, //base指向了待排序数组中的第一个元素
size_t num, //num是指待排序数组的元素个数
size_t size, //size是指待排序数组的元素大小,单位是字节
int (*compar)(const void*, const void*)); //函数指针用来比较base指向数组中任意两个元素的大小
*/
compar函数的比较原理 这里的例子中(*(mytype*)a)里面的(mytype*)就是强制类型转换,之所以需要强制类型转化,是因为数组元素传给函数指针时是空指针类型。当你要比较的元素类型是什么就转换为shen么。
当我们全部理解后,现在我们用qsort来新写一个冒泡排序
#include
#include
int cmp_int(const void* e1, const void* e2) {
return *(int*)e1 - *(int*)e2; //这里cmp函数的比较方法就是随便拿两个数相减作为它的返回值,看它结果大于还是小于还是等于,以此进行排序
}
void print(int arr[], int sz) {
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int main() {
int arr[] = { 1,3,2,4,6,5,8,7,9,0 };
qsort(arr, 10, sizeof(arr[0]), cmp_int);
print(arr, 10);
return 0;
}
当我们将e1e2改变顺序时,qsort的排序方式也会发生改变。具体解释见上图画圈部分。
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
struct stu {
char name[20];
int age;
};
void print(struct stu arr[], int sz) {
for (int i = 0; i < sz; i++) {
struct stu currentarr = arr[i];
printf("Name: %s, Age: %d\n", currentarr.name, currentarr.age); //这个是结构体打印的方法先用for循环取到每一个数组元素结构体,然后再遍历每个结构体的成员变量
}
}
int cmp_stu_by_name(const void* p1, const void* p2) {
return strcmp((*(struct stu*)p1).name, (*(struct stu*)p2).name);
}
int main() {
struct stu arr[3] = { {"zhangsan",18},{"lisi",19},{"wangemazi",20} };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
print(arr, sz);
return 0;
}
我们现在用自己的代码来模拟qsort
前面3个用户自定义函数是用来模拟实现qsort函数的,后面的print_int和print_struct是打印作用。
#include
#include
struct stu {
char name[20];
int age;
};
int cmp1(const void* p1, const void* p2) {
return *(int*)p1 - *(int*)p2; //这个是用来比较int
}
int cmp2(const void* p1, const void* p2) {
return strcmp(((struct stu*)p1)->name ,((struct stu*)p2)->name); //这个是用来比较struct
}
void swap(char* p1, char* p2,size_t n) { //这个是用来按字节交换地址,n指的是每个袁术多少字节
for (int i = 0; i < n; i++)
{
char tmp = *p1;
*p1 = *p2;
*p2 = tmp;
p1++;
p2++;
}
}
void bubble_sort(void* base, size_t sz, size_t size, int(*cmp)(const void* p1, const void* p2)) {
for (int i = 0; i < sz - 1; i++) //控制循环趟数
{
for (int j = 0; j < sz - 1 - i; j++) //每趟两个相邻的元素进行比较
{
if (cmp((char*)base + j * size, (char*)base + (j + 1) * size) > 0)
{
swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
}
}
}
}
void print_int(int arr[], int sz) { //这个起打印功能
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
void print_struct(struct stu arr[], int sz) { //这个起打印功能
for (int i = 0; i < sz; i++) {
struct stu currentarr = arr[i];
printf("name: %s, age: %d\n", currentarr.name, currentarr.age);
}
}
void test_int() {
int arr[] = { 2,3,5,1,6,4,8,7,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz, sizeof(arr[0]),cmp1);
print_int(arr, sz);
}
void test_struct() {
struct stu arr[] = { {"zhangsan",15}, {"lisi",156},{"wangermazi",18} };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz, sizeof(arr[0]), cmp2);
print_struct(arr, sz);
}
int main() {
test_int();
test_struct();
return 0;
}
我们写的这个代码其实和qsort差不多,如果我们还想实现其他比较功能只需要自己设计一个cmp函数来实现相应的功能。