I want to switch between comparer in qsort instead creating 5 different comparer, but for some reason the program doesn't work. I don't have any idea why this is happen. Can anyone explain please? Thanks!
struct propertySales{
unsigned int tanggal[3];
char pelanggan[30];
char jenisProperty[30];
char namaProperty[30];
int jumlahProperty;
double hargaProperty;
double totalPembayaran;
}Arr[100], compare[100], temp;
typedef int (*compfn)(const void*, const void*);
int compare_harga(struct propertySales *, struct propertySales *);
int compare_pembayaran(struct propertySales *, struct propertySales *);
int compare_harga(struct propertySales *elem1, struct propertySales *elem2){
if( elem1->hargaProperty < elem2->hargaProperty){
return -1;
}
else if(elem1->hargaProperty > elem2->hargaProperty){
return 1;
}
else{
return 0;
}
}
int compare_pembayaran(struct propertySales *elem1, struct propertySales *elem2){
if( elem1->totalPembayaran < elem2->totalPembayaran){
return -1;
}
else if(elem1->totalPembayaran > elem2->totalPembayaran){
return 1;
}
else{
return 0;
}
}
The compiler throw warning saying --- [Warning] cast to pointer from integer of different size [-Wint-to-pointer-cast]
Short code
Let’s start with our structures. I’m going to mess with them, just for the purposes of having a greater variety of object types inside.
Now for comparator functions.
That’s it! Now to sort your data you just need to use the proper comparator function!
In English:
Shorter code with X-macros
You can reduce the repetative typing quite a bit with some macros, but the real benefit here is ODR, which is a useful concept in C as well as C++.
The idea is to create a single table of information that we will afterward use to construct our objects.
Woah! Yeah! Now to generate the comparator functions:
That was... surprisingly short, right? Even with all the additional code doign stuff the original code could not, and complete code for all comparator functions (because we left them all out in the first example).
The obvious tradeoff is that now we are in tricky-code territory.
The original code is very clear and easy to read. This stuff takes extra brainpower.
Whether it is worth it or not is a debate to be had elsewhere. For now, we can easily sort an array of Property_Sales against any member.
English:
If that Client structure existed, and had things set up to sort Clients by a specific member comparator function, then you could sort by client as well:
English:
That’s it!
All the code is still repetitive, but we put all that repetition into some macros to generate code for us from a table. This trick is known as the X-macro trick.
Noted from above: we made the district effectively unsortable by simply returning a
0value. Wecould haveshould have given it sort ability just like all the other elements around it. The point is just to provide an example!I should point out that I also used the (in)famous
offsetof()macro to make things nicer for us. In the sort functionaandbare now direct pointers to the member elements to compare (and not to the structure itself as before). Notice how this had a direct effect on the comparison code in thePENJUALAN_PROPERTItable: be careful to remember at what level of indirection you are at. Notice, for example, the difference when usingstrcmp()on a member string array versus a member string pointer.Remember also that
qsort()is neither re-entrant nor stable. Playing with global state like we are means we need to be careful about threaded and recursive uses.Oh, and find that
ARRAY_SIZE macrohere (with a slightly different name).Remember, with great power comes great responsibility!