簡體   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