需要帮助使用 qsort 对 C 中的结构数组进行排序

Need help sorting an array of structures in C using qsort

我有这个结构。

struct Transport
{
   int id;
   float Price;
};

在这里我将数据读入结构数组。

void read (struct Transport **Car, int *m)
{
    int i;
    printf("Insert total number of cars: ");
    scanf("%d",m);
    *Car=(struct Transport*) malloc ((*m)*3*sizeof(struct Transport));               

    for(i=1; i<=*m; i++)
    {
       (*Car)[i].id=i;
       printf("Price: ");
       scanf("%f",&(*Car)[i].Price);
       printf("\n");
    }
}

这里是显示功能。

void display(struct Transport *Car,int m)
{
    int i;
    for(i=1; i<=m; i++)
    {
        printf("Entry #%d: \n",i);
        printf("Price: %2.2f\n",(Car+i)->Price);
        printf("\n");
    }
}

现在 problem.I 必须按价格字段对数据进行排序。到目前为止,我已经试过了,但它什么也没做。

int struct_cmp_by_price(const void *a, const void *b)
{
    struct Transport *ia = (struct Transport *)a;
    struct Transport *ib = (struct Transport *)b;
    return (int)(100.f*ia->Price - 100.f*ib->Price);
}

这是主要的样子。

int main()
{
    int m;
    struct Transport *Car;
    read(&Car,&m);
    qsort(Car, m, sizeof(struct Transport), struct_cmp_by_price);
    display(Car,m);
    return 0;
}

谁能帮帮我?

您的代码中存在多个问题:

  • 你在read()中分配了太多的内存,你不需要在C中转换malloc()的return值,但你应该检查分配失败。你应该改用:

    *Car = calloc(*m, sizeof(struct Transport));
    if (*Car == NULL) {
        fprintf(stderr, "cannot allocate memory for %d structures\n", *m);
        exit(1);
    }
    
  • 您不应使用 read 作为函数名,因为它是系统调用的名称,可能与该函数的标准库使用冲突。使用 readTransport.

  • 索引是 0 基于 C 的。而不是 for(i=1; i<=*m; i++),使用:

    for (i = 0; i < *m; i++)
    
  • 比较函数不能使用减法技巧。事实上,减法技巧只能用于整数类型int。改用这个:

    int struct_cmp_by_price(const void *a, const void *b) {
        const struct Transport *ia = a;
        const struct Transport *ib = b;
        return (ia->Price > ib->Price) - (ia->Price < ib->Price);
    }
    
  • 您应该测试 scanf() 的 return 值以检测无效输入。 Price 成员在转换失败的情况下保持未初始化,这会导致未定义的行为,除非您使用 calloc(),但结果仍然没有意义。

您也可以尝试使用两个单独的结构体,使指针操作更容易处理。

这样的事情给出了正确的想法:

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

typedef struct {
    int id;
    float price;
} transport_t;

typedef struct {
    transport_t *Cars;
    int numcars;
} Cars_t;

Cars_t *initialize_struct(void);
void read(Cars_t *Car);
void display(Cars_t *Car);
int price_cmp(const void *x, const void *y);

int 
main(void) {
    Cars_t *Car;

    Car = initialize_struct();

    read(Car);

    printf("Before:\n");
    display(Car);

    qsort(Car->Cars, Car->numcars, sizeof(transport_t), price_cmp);

    printf("\nAfter:\n");
    display(Car);

    free(Car->Cars);
    free(Car);

    return 0;
}

void
read(Cars_t *Car) {
    int i, count = 0;

    printf("Insert total number of cars: ");
    if (scanf("%d", &(Car->numcars)) != 1) {
        printf("Invalid entry\n");
        exit(EXIT_FAILURE);
    }

    Car->Cars = calloc(Car->numcars, sizeof(transport_t));
    if (Car->Cars == NULL) {
        fprintf(stderr, "Issue allocating memory for %d members", Car->numcars);
        exit(EXIT_FAILURE);
    }

    for (i = 1; i <= Car->numcars; i++) {
        Car->Cars[count].id = i;
        printf("Car id %d\n", Car->Cars[count].id);

        printf("Price: ");
        scanf("%f", &(Car->Cars[count].price));

        count++;

        printf("\n");
    }
}

void
display(Cars_t *Car) {
    int i;

    for (i = 0; i < Car->numcars; i++) {
        printf("Car id: %d, Car price: %2.2f\n", 
                Car->Cars[i].id, Car->Cars[i].price);
    }
}

Cars_t
*initialize_struct(void) {
    Cars_t *Car;

    Car = malloc(sizeof(*Car));
    if (Car == NULL) {
        fprintf(stderr, "%s", "Issue allocating memory for structure");
        exit(EXIT_FAILURE);
    }

    Car->Cars = NULL;
    Car->numcars = 0;

    return Car;
} 

int
price_cmp(const void *x, const void *y) {
    const transport_t *car1 = x;
    const transport_t *car2 = y;

    if (car1->price > car2->price) {
        return +1;
    } else if (car1->price < car2->price) {
        return -1;
    }
    return 0;
}