简体   繁体   English

为qsort的结构编写比较函数?

[英]Writing a compare function for a structure for qsort?

I'm having trouble writing a compare function for qsort function in C. This is what I currently have: 我在C中为qsort函数编写比较函数时遇到了麻烦。这就是我目前所拥有的:

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 . 我知道比较函数是如何工作的,但我不明白如何在我的结构中引用一个名为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. 我想比较结构中的适应度值。

This part 这部分

*(Individual*)a->fitness

is wrong. 是错的。 You try to access fitness using -> but at the same time you dereference the pointer using * . 您尝试使用->访问fitness但同时使用*取消引用指针。 You can't do both! 你不能两个都做!

Here are two solutions. 这是两个解决方案。

Solution A: Dereference using * and access fitness using . 解决方案A:使用*取消引用并使用访问fitness .

(*(Individual*)a).fitness

Solution B: Access fitness using -> 解决方案B:使用->访问fitness

((Individual*)a)->fitness

Both solutions also requires a cast from void* to Individual* . 这两种解决方案还需要从void*Individual*

The same apply for variable b 同样适用于变量b

If you are a beginner in C I'll recommend that you avoid using compact statements where multiple things happens. 如果您是C语言的初学者,我建议您避免在多个事情发生时使用紧凑语句。 Instead split the compact statement into a number of individual statements. 而是将compact语句拆分为多个单独的语句。 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! 那说 - 正如@chqrlie所说 - 注意比较代码是错误的!

The function returns an integer but fitnessA - fitnessB is a double that will be converted to an integer. 该函数返回一个整数,但fitnessA - fitnessB是一个将被转换为整数的double。 So 0.1 - 0.0 will end up returning 0 - which is not what you want. 所以0.1 - 0.0最终会返回0 - 这不是你想要的。

You can see this answer https://stackoverflow.com/a/53466034/4386427 from @chqrlie for further details. 您可以从@chqrlie看到此答案https://stackoverflow.com/a/53466034/4386427以获取更多详细信息。

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;
}

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. 假设您使用Individual结构数组调用qsort ,您应该将compare函数接收的参数转换为指向Individual结构的指针,最好是const Individual *以避免警告。

You can then compare the fitness members and return an ordering value. 然后,您可以比较fitness成员并返回订购价值。 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 . 请注意,您不能只返回值的差异,因为这些可能是非整数,差异甚至可能超出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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM