0

I am still learning about C programming, and I am having a bit of an issue with my program.

So my structure is declare in q.h file

#define MAXIMUM_LENGTH 80
struct Tsunami {
    unsigned int day;
    unsigned int month;
    unsigned int year;
    unsigned fatalities;
    double height;
    char location[MAXIMUM_LENGTH];
}; 

and the function that uses qsort is :

double get_median_height(const struct Tsunami* begin, size_t count)
{
    double median = 0;
    double compare1,compare2;
    struct Tsunami* store = (struct Tsunami*) malloc (sizeof(struct Tsunami) * count);

    for (int i = 0; i < (int)count; i++)
    {
        store[i].month = begin[i].month;
        store[i].day = begin[i].day;
        store[i].year = begin[i].year;
        store[i].fatalities = begin[i].fatalities;
        store[i].height = begin[i].height;
        strcpy(store[i].location, begin[i].location);
    }
    qsort(store, count, sizeof(Tsunami), compare_events);
    if(count % 2  == 0)
    {
        printf("%ld",count);
        compare1 = store[(count/2)].height;
        printf("%lf",compare1);
        compare2 = store[(count/2) +1].height;
        printf("%lf",compare2);
        median = (compare1 + compare2)/2;
    }
    else
    {
        median = store[(count/2)].height;
    }
    free(store);
    return median;
}

My compare_events code is

int compare_events(const void* first, const void* second)
{
    struct  Tsunami* first = (struct Tsunami*)first;
    struct  Tsunami* second = (struct Tsunami*)second;

    return (second->height - first->height);
}

For some reason, it does not help me sort out the value of store.height from smallest to largest. Can someone explain to me why? and how should I use the qsort instead?

Milo
  • 1
  • 1

1 Answers1

0

Your comparison function:

  1. Is backwards. It's supposed to return a number less than zero if first < second, but yours does the opposite. So intuitively it should be return first->height - second->height. However...

  2. As "chux - Reinstate Monica" alluded to in comments, your heights are of type double but the comparison function must return int. So your function implicitly converts their difference to an int, but this conversion always rounds toward zero. Thus any two heights that differ by less than 1 will have a difference less than 1, which will be rounded to zero and qsort will think the two Tsunamis are of equal height, and may put them in the array in any order.

    What you really want is something like sign(first->height - second->height). Unfortunately C has no standard sign function, but you can find many possible implementations at Is there a standard sign function (signum, sgn) in C/C++?. (This will also fix another bug, which is that your function will not correctly compare heights whose difference doesn't fit in an int.)

Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • Thank you very much for the explanation. And thank everyone for your help. I managed to resolve the issue. Turn out the issue was indeed in my compare_events code and the way I declare and return the values. Thank you all very much. – Milo Nov 21 '20 at 17:06