繁体   English   中英

使用C qsort()的排序结构

[英]Sorting structure with C 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;
    }
}

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

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

这给出了分段错误。

我不完全了解如何使用qsort,因此我假设我从Microsoft的示例改编了它,但是我做错了。

我希望我已经包含了错误,并且可以对我应该做些什么有所启发以使它正确地工作。

非常感谢!

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

qsort( output, ... );

同样,您的compare函数必须返回一个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

我怀疑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;
}

标准库函数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;
}

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

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

可以使用:

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

多亏了大家的帮助,但大多数还是归功于“自我”。

暂无
暂无

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

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