1

I have two structs, the first one looks like this:

typedef struct plant
{
  char ID[10];

  char scientific_name[MAX_NAME];

  char **alias;

  int n_alias;

  int n_seeds;

} plant;

and the second one is essentially an array of members

typedef struct catalog
{
  plant **plants;

  long catalog_size;
 /*specifies if the plants array is either sorted by ID or scientific_name*/
  char ordering_method[5];

} catalog;

I was trying to use qsort to sort the **plants array inside catalog and my function call is as follows:

int catalog_sort(catalog *c, const char *ordering_method)
{
    if (!strcasecmp(ordering_method, "ID"))
        qsort(c->plants, c->catalog_size, sizeof(plant *), qsortKey_ID);
    else if (!strcasecmp(ordering_method, "name"))
        qsort(c->plants, c->catalog_size, sizeof(plant *), qsortKey_name);
    else
        return -1;

    return 0;
}

Both qsortKey_ functions work basically the same but compare a different element of the struct

int qsortKey_ID(const void *a, const void *b)
{
    const plant *pa = (plant *)a;
    const plant *pb = (plant *)b;

    /*checking to see if data is corrupted when the fuction gets called*/
    printf("ID A - %s, ID B - %s, COMP: %d\n", pa->ID, pb->ID, strcmp(pa->ID, pb->ID));

    return strcmp(pa->ID, pb->ID);
}

When i run this code, qsort does not work properly, failing to order the array and valgrind falgs "Invalid read size of 1" on both strcmp function calls made by either of the qsortKey_ functions, which is in line with the fact that the printed data by the prinf just above is indeed corrupted, funny enough the array itself is fine afterwards, just not properly sorted.

I've been struggling with this for some time now to no avail, so any input is appreciated. Is this not a correct application of qort? Should i resort to implementing a sorting algorithm manually?

4
  • Why do you pass the plant pointers as void pointers to the function qsortKey_ID? Commented Mar 24, 2021 at 9:37
  • Hmm... I can understand that you have an array of pointer to plants in your catalog. Not a problem by itself but the devil often hides in detail. Could you give a minimal reproducible example showing how you build a minimal catalog and try to sort it. Commented Mar 24, 2021 at 9:53
  • @AndySukowski-Bang as far as i know the qsort compare function needs to have const void * as argument or it can't be passed as an argument. Commented Mar 24, 2021 at 10:24
  • @SergeBallesta I was in the middle of making an example but in the meantime my question got successfully answered so that's not really needed anymore, thanks anyway. Commented Mar 24, 2021 at 10:26

1 Answer 1

1

You are missing one indirection.

The comparison function takes two parameters that point at the array elements, thus:

int qsortKey_ID(const void *a, const void *b)
{
    const plant *pa = *(plant **)a; // a == &plants[some index]
    const plant *pb = *(plant **)b; // b == &plants[some other index]

    /*checking to see if data is corrupted when the fuction gets called*/
    printf("ID A - %s, ID B - %s, COMP: %d\n", pa->ID, pb->ID, strcmp(pa->ID, pb->ID));

    return strcmp(pa->ID, pb->ID);
}

Notice the additional asterisks.

Sign up to request clarification or add additional context in comments.

2 Comments

That solved it, thanks! I guess i need to be more carefull with how data is passed by qsort to the compare function.
@TiagoAmorim Or use C++ :P

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.