Reputation: 840
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?"?
Upvotes: 1
Views: 2663
Reputation: 53036
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.
NOTE: Answering to your comment/question in the comments you could also have an enumerator, like
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.
Upvotes: 2