Need help using qsort with an array of structs
Here is an example of using qsort
for an array of structs in C
/* qsort example */
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int price;
int id;
} order;
order list[6];
int i = 0;
int compare (const void * a, const void * b)
{
order *orderA = (order *)a;
order *orderB = (order *)b;
return ( orderB->price - orderA->price );
}
int main ()
{
srand ( time(NULL) );
printf("Before sorting\n");
for(i=0; i<6; i++){
list[i].price = rand()%10;
list[i].id = i;
printf ("Order id = %d Price = %d \n",list[i].id, list[i].price);
}
printf("AFTER sorting\n");
int n;
qsort (list, 6, sizeof(order), compare);
for (n=0; n<6; n++)
printf ("Order id = %d Price = %d \n",list[n].id, list[n].price);
return 0;
}
hope it helps
katerina dimitris
(all regards to pitsi)
Your Soc
should almost certainly not be of type double
, but anyway here's an example of what a compare function needs to return:
int compare(const void *p1, const void *p2)
{
const struct profile *elem1 = p1;
const struct profile *elem2 = p2;
if (elem1->soc < elem2->soc)
return -1;
else if (elem1->soc > elem2->soc)
return 1;
else
return 0;
}
Thanks for pointing out the const void *.
Here is a complete example (archived): Sorting Structures with the C qsort() Function
The strict version of a comparator takes two constant void pointers:
int compare(const void *v1, const void *v2)
{
const struct profile *p1 = v1;
const struct profile *p2 = v2;
if (p1->gender > p2->gender)
return(+1);
else if (p1->gender < p2->gender)
return(-1);
else if (p1->soc > p2->soc)
return(+1);
else if (p1->soc < p2->soc)
return(-1);
else
return(0);
}
This compares the gender field first, then the soc field. This is how you handle any multipart comparison.
To sort the array, use qsort()
and pass a comparison function.
Here is one that produces the correct result for all possible values of the price
member:
typedef struct profile {
char gender[1];
double soc;
int price;
...
} PROFILE;
int compare_price(const void *a, const void *b) {
const PROFILE *oa = a;
const PROFILE *ob = b;
return (oa->price > ob->price) - (oa->price < ob->price);
}
int compare_soc(const void *a, const void *b) {
const PROFILE *oa = a;
const PROFILE *ob = b;
return (oa->soc > ob->soc) - (oa->soc < ob->soc);
}
Notes:
the simple subtraction of values produces incorrect results if the difference does not fit in the
int
type. For example-2
andINT_MAX
cannot be correctly compared with the subtraction method. It would not work for floating point values either.the above method can be used for all comparable types, including
double
except forNaN
.
If you wish to handle NaN
, here is how to group them at the end:
#include <math.h>
int compare_soc_nan_at_the_end(const void *a, const void *b) {
const PROFILE *oa = a;
const PROFILE *ob = b;
if (isnan(oa->soc)) {
return isnan(ob->soc) ? 0 : 1;
} else
if (isnan(ob->soc)) {
return -1;
} else {
return (oa->soc > ob->soc) - (oa->soc < ob->soc);
}
}