问题
I'm having trouble writing a compare function for qsort
function in C. This is what I currently have:
int cmpfunc(const void *a, const void *b) {
return (*(Individual*)a->fitness - *(Individual*)b->fitness);
}
I know how the compare function works but I don't understand how to reference an integer value within my structure called Individual
. Here is the structure of the Individual.
typedef struct {
PPM_IMAGE image;
double fitness;
} Individual;
I want to compare the fitness values within the structure.
回答1:
This part
*(Individual*)a->fitness
is wrong. You try to access fitness
using ->
but at the same time you dereference the pointer using *
. You can't do both!
Here are two solutions.
Solution A: Dereference using *
and access fitness
using .
(*(Individual*)a).fitness
Solution B: Access fitness
using ->
((Individual*)a)->fitness
Both solutions also requires a cast from void*
to Individual*
.
The same apply for variable b
If you are a beginner in C I'll recommend that you avoid using compact statements where multiple things happens. Instead split the compact statement into a number of individual statements. That will make the code easier to understand and debug. Like:
int cmpfunc (const void * a, const void * b){
Individual* pA = a;
Individual* pB = b;
double fitnessA = pA->fitness;
double fitnessB = pB->fitness;
return fitnessA - fitnessB;
}
You don't need to worry about performance. The compiler will optimize the code to be just as efficient as the single statement code.
That said - as spotted by @chqrlie - notice that the compare code is wrong!
The function returns an integer but fitnessA - fitnessB
is a double that will be converted to an integer. So 0.1 - 0.0
will end up returning 0
- which is not what you want.
You can see this answer https://stackoverflow.com/a/53466034/4386427 from @chqrlie for further details.
The code can also be changed like:
int cmpfunc (const void * a, const void * b){
Individual* pA = a;
Individual* pB = b;
double fitnessA = pA->fitness;
double fitnessB = pB->fitness;
if (fitnessA > fitnessB) return 1;
if (fitnessA < fitnessB) return -1;
return 0;
}
回答2:
Assuming you call qsort
with an array of Individual
structures, you should cast the arguments received by the compare function as pointers to Individual
structures, preferably const Individual *
to avoid warnings.
You can then compare the fitness
members and return an ordering value. Note that you cannot just return the difference of the values as these may be non integral and the difference may even overflow the range of type int
.
Here is a classic way to do this:
int cmpfunc(const void *a, const void *b) {
const Individual *aa = a;
const Individual *bb = b;
/* return -1, 0 or 1 depending on the comparison results */
return (aa->fitness > bb->fitness) - (aa->fitness < bb->fitness);
}
来源:https://stackoverflow.com/questions/53465147/writing-a-compare-function-for-a-structure-for-qsort