-1

I have an array of structs that I'm adding entries into

typedef struct card
{
    char* name;
} card_t;

These are the names in the file: Stolen by the Fae, Eternal Isolation, Corpse Knight, Orzhov Enforcer

I have a qsort function that is supposed to sort all entries by alphabetical order. However it is not working.

// 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;
    }
}

My output is:

Corpse Knight
Eternal isolation
Stolen by the Fae
Orzhov Enforcer

If I have my qsort function correct, then Stolen by the Fae and Orzhov Enforcer should be switched. Any suggestions will be greatly appreciated.

csDreamer
  • 11
  • 3

2 Answers2

1

The other answers about the pointer deferencing are correct.

However, why are you passing in length-1 instead of the actual number of elements?

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

Should be:

qsort(cards, cardsaccum, sizeof(cards[0]), cmpname);
selbie
  • 100,020
  • 15
  • 103
  • 173
0

The qsort funciton passess pointers to the elements to the comparison function.

In essence it calls your cmpname function like cmpname(&cards[i], &cards[j]).

And when every element in the array is a pointer, a pointer to it is a pointer to a pointer. Which means the variable p1 and p2 are incorrect in your function, leading to undefined behavior.

You need to use the correct types:

// 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
}

You also have some other problems, like the number of elements argument for qsort should really be the number of elements in the array, not the top index. And why do you use sizeof(char *) as the element size?

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621