2012-08-01 11 views
0

我需要對具有特定擴展名(* .bob)的文件列表進行一些操作,這些操作都存儲在相同的目錄中。這些文件是圖像幀,其名稱格式是frame_XXXX.bob。我不知道先驗幀的數量,我需要確保按順序處理它們(從第0幀到最後一幀)。我閱讀struct dirent *readdir(DIR *dirp)文件夾的內容,但由於它不能保證文件將按字母順序閱讀(儘管看起來總是如此),我想將它們放入單個鏈接列表中,然後在處理之前對它們進行排序進一步。 我將這個列表的頭部保存到指針filesListStart之前,然後讀取整個文件夾內容,如果它具有「.bob」擴展名,則將每個條目添加到列表中。當所有幀數達到100幀時,這一切都很好,但由於某種原因,超出了這個範圍 - 指針filesListStart指向的值不再包含列表中第一個條目的文件名。代碼不使用任何數字,所以我不知道超過100個元素的意義是什麼。 在我開始填充列表之前和之後,我寫出了內存地址filesListStart,它們是相同的,但是它們在魔術上顯示的值發生了變化。當我設置filesListStart它指向的對象與字段fileName等於「frame_0000.bob」(這是預期的),但填充列表後,它指向的名稱變成「e_0102.bob」。當列表增長超過100個元素時,鏈表頭部的值默認會更改

列表結構定義爲

// List structure 
struct FilesList { 
    char *fileName ; 
    struct FilesList *next ; 
} ; 

有問題的代碼是:

DIR *moviesDir ; 
moviesDir = opendir("movies") ; 

if(moviesDir == NULL) 
{ 
    printf("Make Movie failed to open directory containing bob frames\n") ; 
    return ; 
} 

struct dirent *dirContent ; 

// Get first .bob frame name from the directory 
dirContent = readdir(moviesDir) ; 
// isBobFile(dirContent) returns 1 if entry has ".bob" extension and 0 otherwise 
while(!isBobFile(dirContent)) 
{ 
    dirContent = readdir(moviesDir) ; 
} 

struct FilesList *filesList = (struct FilesList*) 
    malloc(sizeof(struct FilesList)) ; 

// Initialize the list start at that first found .bob frame 
filesList->fileName = dirContent->d_name; 
// And save the head of the list 
struct FilesList *filesListStart = filesList ; 
printf("FilesListStart: %s\n", filesListStart->fileName) ; 
printf("Address is: %p\n", filesListStart) ; 

// For all other bob frames 
while((dirContent = readdir(moviesDir)) != NULL) 
{ 
    if(isBobFile(dirContent)) 
    { 
    struct FilesList *temporaryNode = (struct FilesList*) 
     malloc(sizeof(struct FilesList)); 
    temporaryNode->fileName = dirContent->d_name ; 
    filesList->next = temporaryNode ; 
    filesList = temporaryNode ; 
    } 
} 
// Set the 'next' pointer of the last element in list to NULL 
filesList->next = NULL ; 
// close stream to directory with .bob frames 
closedir(moviesDir) ; 

// Check what FilesListStart points at 
printf("FilesListStart: %s\n", filesListStart->fileName) ; 
printf("Address is: %p\n", filesListStart) ; 

// Rest of the code 

回答

2

你應該做一個副本dirContent->d_name而不是使用實際值。

無論何時調用readdir,運行時庫都可以自由更改該dirent結構的內容,並且如果所有存儲的都是地址,則底層內存可能會更改。從POSIX手冊頁:

readdir()返回的指針指向可能被另一個對同一目錄流上的readdir()的調用覆蓋的數據。

換句話說,更換線路:

filesList->fileName = dirContent->d_name; 
temporaryNode->fileName = dirContent->d_name ; 

有:

filesList->fileName = strdup (dirContent->d_name); 
temporaryNode->fileName = strdup (dirContent->d_name); 

假設你有一個strdup樣的功能,如果沒有,你可以得到一個便宜的here

如果它只是在100次調用後才發生變化,那麼運行時可能會更智能一些,但即使它不能存儲無限數字,因此它可能會設置一個合理的限制。

只要記住釋放所有這些字符指針,然後釋放鏈接列表節點(假設在「其餘代碼」部分中的某處)。

+0

工作就像一個魅力,謝謝。正如你指出的那樣,我懷疑問題出在'filesList-> fileName = dirContent-> d_name'上,但是不知道如何將一個值從一個指針複製到另一個指針。任何'*(filesList-> fileName)= *(dirContent-> d_name)'和其他我想出來的東西都會導致警告,分段錯誤或非法指令。再一次感謝你。 – Puchatek 2012-08-01 06:18:50

+0

@Puchatek:確保你改變了另一條線(我最初錯過的) - 我已經更新了答案以顯示它。 – paxdiablo 2012-08-01 06:22:26

相關問題