什么是回调函数?
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
接下来让我们运用qsort函数来加深对回调函数的理解;
qsort是编译器函数库自带的快速排序函数。
使用qsort()排序并用 bsearch()搜索是一个比较常用的组合,使用方便快捷。
qsort 的函数原型是
void qsort(void*base,size_t num,size_t width,int(__cdecl*compare)(const void*,const void*));
各参数:1 待排序数组首地址 2 数组中待排序元素数量 3 各元素的占用空间大小 4 指向函数的指针 其中base是排序的一个集合数组,num是这个数组元素的个数,width是一个元素的大小,comp是一个比较函数。比如:对一个长为1000的数组进行排序时,int a[1000]; 那么base应为a,num应为 1000,width应为 sizeof(int),comp函数随自己的命名。qsort(a,1000,sizeof(int),comp);
int comp(const void*a,const void*b) { return *(int*)a-*(int*)b; }
Comp 函数编写作用是由小到大排序,这里只是需要comp函数返回正值、负值或者零即可。
前面介绍了qsrot函数,我们知道了我们知道qsort是通过回调函数来实现其功能,故而我们通过回调函数可以排序各种类型的数据;
代码实现:
#include<stdio.h> #include<windows.h> int cmp1(const void *a,const void *b) { return *(int*)a - *(int*)b;//a>b返回正值 } int cmp2(const void *a,const void *b) { return *(char*)a - *(char*)b; } int cmp3(const void *a, const void *b) { return strcmp(*(char **)a,*(char **)b); } int cmp4(const void *a, const void *b) { return *(double*)a - *(double*)b; } int main() { int a[] = { 0,1,9,3,4,5,6,7,8,2 };//整形 char b[] = { 'b','a','c','d','e' };//字符 char *str[] = { "bbbb","aaaa","dddd","cccc" };//字符串 double arr[] = { 1.0,6.0,2.0,3.3,5.5 };//浮点型 qsort(a, 10, sizeof(int), cmp1); qsort(b, 5, sizeof(char), cmp2); qsort(str, 4, sizeof(char*), cmp3); qsort(arr, 5, sizeof(double), cmp4); int i = 0; for (i = 0;i < 10;i++) { printf("%d ", a[i]); } printf("\n"); for (i = 0;i < 5;i++) { printf("%c ", b[i]); } printf("\n"); for (i = 0;i < 4;i++) { printf("%s ", str[i]); } printf("\n"); for (i = 0;i < 5;i++) { printf("%f ", arr[i]); } printf("\n"); system("pause"); return 0; }
运行结果如下:
通过以上这些回调函数,我们可以得出写这些回调函数的规律:
1)返回类型 int ,其实是将两个参数比较完的结果返回;
2)参数类型 void*,void *可以接受任意类型的实参;
3)比较两个参数的大小时,需将其转换成相应的类型,例如数组是 int,此时参数需强转成(int *);
4)注意:在比较字符串大小时,不能将其直接比较,在这里需要使用strcmp函数
模仿qsort的功能实现一个通用的冒泡排序。
代码如下:
#include <stdio.h> #include<windows.h> int cmp2(const void *x,const void *y) { return *(int *)x - *(int *)y; } int cmp1(const void *a, const void *b) { return strcmp(*(char **)a, *(char **)b); } void Swap(void *p1, void *p2, int size) { int i = 0; for (i = 0; i < size; i++) { char tmp = *((char *)p1 + i); *((char *)p1 + i) = *((char *)p2 + i); *((char *)p2 + i) = tmp; } } void Bubble(void *base, int count, int size, int(*cmp)(void *, void *)) { int i = 0; int j = 0; for (i = 0; i < count - 1; i++) { for (j = 0; j < count - 1; j++) { if (cmp((char *)base + j * size, (char *)base + (j + 1)*size)>0) { Swap((char *)base + j * size, (char *)base + (j + 1)*size, size); } } } } int main() { int i = 0; int a[] = { 4,5,6,7,8,9,1,2,0,3 }; char *s[5] = { "aaaa", "dddd", "iiii", "cccc", "ffff" }; Bubble(a, sizeof(a) / sizeof(a[0]), sizeof(int), cmp2); Bubble(s,sizeof(s)/sizeof(*s), sizeof(char *), cmp1); for (i = 0; i <sizeof(s) / sizeof(*s); i++) { printf("%s ", s[i]); } printf("\n"); for (i = 0; i < sizeof(a) / sizeof(a[0]); i++) { printf("%d ", a[i]); } printf("\n"); system("pause"); return 0; }
结果如下: