1.回调函数
回调函数就是通过函数指针调用的函数。
将函数的指针(地址)作为一个参数传递给另一个函数,当这个指针被调用其所指向的函数时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外一方调用的,用于对该事件或条件进行响应。
计算器的实现:
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;
}void calc(int(*pf)(int,int))//传过来的是函数的地址,要用函数指针变量来接收
{int x = 0;int y = 0;int ret = 0;printf("请输入两个操作数:");scanf("%d %d", &x, &y);ret = pf(x, y);printf("%d\n", ret);
}int main()
{int input = 0;do{menu();printf("请选择:");scanf("%d", &input);switch (input){case 1://calc功能强大了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;
}
2.qsort使用举例
2.1使用 qsort 函数排序整形数据
#include<stdlib.h>
void print_arr(int arr[],int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");
}//cmp_int 这个函数是用来比较p1和p2指向元素的大小// cmp—函数的使用者提供,谁使用谁提供//cmp函数中的参数类型必须和 test() 函数中的qsort中的第四个参数类型保持一致才可以传过去
int cmp_int(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;}//测试qsort排序整型数据
void test1()
{int arr[10] = { 5,3,2,1,0,9,8,4,7,6 };int sz = sizeof(arr) / sizeof(arr[0]);print_arr(arr,sz);qsort(arr, sz, sizeof(arr[0]), cmp_int);//qsort 函数底层用的是快速排序print_arr(arr,sz);
}
int main()
{test1();//用来实现整型数据的排序return 0;
}
2.2使用qsort排序结构数据
//测试qsort排序结构体数据struct Stu
{char name[20];int age;};//比较2个结构体的数据???
//不能直接使用 < > == 来比较
//
//1.按照名字来比较
//2.按照年龄来比较//按照年龄来比较
int cmp_stu_by_age(const void* p1, const void* p2)
{return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;//升序// p2 p1 //降序//(*(struct Stu*)p1).age
}
//-> 仅限于结构体指针运用
//结构体指针->成员名
//结构体变量.成员名#include<string.h>
//按照姓名来比较:比较对应位置上的字母相对应的ASCII码值
//两个字符串是不能使用 > < == 来进行比较的
//比较字符串是 strcmp - string compare 返回类型和
//int cmp_stu_by_name(const void* p1, const void* p2) 一样: <0 >0 =0
//所以直接 return 0 返回
int cmp_stu_by_name(const void* p1, const void* p2)
{return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
}test2()
{struct Stu arr[] = { {"xiaoming",14},{"xiaohong",16},{"xiaolan",17} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);}test3()
{struct Stu arr[] = { {"xiaoming",14},{"xiaohong",16},{"xiaolan",17} };int sz = sizeof(arr) / sizeof(arr[0]);qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);}
int main()
{test1();//用来实现整型数据的排序test2();//用来实现结构体指针数据的排序test3();//按照结构体年龄来排序return 0;
}
3.qsort函数的模拟实现
使用回调函数,模拟实现qsort的功能(采用冒泡排序)
代码中使用 void * 的指针,是方便接收任何类型的地址,以此来实现任何类型的排序
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<string.h>int cmp_int(const void* p1, const void* p2)
{return (*(int*)p1 - *(int*)p2);
}void Swap(char *buf1, char *buf2, size_t width)
{int i = 0;for (i = 0; i < width; i++){char tmp = *buf1;*buf1 = *buf2;*buf2 = tmp;buf1++;buf2++;}}
//参照qsort(arr, sz,sizeof(arr[0]),cmp_int);来写bubble_sort2函数
void bubble_sort2(void* base, size_t sz, size_t width, int(*cmpar)(const void* p1, const void* p2))
//只希望接收p1和p2的地址,不想由任何的改变,所以加上const
{int i = 0;for (i = 0; i < sz; i++)//趟数不变,这个不变{int j = 0;for (j = 0; j < sz - 1 - i; j++)//每相邻的元素的比较不变,这个也不变{//if (arr[j] > arr[j + 1]) 不再是数组—>改变if(cmpar((char*)base+j*width,(char*)base+(j+1)*width)>0){/*int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;*///交换-->也变Swap((char*)base + j * width, (char*)base + (j + 1) * width,width);}}}
}void test3()
{int arr[10] = { 2,6,4,8,9,3,0,1,7,5 };int sz = sizeof(arr) / sizeof(arr[0]);bubble_sort2(arr, sz, sizeof(arr[0]), cmp_int);print_arr(arr, sz);
}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 test4()
{struct Stu arr[] = { {"mingxiao",25},{"hongxiao",27},{"lanxiao",23} };int sz = sizeof(arr) / sizeof(arr[0]);//bubble_sort2(arr, sz, sizeof(arr[0]), cmp_stu_by_name);bubble_sort2(arr, sz, sizeof(arr[0]), cmp_stu_by_age);//打印数组内容int i = 0;for (i = 0; i < sz; i++){printf("%s %d\n", arr[i].name, arr[i].age);}}int main()
{//test1();//冒泡排序实现数组的升序//test2();//用qsort函数来实现数组的升序test3();//自己用bubble_sort2来实现qsort函数的功能,以此来达到实现能够排序任意类型数据的目的//1.先实现bubble_sort2()函数,再进行后续的操作//2.bubble_sort2()函数里面两个相邻函数的比较以及交换test4();//用bubble_sort2()函数来实现结构体的中数据的排序return 0;
}
在Swap中用 char * 来接收是为了方便交换,特别是结构体类型的数据,大小是不确定的,可能是4字节、16字节、23字节等等,根据使用者自己编写的代码来分配大小,一个一个字节的交换可以实现单数(9)字节大小的单位的类型交换,来达到实现任意类型数据的交换。