2013-08-23 34 views
2

我想存儲char **變量中的文件列表。如何在c中正確使用scandir()?

scandir()正常結束,但嘗試打印char **時出現分段錯誤。

下面的代碼:

int main() 
{ 
    char** fileList; 
    int noOfFiles; 
    char* path = "."; 
    makeList(&fileList, &noOfFiles, path); 
    return 0; 
} 

void makeList(char ***fileList, int* noOfFiles, char* path){ 
    struct dirent **fileListTemp; 
    *noOfFiles = scandir(path, &fileListTemp, NULL, alphasort); 
    int i; 
    fileList = (char***)malloc(sizeof(char***)); 
    *fileList = (char**)malloc(*noOfFiles * sizeof(char*)); 
    printf("total: %d files\n",*noOfFiles); 
    for(i = 0; i < *noOfFiles; i++){ 
     *fileList[i] = (char*)malloc(strlen(fileListTemp[i] -> d_name) *sizeof(char)); 
     strcpy(*fileList[i], fileListTemp[i] -> d_name); 
     printf("%s\n",*fileList[i]); 
    } 
    return; 
} 

此打印2文件名後給出一個分段錯誤。

輸出:

總:27個文件。

..

.jv

分割故障(核心轉儲)

+2

[請不要投在C.的malloc()](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – chrylis

+0

沒有必要投入分配的內存?請詳細說明。 – kBisla

+2

這個鏈接有很好的解釋。關於你的問題,你傳入'char *** fileList'(一個指向聲明變量的指針,它是'main'中的'char ** fileList'),然後直接寫入堆棧的值。你的意思是說'* fileList = malloc(sizeof(char **))'?對不同級別的指針使用相同的名稱會讓人感到困惑。 – chrylis

回答

12

函數scandir()爲您分配內存。

您不需要分配任何內存。你DO需要釋放你回憶的內存scandir()

代碼調用:*noOfFiles = scandir(path, &fileListTemp, NULL, alphasort);

在返回時,noOfFiles將包含目錄條目的數量在path目錄,fileListTemp將指向指針的分配數組分配字符串分別指向已分配塊包含文件的空終止名稱。

如果您的目錄中包含的文件「FirstFile.txt」,「AnotherFile.txt」,「ThirdFile.txt」,例如,有你的電話,當從scandir()回報,noOfFiles將被設置爲爲三個文件加兩個「。」。和「..」目錄條目。如果您不通過'alphasort',條目將毫無特別地排列。 (實際上這有點不正確,它們將按照目錄文件名條目的順序,這取決於文件最初創建的順序。)

因爲您通過'alphasort',您應該看到以下條目爲了(我明確地顯示了空字節串終止:

fileListTemp[0] == ".\0" 
fileListTemp[1] == "..\0" 
fileListTemp[2] == "AnotherFile.txt\0" 
fileListTemp[3] == "FirstFile.txt\0" 
fileListTemp[4] == "ThirdFile.txt\0" 

所以fileListTemp點分配的內存持有五(字符*)指針每五(的char *)的指針指向一個塊。一個包含空終止的目錄條目名稱的已分配內存塊。

SIX分配的內存塊。

您可以使用這塊內存,直到你用它做,然後你對數組中的()數組本身的每一個條目,然後自由調用free()。

你必須釋放每個條目以及數組本身。它們都是獨立分配的內存塊。

當您使用列表,你應該做到:

for (int i = 0; i < noOfFiles; i++) 
    { 
    free(fileListTemp[i]; 
    } 

free(fileListTemp); 
+1

使用內嵌代碼(: –

0

我不知道這是問題,但你必須爲空終止分配另一個字節:

*fileList[i] = (char*)malloc(strlen(fileListTemp[i] -> d_name + 1) *sizeof(char)); 
+1

這裏有一個很好的指針意大利麪條。它大部分是不可避免的,但我懷疑堆棧粉碎。 – chrylis

+1

這是挑戰... 否則我可以找出一些其他更長的方式來實現相同的結果... 但是,學習者仍然... – kBisla

5

這是一個老問題,但自從我來後,它並沒有爲有效的手冊頁做了,我解決我的問題複製man頁面中的代碼片段作爲未來的新答案。

#include <dirent.h> 

    int 
    main(void) 
    { 
     struct dirent **namelist; 
     int n; 

     n = scandir(".", &namelist, NULL, alphasort); 
     if (n < 0) 
      perror("scandir"); 
     else { 
      while (n--) { 
       printf("%s\n", namelist[n]->d_name); 
       free(namelist[n]); 
      } 
      free(namelist); 
     } 
    } 
+0

這不會編譯,此添加到頂部 '#包括'' 的#include ' – gschaden

+0

@gschaden,如果你看夠了對答案的話,你會發現,大多數是那些使用標準的頭承擔這些責任。 – merlin2011