指针(4)
- 1.回调函数是什么?
- 2.qsprt使用举例
- 2.1使用qsort函数排序整型数据
- 2.2使用qsort函数排序结构体数据
- 3.qsort函数的模拟实现
1.回调函数是什么?
回调函数就是一个通过函数指针调用的函数
- 如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。
- 回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
在指针(3)中我们写的计算机的实现的代码中,有一部分代码是重复出现的,其中虽然执行计算的逻辑是区别的,但是输入输出操作是冗余的,有没有办法,简化⼀些呢?
因为在计算机的实现的代码中,只有调用函数的逻辑是有差异的,可以把调用的函数的地址以参数的形式传递过去,使用函数指针接收,函数指针指向什么函数就调用什么函数,这里其实使用的就是回调函数的功能。
//使用回调函数之前
#include<stdio.h>//实现加法
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 meun()
{printf("-------------------\n");printf("--- 1.Add 2.Sub ---\n");printf("--- 3.Mul 4.Div ---\n");printf("--- 0.Exit ---\n");printf("-------------------\n");
}int main()
{int x, y = 0;int input = 0;int ret = 0;do{meun();printf("请选择:>");scanf("%d", &input);switch (input){default:printf("选择错误,请重新选择\n");break;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;}} while (input);return 0;
}
//使用回调函数之后
#include<stdio.h>//实现加法
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 meun()
{printf("-------------------\n");printf("--- 1.Add 2.Sub ---\n");printf("--- 3.Mul 4.Div ---\n");printf("--- 0.Exit ---\n");printf("-------------------\n");
}//回调函数
void calc(int (*pf)(int, int))
{int x, y = 0;int ret = 0;printf("请输入两个数: ");scanf("%d %d", &x, &y);ret = pf(x, y);printf("ret = %d\n", ret);
}int main()
{int input = 0;do{meun();printf("请选择:>");scanf("%d", &input);switch (input){default:printf("选择错误,请重新选择\n");break;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;}} while (input);return 0;
}
2.qsprt使用举例
2.1使用qsort函数排序整型数据
#include<stdio.h>
//qsort()函数的使用这得实现一个比较函数
int int_cmp(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}int main()
{int arr[] = { 9,8,7,6,5,4,3,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);//比较qsort(arr, sz, sizeof(arr[0]), int_cmp);//打印int i = 0;for ( i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");//0 1 2 3 4 5 6 7 8 9return 0;
}
2.2使用qsort函数排序结构体数据
#include<stdio.h>
#include<string.h>struct Stu //学生
{char name[10];//名字int age;//年龄
};//假如按照年龄来比较
int cmp_stu_by_age(const void* p1, const void* p2)
{return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}//假如按照名字来比较
//strcmp() - 是库函数,是专门来比较两个字符串的大小的
int cmp_stu_by_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}//假如按照年龄来比较
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);
}//假如按照名字来比较
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);
}int main()
{test1();test2();return 0;
}
3.qsort函数的模拟实现
使用回调函数,模拟实现qsort(采用冒泡的排序方式)
代码1:
//使用bubble_sort函数排序整型数据
#include<stdio.h>int int_cmp(const void* p1, const void* p2)
{return ((*(int*)p1) - (*(int*)p2));
}//交换
void Swap(void* buf1, void* buf2, int width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *((char*)buf1 + i);*((char*)buf1 + i) = *((char*)buf2 + i);*((char*)buf2 + i) = tmp;}
}
//qsort函数的模拟实现
void bubble_sort(void* base, int sz, int width, int (*cmp)(void*, void*))
{int i = 0;int j = 0;for (i = 0; i < sz - 1; i++){for (j = 0; j < sz - 1 - i; j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}int main()
{int arr[] = { 9,8,7,6,5,4,3,2,1,0 };int sz = sizeof(arr) / sizeof(arr[0]);//使用回调函数,模拟实现qsortbubble_sort(arr, sz, sizeof(arr[0]), int_cmp);//打印for (size_t i = 0; i < sz; i++){printf("%d ", arr[i]);//0 1 2 3 4 5 6 7 8 9}printf("\n");return 0;
}
代码2:
//使用bubble_sort函数排序结构体数据
#include<stdio.h>
#include<string.h>struct Stu //学生
{char name[10];//名字int age;//年龄
};//交换
void Swap(void* buf1, void* buf2, int width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *((char*)buf1 + i);*((char*)buf1 + i) = *((char*)buf2 + i);*((char*)buf2 + i) = tmp;}
}
//qsort函数的模拟实现
void bubble_sort(void* base, int sz, int width, int (*cmp)(void*, void*))
{int i = 0;int j = 0;for (i = 0; i < sz - 1; i++){for (j = 0; j < sz - 1 - i; j++){if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0){Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);}}}
}//假如按照年龄来比较
int cmp_stu_by_age(const void* p1, const void* p2)
{return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
}//假如按照名字来比较
//strcmp() - 是库函数,是专门来比较两个字符串的大小的
int cmp_stu_by_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}//假如按照年龄来比较
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);bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}//假如按照名字来比较
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);bubble_sort(s, sz, sizeof(s[0]), cmp_stu_by_name);
}int main()
{test1();test2();return 0;
}