我试图通过增加一个字段(双数)来对结构数组进行排序,但似乎qsort()以某种方式破坏了此数组中的数据(在调用显示字段填充了一些随机值后打印数组) 。此外,如果我将比较器按照后代顺序更改为排序数组,则qsort不会再破坏数据,但它不会对数组进行排序 - 在调用后,所有内容都相同。 这个小程序演示了这个问题:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
/* Macro for comparing floats. */
#define CMP_PREC 0.000001
#define dbl_eq(x, y) (fabs((x) - (y)) < CMP_PREC)
/* Structure for testing. */
struct level {
double alt;
double volume;
double area;
};
/* Create array of levels with random alts.
* (Other fields are unimportant for this demo). */
struct level *create_random_arr(size_t size) {
size_t i;
struct level *lev = NULL;
lev = calloc(sizeof(*lev), size);
srand(time(NULL));
for (i = 0; i < size; i++) {
lev[i].alt = (double) rand() / 1000.0;
lev[i].volume = lev[i].area = 0.0;
}
return lev;
}
/* Prints array in format:
* [index]: alt=[alt], volume=[volume], area=[area]\n */
void print_levels(struct level *lev, int lev_cnt) {
int i;
for (i = 0; i < lev_cnt; i++) {
printf("%d: alt=%g, volume=%g, area=%g\n",
i, lev[i].alt, lev[i].volume, lev[i].area);
}
}
/* Comparator for sorting by increasing of alt. */
static int levels_compar(const void *a, const void *b) {
const struct level *al = (const struct level *) a;
const struct level *bl = (const struct level *) b;
if dbl_eq(al->alt, bl->alt) {
return 0;
} else if (al->alt < bl->alt) {
return -1;
} else {
return 1;
}
}
int main(void) {
int size = 10;
struct level *lev = NULL;
lev = create_random_arr(size);
/* Print generated array. */
print_levels(lev, size);
/* Sort array by increase. */
qsort(lev, sizeof(*lev), size, levels_compar);
/* Print result... very surprising, isn't it? */
printf("----------\n");
print_levels(lev, size);
free(lev);
return 0;
}
答案 0 :(得分:2)
您已将元素数量和元素大小参数混合到qsort
。这样就可以了:
qsort(lev, size, sizeof(*lev), levels_compar);
如上所述,您还应该在比较宏中使用fabs
。我真的不认为你需要与容差进行比较,但是,因为你并不是在寻找平等而是为了升序。我只需要使用==
并将其作为最后一个分支,因为它几乎不会发生。
答案 1 :(得分:0)
#define dbl_eq(x, y) ((x) - (y) < CMP_PREC)
我认为比较方法不正确。应该用这种方式比较绝对值:
#define dbl_eq(x, y) (fabs((x) - (y)) < CMP_PREC)
答案 2 :(得分:-1)
您在qsort中切换了参数,应该是:
qsort(lev, size , sizeof(struct level) , levels_compar);
我将*lev
替换为struct level
,因为我认为它更适合代码可读性。