回调函数:通过函数指针调用的函数 。当把函数指针(地址)作为参数传给另一个函数,这个指针被用来调用其指向的函数时,就称这个函数为回调函数
下面将针对回调函数机制实现代码
对一组数据进行排序,我们会传统的想到冒泡排序,比如以下代码
void Bubble(int arr[], int sz)
{
int i = 0;
for(i=0; i<sz-1; i++)
{
int j = 0;
for(j=0; j<sz-1-i; j++)
{
if(arr[j] > arr[j+1])
{
int tmp = 0;
tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
int main()
{
int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
int sz = sizeof(arr)/sizeof(arr[0]);
int i = 0;
Bubble(arr, sz);
for(i=0; i<sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
这里我们对整形数组arr进行了排序,那么如果我们想要对浮点型、结构体类型数组进行排序呢?
那么冒泡排序就不能够实现我们想要的功能了
这里我们将使用qsort库函数——对不同类型的数组进行排序
void qsort (void* base, size_t num, size_t size,int (*compar)(const void*,const void*));
解释说明:
qsort(待排序数组首元素地址,待排序数组元素个数,待排序数组每个元素大小(byte),函数名指针()该函数用于比较两个void*类型的元素,返回类型为int))
这里举个例子,我们用qsort来实现整形数组排序
int cmp_int(const void*e1, const void*e2)
{
//void*类型的指针,不能进行解引用操作,需要强制转换
return *(int*)e1 - *(int*)e2;
}
void test1()
{
int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
int sz = sizeof(arr)/sizeof(arr[0]);
int i = 0;
qsort(arr, sz, sizeof(arr[0]), cmp_int);
for(i=0; i<sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
test1();
return 0;
}
这里get到了新知识——void *类型的指针
- void*类型的指针可以接收任意类型的指针
- void*类型的指针不可以进行解引用操作
- void*类型的指针不能进行加减整数的操作
如果我们想要对一组浮点类型的数组又该如何进行排序呢?
int cmp_float(const void*e1, const void*e2)
{
//因为返回类型是int所以要进行强制类型转换
return ((int)(*(float*)e1 - *(float*)e2));
}
void test2()
{
float f[] = {9.0, 8.0, 7.0, 6.0, 5.0};
int sz = sizeof(f)/sizeof(f[0]);
int i = 0;
qsort(f, sz, sizeof(f[0]), cmp_float);
for(i=0; i<sz; i++)
{
printf("%f ", f[i]);
}
}
只需注意一点:浮点类型要进行强制类型转换,因为返回类型为int整型
对于结构体数组,又将如何实现呢?
struct Stu
{
char name[20];
int age;
};
int cmp_stu_by_age(const void*e1, const void*e2)
{
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
void test3()
{
struct Stu s[3] = {{"zhangsan", 30}, {"lisi", 20}, {"wangwu", 10}};
int sz = sizeof(s)/sizeof(s[0]);
qsort(s, sz, sizeof(s[0]), cmp_stu_by_age);
}
int main()
{
test3();
return 0;
}
这里我们用年龄age比较,当然也可以用名字进行比较
int cmp_stu_by_name(const void*e1, const void*e2)
{
//名字比较=字符串比较——strcmp
return strcmp(((struct Stu*)e1)->name,((struct Stu*)e2)->name);
}
注:名字比较=两个字符串比较,需用到库函数strcmp
至此,就了解qsort函数是如何使用的了,下面,我们将使用回调函数,模拟qsort(冒泡方法)
int cmp_int(const void*e1, const void*e2)
{
//void*类型的指针,不能进行解引用操作,需要强制转换
return *(int*)e1 - *(int*)e2;
}
void Swap(char* buf1, char* buf2, int width)
{
int i = 0;
for(i=0; i<width; i++)
{
int tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
void Bubble_Sort(void* base, int sz, int width, int(*cmp)(const void* e1, const void* e2))
{
int i = 0;
for(i=0; i<sz-1; i++)
{
int j = 0;
for(j=0; j<sz-1-i; j++)
{
//两个元素比较
//因为不知道要比较的元素大小,因此进行强制类型转换char*以一个字节为单位进行运算
if(cmp((char*)base+j*width, (char*)base+(j+1)*width)>0)
Swap((char*)base+j*width, (char*)base+(j+1)*width, width);
}
}
}
void test1()
{
int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
int sz = sizeof(arr)/sizeof(arr[0]);
int i = 0;
Bubble_Sort(arr, sz, sizeof(arr[0]), cmp_int);
for(i=0; i<sz; i++)
{
printf("%d ", arr[i]);
}
}
int main()
{
test1();
return 0;
}
en,我只能说:晕