2012-08-01 13 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

相关问题