qsort()比较结构数组:非常奇怪的行为

时间:2013-11-22 20:44:19

标签: c arrays struct 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;
}

3 个答案:

答案 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,因为我认为它更适合代码可读性。