Qsort 结构体数组

Posted

技术标签:

【中文标题】Qsort 结构体数组【英文标题】:Qsort array of structs 【发布时间】:2021-06-05 02:58:50 【问题描述】:

我有一个结构数组,我正在向其中添加条目

typedef struct card

    char* name;
 card_t;

这些是文件中的名字:被妖精偷走、永恒隔离、尸骑士、欧佐夫执行者

我有一个 qsort 函数,它应该按字母顺序对所有条目进行排序。但是它不起作用。

// FUNCTION FOR QSORT()
int cmpname (const void *pa, const void *pb) 
    const card_t **p1 = pa;
    const card_t **p2 = pb;
    
    return strcmp((*p1(->name, (*p2)->name); 

#include "card.h"
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
// FUNCTION FOR QSORT()
int cmpname (const void *pa, const void *pb) 
    const card_t *p1 = pa;
    const card_t *p2 = pb;
    
    return strcmp(p1->name, p2->name); 


int main(int argc, char **argv)    
    char *buf = NULL;
    size_t bufsiz = 0;
    FILE *input_file;
    
    if((input_file = fopen(argv[1], "r")))
    
        ssize_t result = getline(&buf, &bufsiz, input_file);
        int num_entries = 1;
        card_t **cards = NULL;
    
        int i = 0;
        int cardsaccum = 0;
        int id;
        char *name_duplicate;

        // GETS LINE FROM THE CSV FILE
        result = getline(&buf, &bufsiz, input_file);
        // WHILE THE FILE STILL HAS TEXT
        while (result > 0)
           // COPIES BUFFER TO SAVE THE MEMORY ADDRESS
            char *stringp = buf;
            // ALLOCATES MEMORY
            cards = realloc(cards, sizeof(card_t *) * num_entries);
            cards[cardsaccum] = malloc(sizeof(card_t));
            
            cards[cardsaccum]->name = strsep(&stringp, "\"");
            
            cardsaccum++;
            num_entries++;
            // MUST NULL THE BUFFER BEFORE GETLINE 
            buf = NULL;
            // NEXT LINE
            result = getline(&buf, &bufsiz, input_file);
            if(result == -1)
            
                qsort(cards, cardsaccum - 1, sizeof(student_t *), cmpname);
                //printf("AFTER QSORT \n");
                //printf("\n");
                for(i = 0; i < cardsaccum;i++)
                
                    printf("%s", cards[i]->name);
                
            
        
        
        for(i=0; i < cardsaccum;i++)
        
            free(cards[i]);
        
        free(cards);
        free(buf);
        fclose(input_file);
        return 0;
    
    else
    
        fprintf(stderr, "./parser: cannot open(%s%s%s): No such file or directory\n", "\"", argv[1], "\""); 
        return 1;
    

我的输出是:

Corpse Knight
Eternal isolation
Stolen by the Fae
Orzhov Enforcer

如果我的 qsort 功能正确,那么应该切换被 Fae 和 Orzhov Enforcer 偷走。任何建议将不胜感激。

【问题讨论】:

【参考方案1】:

关于指针引用的其他答案都是正确的。

但是,你为什么要传入 length-1 而不是实际的元素数量?

qsort(cards, cardsaccum - 1, sizeof(char *), cmpname);

应该是:

qsort(cards, cardsaccum, sizeof(cards[0]), cmpname);

【讨论】:

【参考方案2】:

qsort 函数将指向元素的指针传递给比较函数。

本质上,它会调用您的 cmpname 函数,例如 cmpname(&amp;cards[i], &amp;cards[j])

当数组中的每个元素都是指针时,指向它的指针就是指向指针的指针。这意味着变量p1p2 在您的函数中不正确,导致未定义的行为

您需要使用正确的类型:

// FUNCTION FOR QSORT()
int cmpname (const void *pa, const void *pb) 
    const card_t **p1 = pa;  // These are pointer to the elements, and since each
    const card_t **p2 = pb;  // element is a pointer then these becomes pointers to pointers
    
    return strcmp((*p1)->name, (*p2)->name);  // Remember to dereference the pointers

您还有一些其他问题,例如 qsort 的元素数量参数实际上应该是数组中的元素数量,而不是顶部索引。以及为什么使用sizeof(char *) 作为元素大小?

【讨论】:

感谢您对 qsort 的解释!

以上是关于Qsort 结构体数组的主要内容,如果未能解决你的问题,请参考以下文章

c语言 qsort 对结构体数组排序

在c中怎样用qsort对结构体数组进行多级排序

c++中参考C语言的qsort函数实现一个一个能对任意数据类型(包括结构体)的数组进行排序的函数

qsort 与sort 对结构体排序实例

关于结构体的qsort

第52题qsort 结构体 应用(更新中)