我想通过增加一个字段(双数)来对结构数组进行排序,但似乎qsort()以某种方式破坏了此数组中的数据调用显示字段填充了一些随机值)。此外,如果我将比较器更改为按后代顺序排序数组,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;
}
我不同意你的替换。 'sizeof * lev'与'lev'指向的类型是不可知的,并且在类型的变化中是强健的。如果类型发生变化并且编译器无法为您自动诊断,那么对该类型进行硬编码将导致严重的破坏(与OP所经历的相当)。 –
@R。通过使用struct,您可以通过编译器错误立即查看刚刚破解的代码(在什么范围内),从而获得额外的好处。并且字符串查找/替换在这些日子里不是很难。可读性>懒惰 – this
不,你不知道。使用struct,您在运行时不会出错,并且可怕的UB。随着OP的版本(固定订单)就像我推荐的那样,代码会自动工作。 –