2015-09-27 61 views
2

我在C中對dirent結構進行排序時遇到了問題。我嘗試了所有內容,無法獲取我的結構數組的值以顯示在我的比較中。我的代碼如下所示:無法使用qsort在C中對dirent進行排序

void printSortedNames(){ 

    struct dirent **file_list = (dirent**)malloc(5 * sizeof(dirent*)); 

    int i = 0; 
    for (i = 0; i < directory_size; ++i){ 
     file_list[i] = (dirent*)malloc(50 * sizeof(dirent)); 
    } 

    DIR *dir; 
    struct dirent *sd; 

    dir = opendir("."); 

    if (dir == NULL){ 
     printf("Error! unable to open directory.\n"); 
     exit(1); 
    } 

    int count = 0; 
    while ((sd = readdir(dir)) != NULL){ 
     file_list[count] = sd; 
     printf("%s\n", file_list[count]->d_name); 
     ++count; 
    } 

    size_t file_list_size = sizeof(&file_list)/sizeof(struct dirent); 

    qsort(file_list, file_list_size, sizeof(struct dirent), sizeCompare); 
} 

我創建了一個簡單的函數sizeCompare表明我的功能是工作,但我得到空值。我的功能如下:

int sizeCompare(const void* a, const void* b){ 

    printf("%s\n", ((const struct dirent*)a)->d_name); 
} 

有人可以向我解釋爲什麼我的sizeCompare不能正確檢索數組值嗎?

更新: 我曾嘗試在qsort中調整大小,因此我的值不再爲空。下面的行給我一個輸出:

qsort(file_list, 1000, sizeof(struct dirent), sizeCompare); 

顯然1000是不是一個好的解決方案。有人知道像這樣的數組的正確大小嗎?

UPDATE 2: sizeCompare函數只接受第一個參數,第二個參數爲null。

int sizeCompare(const void* a, const void* b){ 

    const struct dirent *first_dirent = *(const struct dirent **) a; 
    const struct dirent *second_dirent = *(const struct dirent **) b; 
    ....... 
    //first one works but second one is NULL 
} 
+0

這一行:'file_list [count] = sd;'只複製一個指針。你實際需要的東西類似於:'memcpy(file_list [0],sd,sizeof(struct dirent));' – user3629249

+0

你不需要轉換'void *'。 –

+0

@ user3629249的確,這段代碼泄漏了內存。不僅如此,當OP取消引用時,'closedir()'將釋放所有指向數組中懸掛指針的指針,並導致*未定義的行爲。雖然代碼中沒有'closedir()',這意味着有另一個內存泄漏。 –

回答

3
  1. 在你需要提領先鑄造的指針struct dirent **比較功能,這樣

    const struct dirent *first_dirent = *(const struct dirent **) first_parameter; 
    

    這是因爲每個元素的地址被傳遞,自元素是指針,傳遞給函數的指針是指向指針的指針。他們的void *地址是一樣的,但是你不能直接投const struct dirent **const struct dirent *

  2. 你有這樣的另一個重要問題,

    file_list_size = sizeof(&file_list)/sizeof(struct dirent); 
    

    是錯誤的,試圖打印的價值,看到它應該是

    file_list_size = count; 
    

    ,因爲你的代碼計算的大小一個指針除以大小struct dirent這可能導致0,閱讀有關sizeof運算符,它的結果取決於傳遞的參數。當它是一個變量時,類型的大小就是結果,當變量是一個數組時,它就是數組的大小。

    由於file_list是指向指針的指針,即不是陣列,那麼結果

    file_list_size = sizeof(&file_list)/sizeof(struct dirent); 
    

    是不是你認爲它是什麼或它實際應該是什麼。

  3. 沒有正確的大小,也許你應該先計算條目並預測代碼中第一個malloc()的值。或者使用realloc()並動態計數條目並同時分配泊位者。

另外:

  • 您的代碼泄漏爲this comment

  • 指出了@user3629249你不需要cast the return value from malloc()

  • 儘量不要混合代碼存儲器有了聲明,它很難追蹤變量及其範圍。

  • 您爲5 struct dirent *指針分配空間,但不會檢查count變量是否達到或超出該值。這可能導致未定義的行爲。

  • 您的代碼也會泄漏內存,因爲您從未撥打過closedir()

這裏是按字母順序排序的條目

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

#include <dirent.h> 

int 
compareSize(const void *const A, const void *const B) 
{ 
    return strcmp((*(struct dirent **) A)->d_name, (*(struct dirent **) B)->d_name); 
} 

void printSortedNames(const char *const path) 
{ 
    int count; 
    DIR *dir; 
    struct dirent **list; 
    struct dirent *entry; 

    dir = opendir(path); 
    if (dir == NULL) 
    { 
     fprintf(stderr, "cannot open `%s'\n", path); 
     return; 
    } 

    /* First determine the number of entries */ 
    count = 0; 
    while ((entry = readdir(dir)) != NULL) 
     ++count; 
    /* Allocate enough space */ 
    list = malloc(count * sizeof(*list)); 
    if (list == NULL) 
    { 
     closedir(dir); 
     fprintf(stderr, "memory exhausted.\n"); 
     return; 
    } 
    /* You don't need to allocate the list elements 
    * you can just store pointers to them in the 
    * pointer array `list' 
    */ 
    rewinddir(dir); /* reset position */ 
    /* Save the pointers allocated by `opendir()' */ 
    count = 0; 
    while ((entry = readdir(dir)) != NULL) 
     list[count++] = entry; 
    /* Call `qsort()', read about the `sizeof' operator */ 
    qsort(list, count, sizeof(*list), compareSize); 
    /* Print the sorted entries now */ 
    for (int index = 0 ; index < count ; ++index) 
     fprintf(stderr, "%s\n", list[index]->d_name); 
    closedir(dir); 
} 

int 
main(void) 
{ 
    printSortedNames("/home/iharob"); 
    return 0; 
} 

記住的count值限制爲您分配的空間指針的最大數量的例子。

+0

我已經添加了您提到的行,但first_dirent的值爲NULL。我似乎有一個問題,傳遞到比較函數 – VMA92

+0

值的大小。我會嘗試數數,看看如何。 – VMA92

+0

@ VMA92請將'readdir()'循環限制爲'5'(與'malloc(5 * sizeof(struct dirent *))'同時測試,否則無法預測程序的結果。另外,你使用'malloc()'並且使用'dirent'而不使用'struct'建議你使用一個C++編譯器。如果這是真的,請重新回答你的問題並讓我刪除答案,因爲C++程序員不會使用這個函數來完成這個任務。 –

3

您的sizeCompare函數沒有返回任何東西。你需要實現的是當它返回-1時a < b,0時a = b和1時a > b

int sizeCompare(const void* a, const void* b) { 
    // The implementation should return something 
} 

此外,您正在計算file_list_size不正確。你不能通過count作爲第二個參數嗎?

qsort(file_list, count, sizeof(struct dirent), sizeCompare); 
+0

是的我知道,我的問題是更多的是,它不是打印任何告訴我的值傳遞到A和B是空的這是我的主要問題 – VMA92

+0

也許錯誤是在計算'file_list_size'。 'sizeof(&file_list)'的價值是什麼? –

+0

我得到sizeof(&file_list)的值爲 – VMA92