我一直在寻找一种在C中对数组子集进行排序的方法,而不将元素移动到临时数组,然后将它们复制回来。我可能对qsort有一个不好的理解,但我认为下面的代码应该有效:
qsort(&my_struct_arr[1],3,sizeof(my_struct),my_struct_cmp);
//my_struct_arr is a 4 element array, where i want to sort from position 1 to 3
int my_struct_cmp(const void *a, const void *b)
{
my_struct A=*(my_struct*)a, B=*(my_struct*)b;
if(A.x-B.x < 0.01) return A.y-B.y;
return A.x-B.x;
}
typedef struct foo
{
float x, y;
} my_struct;
问题是,它不起作用。
更新1: 好的,我看到我对这个问题并不完全清楚。我把数组从第1位到第3位初始化,所以我有一个包含这样的元素的数组:
{{ValueFromPreviousIteration.x,ValueFromPreviousIteration.y},{x1,y1},{x2,y2},{x3,y3}}
我的问题是,上面调用的qsort将对整个数组进行排序,而我只想对它的最后3个元素进行排序。
答案 0 :(得分:1)
您的比较功能不稳定。它可以返回不同的结果,具体取决于结构传递的顺序。
考虑以下结构值:
my_struct m = { -3.021, 30 };
my_struct n = { 3.010, 0 };
int main(void)
{
int comp1 = my_struct_cmp( &m, &n);
int comp2 = my_struct_cmp( &n, &m);
printf( "%d %d\n", comp1, comp2);
return 0;
}
第一次比较表示m > n
,而第二次表示n > m
。这种行为混淆了qsort()
。
答案 1 :(得分:0)
int my_struct_cmp
返回int。
你要回归float
。它将自动转换为int,可能是0
。
这就是为什么它不起作用。
答案 2 :(得分:0)
if(A.x-B.x < 0.01)
是否正确?您可能需要if(A.x-B.x < 0.0)
。使用0.0
代替0.01
答案 3 :(得分:0)
我认为您需要将比较功能修改为
int my_struct_cmp(const void* a, const void* b)
{
const my_struct A = *(my_struct*)a, B = *(my_struct*)b;
return fabs(A.x - B.x) >= 0.01 ? (A.x > B.x) - (A.x < B.x) : (A.y > B.y) - (A.y < B.y);
}
或(不那么便携)
int my_struct_cmp(const void* a, const void* b)
{
const my_struct A = *(my_struct*)a, B = *(my_struct*)b;
return fabs(A.x - B.x) >= 0.01 ? copysign(1, A.x - B.x) : copysign(1, A.y - B.y);
}
否则,存在许多特定于平台的解决方案,用于确定浮动的符号而不进行比较,实际上这不是一件小事。
这应该快一点:
int my_struct_cmp(const void* a, const void* b)
{
const my_struct *A = (my_struct*)a, *B = (my_struct*)b;
return fabs(A->x - B->x) >= 0.01 ? (A->x > B->x) - (A->x < B->x) : (A->y > B->y) - (A->y < B->y);
}