本文共 3337 字,大约阅读时间需要 11 分钟。
回调函数就是⼀个通过函数指针调⽤的函数。如果你把函数的指针(地址)作为参数传递给另⼀个函数,当这个指针被⽤来调⽤其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现⽅直接调⽤,⽽是在特定的事件或条件发⽣时由另外的⼀⽅调⽤的,⽤于对该事件或条件进⾏响应。qsort函数就是根据回调函数实现的。
接下来介绍一下qsort函数:
1.编译器函数库自带的快速排序函数。
2.使用qsort()排序并用 bsearch()搜索是一个比较常用的组合,使用方便快捷。
3.qsort 的函数原型是:void qsort(void*base, size_t num, size_t width, int(__cdecl*compare)(const void*, const void*));
各参数:1 待排序数组首地址 ;2 数组中待排序元素数量 ;3 各元素的占用空间大小; 4 指向函数的指针(待定函数的比较方法)
int(__cdecl*compare)()就是回调函数,将函数本身作为参数传递给对应的方法,然后在特定的时候再调用。
现在我们模仿qsort的功能实现一个通用的冒泡排序:
#include#include #include //回调函数int int_cmp(const void *p1, const void *p2){ int *_p1 = (int *)p1; int *_p2 = (int *)p2; if (*_p1 < *_p2) { return 1;//降序 } else if (*_p1 > *_p2) { return -1; } else { return 0; }}//交换void swap(char *x, char *y, int width){ while (width--) { *x^=*y; *y^=*x; *x^=*y; x++; y++; }}//实现qsortvoid my_qsort(void *arr, int num, int width, int(*cmp)(void *, void *)){ assert(arr); assert(cmp); int i = 0; for (; i < num - 1; i++) { int j = 0; for (j = 0; j < num - 1 - i; j++) { //调用函数判断两个操作数大小。 //cmp()传参只需将操作数的地址传过去。 if (cmp((char *)arr + j*width, (char *)arr + (j + 1)*width)>0) //这里是任意类型,所以不能整体交换,只能局部按字节交换,达到整体交换的目的。 { swap((char *)arr + j*width, (char *)arr + (j + 1)*width, width); } } }}int main(){ int arr[] = { 1, 5, 4, 6, 8, 0, 9, 2, 7, 3 }; int size = sizeof(arr) / sizeof(arr[0]); int i = 0; my_qsort(arr, size, sizeof(int), int_cmp); for (i = 0; i < size; i++) { printf("%d\n", arr[i]);//9876543210 } system("pause"); return 0;}
通过上面模拟实现我们了解到qsort能够进行排序,接下来我们来练习使用qsort函数排序各种类型的数据。
1.int 类型:int int_cmp(const void *p1, const void *p2){ int *_p1 = (int *)p1; int *_p2 = (int *)p2; if (*_p1 < *_p2) { return 1;//降序 } else if (*_p1 > *_p2) { return -1; } else { return 0; }}int main(){ int arr[] = { 1, 5, 4, 6, 8, 0, 9, 2, 7, 3 }; int size = sizeof(arr) / sizeof(arr[0]); int i = 0; qsort(arr, size, sizeof(int), int_cmp); for (i = 0; i < size; i++) { printf("%d\n", arr[i]);//9876543210 } system("pause"); return 0;}
//2.double类型:int double_cmp(const void *p1, const void *p2){ double *_p1 = (double *)p1; double *_p2 = (double *)p2; if (*_p1 < *_p2) { return -1;//升序 } else if (*_p1 > *_p2) { return 1; } else { return 0; }}int main(){ double arr[] = { 10.3, 5.0, 4.345, 6.66, 8.9, 0.1, 9.4, 2.5, 7.35, 3.09 }; int size = sizeof(arr) / sizeof(arr[0]); int i = 0; qsort(arr, size, sizeof(double), double_cmp); for (i = 0; i < size; i++) { printf("%f ", arr[i]); }//0.100000 2.500000 3.090000 4.345000 5.000000 6.660000 7.350000 8.900000 9.400000 10.300000 请按任意键继续. . . system("pause"); return 0;}
//3.排序字符char类型:int char_cmp(const void *p1, const void *p2){ char *_p1 = (char *)p1; char *_p2 = (char *)p2; if (*_p1 < *_p2) { return -1;//升序 } else if (*_p1 > *_p2) { return 1; } else { return 0; }}int main(){ char arr[] = { 'v','A','g','t','H','M','d' }; int size = sizeof(arr) / sizeof(arr[0]); int i = 0; qsort(arr, size, sizeof(char), char_cmp); for (i = 0; i < size; i++) { printf("%c ", arr[i]); } //A H M d g t v 请按任意键继续. . . system("pause"); return 0;}
注意字符串传参问题: 因为char*是字符数组,后面跟的相当于字符数组名,而指向字符数组(字符串)的指针,那就再加一星号,char**就是指向字符数组的指针了(当然它也可以表示字符串数组)。函数定义时使用char **s1和char **s2作参数,函数内容不需要变。使用这两个形参后,在函数体中,*s1表示指针s1指向的字符数组(字符串),*s2表示指针s2指向的字符数组(字符串),因此,函数体不需要做改变。
转载地址:http://vmypi.baihongyu.com/