使用C qsort()排序结构

时间:2014-04-01 17:46:12

标签: c sorting struct qsort

无法深入实现C中内置的qsort()以按存储的int值(hitCount)对结构数组进行排序。

我的结构:

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

我正在尝试使用Microsoft提供的示例(http://support.microsoft.com/kb/73853)。

所以我得到了顶部:

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

和比较方法:

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

然后在另一个方法中,我使用我的数组名称和其他详细信息替换Microsoft示例调用qsort:

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

这会产生分段错误。

我不完全了解如何使用qsort所以我假设我从微软的例子中调整了它我做错了。

我希望我已经包含了这个错误,并且可以获得一些关于我应该做什么的启示,以使其正常工作。

非常感谢!

4 个答案:

答案 0 :(得分:3)

您必须将数组而不是数组的地址传递给qsort。

qsort( output, ... );

此外,您的比较函数必须返回一个int并接受两个const void *参数。 将函数int compare (words *a, words *b)转换为另一个(但正确的)类型然后由qsort()调用将导致未定义的行为。

比较功能必须是:

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

然后你将a和b转换成正确的类型:

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

答案 1 :(得分:1)

我怀疑outputLength计算不正确。一个完整的工作示例:

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

答案 2 :(得分:1)

标准库函数qsort的原型是

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

请注意compare功能的签名。 您不能将指针指向不同签名的函数并使其正常工作。因此,对比较函数进行类型转换将不起作用。它必须具有与qsort原型中声明的相同的签名。将您的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;
}

base的第一个参数qsort是包含要排序的元素的缓冲区的基址。此外,任何指针类型都与void *变量兼容,因此您无需转换基址。因此,您应该将qsort函数称为 -

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

答案 3 :(得分:0)

使用它:

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

并致电排序:

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

感谢大家的帮助,但多数人都归功于“自我”。