如何使用qsort

时间:2018-07-07 15:59:50

标签: c pointers qsort

我正在尝试使用qsort对包含指针的结构进行排序。比较功能有问题吗?我该如何解决,以便可以根据抄送进行排序。

代码如下:

#include <stdlib.h>
#include <string.h>

typedef enum {
    PETROL,
    DIESEL,
    ELECTRIC,
    LPG,
    BIOFUEL,
    OTHER
} fuel_t;

typedef struct car_tag {
    unsigned cc;
    fuel_t fueltype;
} car_t;


typedef struct fleet_tag {
    car_t ** cars;
    size_t n_cars;
} fleet_t;

int car_comp(const void * vp1, const void * vp2) {
    const car_t* const c1 = vp1;
    const car_t* const c2 = vp2;
    if (c1->cc > c2->cc)
        return -1;
    else if (c1->cc < c2->cc)
        return 1;
    else {
        return 0;
    }
}


int main() {
    car_t array[] = {
        { 600, PETROL},
        {1200, PETROL},
        {1000, PETROL},
        {1600, DIESEL},
        {1000, ELECTRIC}
    };

    int size = sizeof(array) / sizeof(array[0]);

    fleet_t fl;
    fl.n_cars = size;
    fl.cars = malloc(size * sizeof(car_t));

    for (int i = 0; i < size; i++) {
        car_t* pc = malloc(sizeof(car_t));
        memcpy(pc, &array[i], sizeof(car_t));
        fl.cars[i] = pc;
    }

    // how to sort cars by cc
    qsort(&fl, fl.n_cars, sizeof(car_t), car_comp);

    // sort function doesn't correctly sort fleet of cars by cc
}

1 个答案:

答案 0 :(得分:1)

我完全没有看到在此代码 中需要为每个待分类汽车进行动态分配和memcpy调用。

您要建立一个指针床(一个指针序列),所以为什么不分配它(您在做什么),然后在其中存储array中每个元素的地址。然后,定制比较器以处理要发送的内容:指针的地址(指向指针的指针)并相应地设置取消引用

此外,您应该将fl.cars传递给qsort,而不是&fl,并且其中的sizeof参数也是错误的。

最后,我不知道您是否有意在比较器中使用大于逻辑的堆栈,但这正是您最终的目的。

示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef enum {
    PETROL,
    DIESEL,
    ELECTRIC,
    LPG,
    BIOFUEL,
    OTHER
} fuel_t;

typedef struct car_tag {
    unsigned cc;
    fuel_t fueltype;
} car_t;


typedef struct fleet_tag {
    car_t ** cars;
    size_t n_cars;
} fleet_t;

int car_comp(const void * vp1, const void * vp2)
{
    const car_t * const *pc1 = vp1;
    const car_t * const *pc2 = vp2;

    if ((*pc1)->cc > (*pc2)->cc)
        return -1;

    if ((*pc1)->cc < (*pc2)->cc)
        return 1;

    return 0;
}


int main() {
    car_t array[] = {
        { 600, PETROL},
        {1200, PETROL},
        {1000, PETROL},
        {1600, DIESEL},
        {1000, ELECTRIC}
    };

    int size = sizeof(array) / sizeof(array[0]);

    fleet_t fl;
    fl.n_cars = size;
    fl.cars = malloc(size * sizeof *fl.cars);

    for (int i = 0; i < size; i++)
        fl.cars[i] = array+i;

    // how to sort cars by cc
    qsort(fl.cars, fl.n_cars, sizeof *fl.cars, car_comp);

    for (int i=0; i<size; ++i)
        printf("%d (%u, %d)\n", i+1, fl.cars[i]->cc, fl.cars[i]->fueltype);

    free(fl.cars);

    return EXIT_SUCCESS;
}

输出

1 (1600, 1)
2 (1200, 0)
3 (1000, 0)
4 (1000, 2)
5 (600, 0)

qsort的工作原理是:向其提供一系列“事物”,长度说明存在“事物”的数量,大小指示序列中每个“事物” 的大小 ,最后是一个比较器函数,该函数将在算法执行过程中馈入每个“事物”的地址

在您的情况下,您的“事物”是指向car_t结构的指针。实际上,

  • 您的序列是一个动态的指针数组;您的“事物”是指向car_t的指针。
  • 您的长度是size
  • 每个“事物”的大小就是指针的大小。
  • 您的比较器将访问您的两个对象的地址(因此,有两个 pointers ,因此是指向指针的指针),并相应地执行操作。

因此,呼叫变为:

qsort(fl.cars, fl.n_cars, sizeof *fl.cars, car_comp);

最后,请注意原始的array保持不变。排序仅修改了您的指针床。这可能是合乎需要的,我希望您了解它是如何工作的。