-1

i'm having a little trouble using the qsort available in C to sort an array of strings i have in a struct of mine.

My code goes as follows:

typedef struct estrutura
{
    int sp;
    int numberOfEntries;
    int entriesSize;
    char* stack[26];
    char** list;
}*estrutura;


void createStruct (estrutura l, int numberEntries, int sizeEntries)
{
    l -> list = malloc (numberEntries * sizeof(char*));

    l -> numberOfEntries = numberEntries;
    l -> sp = 0;
    l -> entriesSize = sizeEntries;

    for (int i = 0; i < (l -> numberOfEntries); i++)
        (l -> list)[i] = malloc ((sizeEntries + 1) * sizeof(char));


}

int cmpstr(void const *a, void const *b) {
    char const *aa = (char const *)a;
    char const *bb = (char const *)b;

    return strcmp(aa, bb);
}

void addEntry (estrutura l, char* line)
{
    strcpy((l -> list)[(l -> sp)],line);
    (l -> sp)++;
}

void sortStruct (estrutura l)
{
    qsort((l -> list)[0], l -> numberOfEntries, (l -> entriesSize) * sizeof(char), cmpstr);
}

void printStruct (estrutura l)
{
    for (int i = 0; i < (l -> numberOfEntries); i++)
        printf("%s\n",(l -> list)[i]);
}

void freeStruct (estrutura l)
{
    for (int i = 0; i < (l -> numberOfEntries); i++)
        free((l -> list)[i]);

    free(l);

}

So my problem is: when i run a test in my main function:

int main ()
{

    estrutura example = malloc (sizeof(struct estrutura));
    createStruct(example,2,6);

    char* name = malloc (6*sizeof(char));
    strcpy(name,"A1234");

    char* otherName = malloc(6*sizeof(char));
    strcpy(otherName, "B1234");

    addEntry(example,otherName);
    addEntry(example,name);
    printf("/////BEFORE SORTING//////\n");
    printStruct(example);
    sortStruct(example);
    printf("/////AFTER SORTING//////\n");
    printStruct(example);

freeStruct(example);

}

The output that i get before the sorting is as expected:

"A1234"
"B1234"

But after the sorting, the output i get is:

"     " -> blank line
"B1234"

And this happens for every test i make. It just erases the first element and then doesn't sort at all. Any help would be appreaciated.

  • 3rd argument to `qsort` function is size of each element in the array (in your case its `l->list`). So the 3rd argument is `sizeof(char*)`. – Rahul Bharadwaj Apr 01 '20 at 18:09
  • @RahulBharadwaj im confused now, but when i do the malloc in the create function, doesn't that size change according to the size i indicate in the malloc? –  Apr 01 '20 at 18:18
  • @RahulBharadwaj and the output remains the same tho. but thanks for the help so far! –  Apr 01 '20 at 18:19
  • first argument to qsort should be l->list, this is the location your pointers are stored, and the 3rd argument is sizeof(char*) – Jens Harms Apr 01 '20 at 19:08

1 Answers1

2

Suppose you want to sort an array with N entries of type T:

T *array = malloc(N * sizeof(*array));

Then your call to qsort looks like this:

qsort(array, N, sizeof(*array), t_cmp);

Your conparison function is:

int t_cmp(const void *a, const void *b)
{
    const T *aa = a;
    const T *bb = b;

    // compare *aa and *bb
}

The pointers you receive are pointers to the array elements. They have the same type as the handle to the array, array. (If you have a fixed-size array as defined with T a[N] these pointers have the same type as the array after it has decayed to a pointer. In both cases, that type is T *.)


In your case, the type T is char *. So:

l->list = malloc(l->numberEntries * sizeof(*l->list));

Then sort:

qsort(l->list, l->numberOfEntries, sizeof(*l->list), cmpstr);

with this comparison function.

int cmpstr(void const *a, void const *b)
{
    char *const *aa = a;
    char *const *bb = b;

    return strcmp(*aa, *bb);
}

(Instead of sizeof(*l->list) you can use sizeof(char *), which would be sizeof(T), the size of one element of the array, in the parlance used above.)

M Oehm
  • 28,726
  • 3
  • 31
  • 42