深入理解指针5
回调函数
回调函数就是一个通过函数指针调用的函数
如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数
回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void fun() {printf("hehe\n");
}
void test(void(*pf)()) {if (1)pf();
}
int main() {test(fun);return 0;
}
fun为回调函数
将上篇博文的计算器进行简化:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void menu() {printf("**********************\n");printf("*** 1.add 2.sub ***\n");printf("*** 3.mul 4.div ***\n");printf("*** 0.exit ***\n");printf("**********************\n");
}
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;
}
Calc(int (*pf)(int,int)){int a = 0, b = 0, r = 0;printf("请输入两个操作数");scanf("%d%d", &a, &b);r = pf(a, b);printf("%d\n", r);
}
//写一个简易的计算器
//1.实现加减乘除
//2.不需要退出程序可以继续计算
int main() {int input = 0;do{menu();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:printf("退出计算器");break;default:printf("选择错误,重新选择");break;}} while (input);return 0;
}
qsort(快速排序)
是一个库函数,用来对数据排序
不管是什么类型的数据,它都能排序
void qsort(void* base,size_t num,size_t size,int (*cmp)(const void*,const void*))
void* base//base指向了待排序数组的第一个元素
//qsort函数无法预测你会使用这个函数排序什么类型的数据
size_t num//待排序数据的元素个数
size_t size//待排序数组的第一个元素大小
int (*cmp)(const void*,const void*)//函数指针——指针指向的函数,可以比较base指向的数组中的任意两个元素的大小
//将比较的方法抽离出来,qsort的使用者提供两个元素的比较函数
例1:
升序排序整数:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
//e1指向一个整数,e2指向另外一个整数
int cmp_int(const void* e1, const void* e2) {return *(int*)e1 - *(int*)e2;
}
void print_arr(int arr[], int sz) {int i = 0;for (i = 0;i < sz;i++) {printf("%d ", arr[i]);}printf("\n");
}
int main() {int arr[10] = { 3,1,5,2,9,8,6,4,0,7 };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz,sizeof(arr[0]),cmp_int);print_arr(arr, sz);return 0;
}
如果想要降序进行排序:
int cmp_int(const void* e1, const void* e2) {return *(int*)e2 - *(int*)e1;
}
即可
例2:
void test3() {struct Stu s = { "cuihua",18 };struct Stu* ps = &s;//结构体指针变量printf("%s\n", (*ps).name);printf("%s\n", *ps->name);//结构体变量 .成员名//结构体指针变量 ->成员名
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Stu
{char name[20];int age;
};
//按照名字来比较
int cmp_stu_by_name(const void* e1, const void* e2) {return strcmp((*(struct Stu*)e1).name , (*(struct Stu*)e2).name);//return strcmp(((struct Stu*)e1)->name , ((struct Stu*)e2)->name);//strcmp比较两个字符串的大小,是按照对应位置上字符的ASCII码值比较的
}
//按照年龄来比较
int cmp_stu_by_age(const void* e1, const void* e2) {return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
void test2() {struct Stu arr[3] = { {"zhangsan",18},{"lisi",35},{"wangwu",12} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}void test4() {struct Stu arr[3] = { {"zhangsan",18},{"lisi",35},{"wangwu",12} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}int main() {test2();test4();return 0;
}
使用回调函数,模拟实现qsort
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int cmp_int(const void* e1, const void* e2) {return *(int*)e1 - *(int*)e2;
}
void Swap(char* buf1, char* buf2, size_t n) {int i = 0;for (i = 0;i < n;i++) {char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf2++;buf1++;}
}
void bubble_sort(void* base, size_t sz,size_t width,int(*cmp)(const void* e1,const void* e2)) {int i = 0;int j = 0;for (i = 0;i < sz - 1;i++) {int flag = 0;//假设已经有序for (j = 0;j < sz - 1 - i;j++) {if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0) {flag = 1;Swap((char*)base + j * width , (char*)base + (j + 1) * width, width);}if (flag == 0) {break;}}}
}
void print_arr(int arr[], int sz) {int i = 0;for (i = 0;i < sz;i++) {printf("%d ", arr[i]);}printf("\n");
}
int main() {//排成升序int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort(arr, sz,sizeof(arr[0]),cmp_int);print_arr(arr, sz);return 0;
}