Home > Net >  Getting wrong sort with qsort - C
Getting wrong sort with qsort - C

Time:11-21

I'm trying to sort an array of pointers to structures using the the qsort function, here's the code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


struct hotel {
    char *address;
    _Bool full;
    int nrooms;
};


/* compare based on the value of nrooms */
int roomcomp(const void *p1, const void *p2)
{
    return (
        ((struct hotel *)p1)->nrooms - 
        ((struct hotel *)p2)->nrooms
    );
}


/* compare based on the alphabetic value of address */
int addcomp(const void *p1, const void *p2)
{
    return strcmp(
        ((struct hotel *)p1)->address,
        ((struct hotel *)p2)->address
    );
}


int main()
{
    struct hotel *p1 = malloc(sizeof(struct hotel));
    struct hotel *p2 = malloc(sizeof(struct hotel));
    struct hotel *p3 = malloc(sizeof(struct hotel));
    struct hotel *p4 = malloc(sizeof(struct hotel));
    
    p1->address = strdup("aaaa");
    p1->nrooms = 100;

    p2->address = strdup("bbbb");
    p2->nrooms = 200;

    p3->address = strdup("cccc");
    p3->nrooms = 300;

    p4->address = strdup("dddd");
    p4->nrooms = 400;

    struct hotel *arr[] = {p1, p2, p3, p4};
    size_t size = sizeof(arr) / sizeof(*arr);

    for (int i = 0; i < size; i  ) {
        printf("address: %s - nrooms: %d\n", arr[i]->address, arr[i]->nrooms);
    }

    putchar('\n');
    qsort(arr, size, sizeof(struct hotel *), roomcomp);

    for (int i = 0; i < size; i  ) {
        printf("address: %s - nrooms: %d\n", arr[i]->address, arr[i]->nrooms);
    }
}

Here's the results I'm getting:

address: aaaa - nrooms: 100
address: bbbb - nrooms: 200
address: cccc - nrooms: 300
address: dddd - nrooms: 400

address: aaaa - nrooms: 100
address: cccc - nrooms: 300
address: dddd - nrooms: 400
address: bbbb - nrooms: 200

I've tried a bunch of different things but I keep getting the same results... When I try to print the value of nrooms inside roomcomp I'm getting pointers values so If I had to guess I would say I'm casting the wrong way...

CodePudding user response:

struct hotel *arr[]

is an array of pointers, so iterators are pointers to pointers.

int roomcomp(const void *p1, const void *p2) {
    const struct hotel *const *x = p1;
    const struct hotel *const *y = p2;
    return (*x)->nrooms - (*y)->nrooms;

CodePudding user response:

As an alternative to KamilCuk's answer, you could avoid making an array of pointers in the first place:

const size_t n_hotels = 4;
struct hotel *arr = malloc(n_hotels * sizeof(struct hotel));
arr[0].address = /* ... */;
arr[0].nrooms = /* ... */;
/* ... */
qsort(arr, n_hotels, sizeof(struct hotel), roomcomp);

and now the things passed to the comparison function will be struct hotel * and your roomcomp will work as written.

  • Related