简体   繁体   English

使用C qsort()的排序结构

[英]Sorting structure with C qsort()

Having trouble getting my head around implementing the qsort() built into C to sort an array of structs by a stored int value (hitCount). 难以理解实现C内置的qsort()来按存储的int值(hitCount)对结构数组进行排序的情况。

My struct: 我的结构:

typedef struct words {
    const char *word;
    int hitCount;
} words;

I'm trying to use the example given by Microsoft ( http://support.microsoft.com/kb/73853 ). 我正在尝试使用Microsoft( http://support.microsoft.com/kb/73853 )给出的示例。

So I've got at the top: 因此,我名列前茅:

typedef int (*compfn)(const void*, const void*);

and the comparision method: 和比较方法:

int compare (words *a, words *b) {
    if (a->hitCount > b->hitCount) {
        return -1;
    } else if (a->hitCount < b->hitCount) {
        return 1;
    } else {
        return 0;
    }
}

then within another method I call qsort with my array name and other details replacing the Microsoft example: 然后在另一个方法中,我使用数组名称和其他详细信息调用qsort替换了Microsoft的示例:

qsort((void *) &output, outputLength, sizeof(words), (compfn)compare);

This gives a segmentation fault. 这给出了分段错误。

I don't fully understand how to use qsort so I assume where I've adapted it from Microsoft's example I've done it incorrectly. 我不完全了解如何使用qsort,因此我假设我从Microsoft的示例改编了它,但是我做错了。

I hope I've included the mistake and can get some enlightenment as to what I should be doing in order for this to work correctly. 我希望我已经包含了错误,并且可以对我应该做些什么有所启发以使它正确地工作。

Many Thanks! 非常感谢!

You have to pass the array not the address of the array to qsort. 您必须将数组而不是数组的地址传递给qsort。

qsort( output, ... );

Also your compare function must return an int and accept two const void* arguments. 同样,您的compare函数必须返回一个int并接受两个const void *参数。 Casting your function int compare (words *a, words *b) to a different( yet correct ) type which is then called by qsort() will cause undefined behaviour. 将您的函数int compare (words *a, words *b)强制转换为其他类型(但正确),然后由qsort()调用将导致不确定的行为。

The compare function must be: 比较函数必须为:

int compare (const void *a, const void *b)...

Then you cast a and b to correct types: 然后,将a和b强制转换为正确的类型:

((words*)a)->hitCount < ((words*)b)->hitCount

I suspect that outputLength is computed incorrectly. 我怀疑outputLength计算不正确。 A complete working example: 一个完整的工作示例:

#include <stdio.h>
#include <stdlib.h>

typedef struct words {
    const char *word;
    int hitCount;
} words;

int compare(const void * left, const void * right) {
    const words * a = (const words *) left;
    const words * b = (const words *) right;
    if (a->hitCount > b->hitCount) {
        return -1;
    } else if (a->hitCount < b->hitCount) {
        return 1;
    } else {
        return 0;
    }
}

int main() {
    struct words output[] = {
      { "hello", 314 },
      { "world", 42 },
      { "answer", 42 }
    };
    int outputLength = sizeof(output) / sizeof(output[0]);
    int i;

    output[0].word = "hello";
    output[0].hitCount = 314;
    output[1].word = "world";
    output[1].hitCount = 42;
    qsort(output, outputLength, sizeof(words), compare);

    for (i = 0; i < outputLength; ++i) {
        printf("%d %s\n", output[i].hitCount, output[i].word);
    }

    return 0;
}

The prototype of the standard library function qsort is 标准库函数qsort的原型是

void qsort(void *base, size_t nmemb, size_t size, 
           int (*compar)(const void *, const void *));

Note the signature of the compare function. 注意compare功能的签名。 You cannot typecast a pointer to a function of different signature and make it work correctly. 您不能将指针转换为具有不同签名的函数并使它正常工作。 Therefore, typecasting your compare function will not work. 因此,类型转换您的比较功能将不起作用。 It must have the same signature as declared in the prototype of qsort . 它必须具有与qsort原型中声明的签名相同的签名。 Change your compare function to - compare功能更改为-

int compare(const void *a, const void *b) {
    int c = ((words *) a)->hitCount;
    int d = ((words *) b)->hitCount;

    if(c > d) return -1;
    if(c < d) return 1;
    return 0;
}

The first argument base of qsort is the base address of the buffer which contains the elements to be sorted. qsort的第一个参数base址是包含要排序元素的缓冲区的基址。 Also, any pointer type is assignment compatible to a void * variable and as such you don't need to cast the base address. 此外,任何指针类型都可以与void *变量赋值兼容,因此您无需强制转换基地址。 Therefore, you should call the qsort function as - 因此,您应该将qsort函数称为-

qsort(output, outputLength, sizeof output[0], compare);

Got it working with: 可以使用:

    int compare (const void *a, const void *b) {
        if (((words *)a)->hitCount > ((words *)b)->hitCount) {
            return -1;
        } else if (((words *)a)->hitCount < ((words *)b)->hitCount) {
            return 1;
        } else {
            return 0;
        }
    }

and call to sort: 并致电进行排序:

    qsort(output, outputLength, sizeof(words), compare);

Thanks to everyone's help but majority credit to "self". 多亏了大家的帮助,但大多数还是归功于“自我”。

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

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