int compare (const void * a, const void * b)
{
return ( (int) (*(float*)a - *(float*)b) );
}
当我想使用qsort
函数时,我应该按照我的理解写这种形式的比较函数。那么,为什么我们在比较函数的参数之前使用void呢?
并且,这是比较函数标准及其参数和花括号中的代码,还是我们可以通过我们的愿望简单地更改代码甚至参数?
答案 0 :(得分:2)
不,您无法更改参数或返回类型。 但是当然你可以改变功能的'代码'。你可以比较你想要的任何东西。唯一重要的是返回值:
如果第一个传递的参数比第二个更低,则返回值应为<0
,如果两者都是相同的,则返回== 0
,如果第一个传递参数为'更大',则返回>0
。
例如,你可以使用带有这样字符串的qsort函数:
int compare (const void * a, const void * b)
{
return strcmp((char *) a, (char *) b);
}
答案 1 :(得分:1)
在C void *
中意味着您可以在其中存储任何类型的指针。想象一下,你想要对字符串列表(char *)进行排序,你会做什么?为qsort
数据类型编写一个int
实现,为char *
编写一个实现?在这里,使用qsort
编写void *
,以便您可以比较不同类型的不同内容。
是的,参数类型是标准的。请参阅stdlib.h
中的定义。
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
答案 2 :(得分:0)
使用void指针的原因是因为它们可以转换为其他指针类型,然后返回到void指针而不会出现任何问题。
答案 3 :(得分:0)
qsort
正在使用允许您使用任意数据类型的callback
,然后在比较器内部,您可以按照自己喜欢的方式对它们进行排序。您只需要遵守API。
这提供了很大的灵活性。下面的代码是一个简化的示例,但它可以扩展为轻松地对任意数据结构进行排序。在所有情况下,使用相同的qsort
函数,即调用相同地址的相同函数。
以下设计的例子可能有助于理解为什么它具有灵活性。注意,比较器int
可以扩展为结构表,而不是func_table
,而每个比较器都有比较器类型。重申一下,在每种情况下都会调用相同的qsort函数,它的回调函数地址会改变为在运行时对数据进行排序所需的正确函数。
以下程序按随机方向对数组进行排序,从表格中选择排序函数。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
int values[] = { 3 , 88 , 52 , 285, 63 , 288 , 576 , 10, 21 , 5,343 , 38 , 55 , 100, 552 , 85 };
typedef int (*comparator)(const void * a, const void * b);
int cmp_reverse(const void * a, const void * b) {
return ( *(int*)b - *(int*)a );
}
int cmp_int(const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
static comparator func_table[2];
int main(void) {
srand(time(NULL));
size_t int_arr_size = ARRAY_SIZE(values);
int n = 0;
int i = 0;
func_table[0] = cmp_int;
func_table[1] = cmp_reverse;
while(i++ < 10) {
int order = rand() % 2 == 0;
printf("order: %d %s ", order, order == 0 ? ">" : "<");
qsort(values, int_arr_size, sizeof(int), func_table[order]);
for( n = 0 ; n < int_arr_size; n++ ) {
printf("%d ", values[n]);
}
printf("<\n");
}
return 0;
}