Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a compare function for qsort from stdlib?

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 by tab_pkt.alfa and tab_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;
}
like image 931
diminish Avatar asked Dec 13 '22 05:12

diminish


1 Answers

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.

like image 70
Robert Gamble Avatar answered Dec 25 '22 14:12

Robert Gamble