Paweł Dymowski - 12 days ago 5
C Question

# How to sort array of structs by given member in C

I have a struct like that :

``````struct Car {
int weight;
int price;
int speed;
etc..}
``````

I want to write a function to sort array of this kind of structs.

``````void sortCars(struct Car table[], int tableSize, ?structMemberParameter?)
{
struct Car temp;
int swapped;
for (int i = 0; i < tableSize; i++)
{
swapped = 0;
for (int j = 0; j < tableSize - 1; j++) {
if (table[j].?structMemberParameter? > table[j + 1].?structMemberParameter?) {
temp = table[j + 1];
table[j + 1] = table[j];
table[j] = temp;
swapped = 1;
}
}
if (swapped == 0) {
break;
}
}
}
``````

What should I put as "?structMemberParameter?"?

Writing a comparison function that compares such member from two structs and using `qsort()`. You can see the example in the `qsort(3)` manual.

This is the answer to the title of the question, the answer to your question is you don't need to pass the member but the comparison function just like `qsort()` does.

So the `if` statement becomes

``````if (compare(&table[j], &table[j + 1]) > 0) ...
``````

and the function signature

``````typedef int (*cmpfn_type)(const struct Car *const, const struct Car *const);
void sortCars(struct Car table[], int tableSize, cmpfn_type compare);
``````

So you can have multiple comparison functions, for example let's say you want to compare by price, the appropriate one would be

``````int compare_by_price(const struct Car *const A, const struct Car *const B)
{
return (int) (A->price - B->price);
}
``````

you should be careful with the type casting though.

The good thing of this approach, is that you can easily rewrite the comparison function to use the `qsort()` library function.

``````enum CarProperties {
Speed, Price // ... AND SO ON
};
``````

and then a sort function like

``````void sort_car_array(struct Car *const array,
size_t size, enum CarProperties sort_property);
``````

where you have a `switch` statement to choose the appropriate callback to pass to a generic sort like say, `generic_car_array_sort()` like the suggested above or even, directly to `qsort()` which would be a better solution.

If your intention is to have an API for the `struct Car` structure you can do it like this and I think it's a very elegant solution. I also recommend making the struct opaque and allowing the caller only to set/get the values via functions.