Qsort массив структур

#arrays #c #memory #struct #alloc

Вопрос:

У меня есть массив структур, в которые я добавляю записи

 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(amp;buf, amp;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(amp;buf, amp;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(amp;stringp, """);
            
            cardsaccum  ;
            num_entries  ;
            // MUST NULL THE BUFFER BEFORE GETLINE 
            buf = NULL;
            // NEXT LINE
            result = getline(amp;buf, amp;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 directoryn", """, argv[1], """); 
        return 1;
    }
}
 

Мой вывод таков:

 Corpse Knight
Eternal isolation
Stolen by the Fae
Orzhov Enforcer
 

Если у меня правильная функция qsort, то Украденное Фейри и Оржовским Силовиком должно быть переключено. Любые предложения будут высоко оценены.

Ответ №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]) .

И когда каждый элемент в массиве является указателем, указатель на него является указателем на указатель. Что означает, что переменные p1 и p2 неверны в вашей функции, что приводит к неопределенному поведению.

Вам нужно использовать правильные типы:

 // 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 *) в качестве размера элемента?

Комментарии:

1. Спасибо за ваше объяснение по qsort!