How to write a compare function for qsort from stdlib?
Solution 1
Something like this should work:
int porownaj(const void *p_a, const void *p_b)
{
/* Need to store arguments in appropriate type before using */
const pkt *pkt_a = p_a;
const pkt *pkt_b = p_b;
/* Return 1 or -1 if alfa members are not equal */
if (pkt_a->alfa > pkt_b->alfa) return 1;
if (pkt_a->alfa < pkt_b->alfa) return -1;
/* If alfa members are equal return 1 or -1 if r_kw members not equal */
if (pkt_a->r_kw > pkt_b->r_kw) return 1;
if (pkt_a->r_kw < pkt_b->r_kw) return -1;
/* Return 0 if both members are equal in both structures */
return 0;
}
Stay away from silly tricks like:
return pkt_a->r_kw - pkt_b->r_kw;
which return un-normalized values, are confusing to read, won't work properly for floating point numbers, and sometimes have tricky corner cases that don't work properly even for integer values.
Solution 2
There are two parts to the problem - how to write the code, and how to compare the packet types. You must ensure you always return a value. Your code should also always be such that:
porownaj(&pkt_a, &pkt_b) == -porownaj(&pkt_b, &pkt_a)
Your outline comparison does not handle cases such as:
pkt_a->alfa > pkt_b->alfa && pkt_a->r_kw <= pkt_b->r_kw
pkt_a->alfa < pkt_b->alfa && pkt_a->r_kw >= pkt_b->r_kw
pkt_a->alfa == pkt_b->alfa && pkt_a->r_kw != pkt_b->r_kw
There is one more problem - is it appropriate to compare floating point values for exact equality? That will depend on your application.
Mechanically, you have to convert the const void pointers to const structure pointers. I use the explicit cast - C++ requires it, and I try to make my code acceptable to a C++ compiler even when it is really C code.
int porownaj(const void *vp1, const void *vp2)
{
const pkt *pkt_a = (const pkt *)vp1;
const pkt *pkt_b = (const pkt *)vp2;
if (pkt_a->alfa > pkt_b->alfa && pkt_a->r_kw > pkt_b->r_kw) return 1;
if (pkt_a->alfa == pkt_b->alfa && pkt_a->r_kw == pkt_b->r_kw) return 0;
if (pkt_a->alfa < pkt_b->alfa && pkt_a->r_kw < pkt_b->r_kw) return -1;
return 0;
}
This does not deal with the bits that I cannot resolve since I am not party to the necessary information. Note that, in general, multi-dimensional objects (such as complex numbers, or (x,y) or (x,y,z) coordinates) cannot simply be compared for greater than or less than or equal to.
Related videos on Youtube
diminish
Updated on April 17, 2022Comments
-
diminish about 2 years
I have a structure:
struct pkt_ { double x; double y; double alfa; double r_kw; }; typedef struct pkt_ pkt;
A table of these structures:
pkt *tab_pkt; tab_pkt = malloc(ilosc_pkt * sizeof(pkt));
What I want to do is to sort
tab_pkt
bytab_pkt.alfa
andtab_pkt.r
:qsort(tab_pkt, ilosc_pkt, sizeof(pkt), porownaj);
Where porownaj is a compare function, but how to write it? Here is my "sketch" of it:
int porownaj(const void *pkt_a, const void *pkt_b) { if (pkt_a.alfa > pkt_b.alfa && pkt_a.r_kw > pkt_b.r_kw) return 1; if (pkt_a.alfa == pkt_b.alfa && pkt_a.r_kw == pkt_b.r_kw) return 0; if (pkt_a.alfa < pkt_b.alfa && pkt_a.r_kw < pkt_b.r_kw) return -1; }