【问题标题】:how to Sorting an array of struct pointers with qsort如何使用 qsort 对结构指针数组进行排序
【发布时间】:2021-08-02 02:34:15
【问题描述】:

这是我的Book 结构,这是我的代码:

typedef struct book {
   char title[100];
   char author[20];
   int price;
} BOOK;

#define MAX_SIZE 10

int comparePrice(const void *bookA, const void *bookB);

int count = 0;

int main() {    
    BOOK *books[MAX_SIZE];    // here is  array of struct pointers
    while (1) {   
        char title[100] = "";
        char author[20] = "";
        int price = -1;
        //////////// printf select menu ////////////
        int selector = -1;
        scanf("%d", &selector);
        switch (selector) {
          case 1:
            while (getchar() != '\n');
            printf("--------input book data--------\n");
            printf("title :");
            gets(title);
            printf("author :");
            gets(author);

            printf("price :");
            scanf("%d", &price);

            books[count] = (BOOK *) malloc(sizeof(BOOK));
            memset(books[count], 0, sizeof(BOOK));
            strcpy(books[count]->title, title);
            strcpy(books[count]->author, author);
            books[count]->price = price;
            count++;
            break;
          case 4:
            printf("--------sorting price--------\n");
            qsort(books, count, sizeof(BOOK), comparePrice);
            for (int i = 0; i < count; ++i) {
                printf("%d. title: %s author: %s price: %d\n", i + 1, books[i]->title, books[i]->author, books[i]->price);
            }
            break;
          default:
            for (int i = 0; i < MAX_SIZE; ++i) {
                free(books[i]);
                books[i] = NULL;
            }
            return 0;
        }
    }
}

int comparePrice(const void *bookA, const void *bookB) {
    const BOOK *a = (const BOOK *)bookA;
    const BOOK *b = (const BOOK *)bookB;
    return b->price - a->price;
}

qsort 不工作 选择 4 号菜单,该程序停止。 我尝试调试,发现 a 和 b 有未知值。 而在打印排序结果的printf语句中出现EXC_BAD_ACCESS错误。 我需要做些什么来进行排序。

【问题讨论】:

  • pssst,如果你使用calloc,你不需要自己把memset的一切都设为0。任何你忘记free,所以你有内存泄漏。和gets is evilstrcpy 也很危险。
  • 不错的编辑,但不能保证 books 数组有 MAX_SIZE 元素。因此,您可能正在尝试释放未初始化的指针。使用count
  • @YIGeon 你想按降序排序吗?
  • @VladfromMoscow 是的!

标签: arrays c pointers struct qsort


【解决方案1】:

数组books应该被初始化

BOOK *books[MAX_SIZE] = { NULL };

否则这个循环

for (int i = 0; i < MAX_SIZE; ++i) {
    free(books[i]);
    books[i] = NULL;
}

将调用未定义的行为。

因为你有一个指针数组,那么qsort 的调用应该至少看起来像

qsort( books, count, sizeof( BOOK * ), comparePrice );

另一方面,他的函数comparePrice应该定义如下

int comparePrice( const void *bookA, const void *bookB ) 
{
    const BOOK *a = *( const BOOK * const * ) bookA;
    const BOOK *b = *( const BOOK * const * ) bookB;
    
    return ( a->price < b->price ) - ( b->price < a->price );
}

这是一个简化的演示程序。

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

typedef struct book
{
    int price;
} BOOK;

int comparePrice( const void *bookA, const void *bookB ) 
{
    const BOOK *a = *( const BOOK * const * ) bookA;
    const BOOK *b = *( const BOOK * const * ) bookB;
    
    return ( a->price < b->price ) - ( b->price < a->price );
}

int main(void) 
{
    BOOK b1 = { 10 }, b2 = { 20 };
    BOOK *a[] = { &b1, &b2 };
    const size_t count = sizeof( a ) / sizeof( *a );
    
    for ( size_t i = 0; i < count; i++ )
    {
        printf( "%d ", a[i]->price );
    }
    
    putchar( '\n' );

    qsort( a, count, sizeof( BOOK * ), comparePrice );
    
    for ( size_t i = 0; i < count; i++ )
    {
        printf( "%d ", a[i]->price );
    }
    
    putchar( '\n' );
    
    return 0;
}

程序输出是

10 20 
20 10

【讨论】:

    【解决方案2】:

    比较函数不正确:它获取指向数组的指针,因此指向结构指针。此外,如果在比较非常大的相反符号值时可能发生减法溢出,则通过减去它们来比较整数将不起作用。

    这是修改后的版本:

    int comparePrice(const void *aa, const void *bb) {
        const BOOK *a = *(const BOOK * const *)aa;
        const BOOK *b = *(const BOOK * const *)bb;
        /* sort in decreasing order of price */
        return (b->price > a->price) - (b->price < a->price);
    }
    

    qsort() 调用也不正确。应该是:

    qsort(books, count, sizeof(*books), comparePrice);
    

    代码中还有其他问题:

    • 数组books 未初始化,因此您应该只free 已分配的指针:将最后一个循环更改为

        while (count > 0) {
            free(books[--count]);
        }
      
    • 不要使用gets()

    • 小心潜在的无限循环:while (getchar() != '\n'); 始终测试EOF

        int c;
        while ((c = getchar()) != EOF && c != '\n')
            continue;
      

    【讨论】:

      【解决方案3】:

      qsort 将指向数组中元素的指针传递给比较函数(在您的情况下,它本身就是指针)。所以你想要:

      int comparePrice(const void *bookA, const void *bookB) {
          const BOOK *a = *(const BOOK **)bookA;
          const BOOK *b = *(const BOOK **)bookB;
          return b->price - a->price;
      }
      

      【讨论】:

        猜你喜欢
        • 2014-07-04
        • 1970-01-01
        • 2015-12-13
        • 2017-04-19
        • 2016-11-29
        • 2021-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多