using qsort() to sort pointers to structs containing strings

前端 未结 3 1262
Happy的楠姐
Happy的楠姐 2021-01-13 02:58

I\'m not sure if this is possible to do with qsort because what I want to sort (array of pointers to struct) is not what I am comparing (strings).

Here is an abridge

相关标签:
3条回答
  • 2021-01-13 03:04

    The other answers are correct in everything but one little detail. I've just hit this, so i'll leave it here in case someone else finds themselves struggling with an extremely pedantic compiler.

    qsort() comparator accepts two const void * parameters. Which means that when you dereference them to get pointers to your actual structs, you have to keep that const-ness. So, if you were to follow every single rule of C language, your code would look like this:

    int
    cmp(const void *p0, const void *p1)
    {
        const struct student* ps0 = *(const struct student* const*) p0;
        const struct student* ps1 = *(const struct student* const*) p1;
    
        return strcmp(ps0->lname, ps1->lname);
    }
    

    Note the "const pointer to const" construct - that's you telling the compiler that at no point your original pointers (p0 and p1) lose their const-ness - you first dereference them to a const * const *, and then dereference that to const *. If you simply use const **, that's a const * to * (non-const) pointer, which discards the original const-ness of const void *.

    0 讨论(0)
  • 2021-01-13 03:26

    It should be something like this:

    int
    cmp(const void *p0, const void *p1)
    {
            // pn is a pointer to an element of the array,
            // so, it's effectively a pointer to a pointer to a struct.
            // Therefore, we need to cast it appropriately to struct student **.
            // To get a pointer to a struct from it, we dereference it once,
            // hence the "*". Then we need to extract a pointer to the beginning
            // of a string, hence the "->".
            return strcmp((*(struct student **) p0)->lname,
                          (*(struct student **) p1)->lname);
    }
    
    0 讨论(0)
  • 2021-01-13 03:30

    What will be passed to cmp() are struct student** parameters (in the guise of void*). So change cmp() like so:

    int
    cmp(const void *p0, const void *p1)
    {
            struct student* ps0 = *(struct student**) p0;
            struct student* ps1 = *(struct student**) p1;
    
            return strcmp( ps0->lname, ps1->lname);
    }
    
    0 讨论(0)
提交回复
热议问题