#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!