2015-11-08 82 views
2

我需要打印出的文件和目录(以及子目录和文件)的帮助下使用递归C.Ç - 打印出递归

目录和文件这是我的代码有:

char filepath[250], filename[250]; 

void listdir(char *dir) 
{ 
    DIR *dp; 
    struct dirent *entry; 
    struct stat statbuf; 

    if((dp = opendir(dir)) == NULL) 
    { 
     fprintf(stderr,"cannot open directory: %s\n", dir); 
     return; 
    } 
    chdir(dir); 

    while((entry = readdir(dp)) != NULL) 
    { 
     if(lstat(entry->d_name, &statbuf) == 0) 
     { 
      if(statbuf.st_mode & S_IFDIR) 
      { 
       /* Found a directory, but ignore . and .. */ 
       if(strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0) 
        continue; 

       // Concatenate directory name 
       strcat(filepath, entry->d_name); 
       strcat(filepath, "/"); 

       /* Recurse at a new indent level */ 
       listdir(entry->d_name); 
      } 
      else 
      { 
       // Concatenate file name 
       strcpy(filename, filepath); 
       strcat(filename, entry->d_name); 
       puts(filename); 
      } 
     } 
    } 

    chdir(".."); 
    closedir(dp); 
} 

有我已经注意到这个代码中的两个问题。比方说,这是我的文件结构:

index.c 
main.c 
test.o 
test/hello.txt 
test/Untitled.txt 
test/random/ 

当我运行上面的程序,有两种可能的产出取决于文件的结构,我可以得到。

一种可能的情况下(这人说Untitled.txt是文件夹内随机的,当它不是):

index.c 
main.c 
test.o 
test/hello.txt 
test/random/Untitled.txt 

如果我重新命名Untitled.txt喜欢的东西apple.txt,那么它将打印没问题。这让我相信,它按字母顺序排列。

如何让它先打印出所有的文件然后进入一个文件夹并打印出所有文件然后重复?所以打印文件>进入文件夹>重复。

+0

你用来打印文件名的变量'path'在哪里?你填写变量'filepath',但使用'path',就是这样吗? –

+0

这是一个错字。将其更改为文件路径。 –

+1

如果你有另一个目录在同一级别的'random'会发生什么?你永远不会从'filepath'中删除当前目录名,所以当退出'random'并且在进入另一个目录后会产生一个无效的路径。可能这也是你问题的原因。 –

回答

1

的问题是在这里:

strcat(filepath, entry->d_name); 
strcat(filepath, "/"); 

/* Recurse at a new indent level */ 
listdir(entry->d_name); 

要追加任何值是filepath以前。因此,无论何时您从一个目录返回时,都会追加到filepath设置在较低级别目录中的值。

您从递归调用回来后,你需要删除您添加的条目,并可能已在较低级别被添加任何其他:

int len = strlen(filepath); 
strcat(filepath, entry->d_name); 
strcat(filepath, "/"); 

/* Recurse at a new indent level */ 
listdir(entry->d_name); 

/* cleanup filepath */ 
filepath[len] = '\0'; 

编辑:

你也可以做这没有全局变量,也没有改变目录:

void listdir(char *dir) 
{ 
    DIR *dp; 
    struct dirent *entry; 
    struct stat statbuf; 
    char *subdir; 

    if((dp = opendir(dir)) == NULL) 
    { 
     fprintf(stderr,"cannot open directory: %s\n", dir); 
     return; 
    } 

    while((entry = readdir(dp)) != NULL) 
    { 
     if(lstat(entry->d_name, &statbuf) == 0) 
     { 
      if(statbuf.st_mode & S_IFDIR) 
      { 
       /* Found a directory, but ignore . and .. */ 
       if(strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0) 
        continue; 

       // allocate space for parent directory, "/", subdir, plus NULL terminator 
       subdir = malloc(strlen(dir) + strlen(entry->d_name) + 2); 
       // Concatenate directory name 
       strcpy(subdir, dir); 
       strcat(subdir, "/"); 
       strcat(subdir, entry->d_name); 

       /* Recurse at a new indent level */ 
       listdir(subdir); 
       free(subdir); 
      } 
      else 
      { 
       // Print file name 
       printf("%s/%s\n", dir, entry->d_name); 
      } 
     } 
    } 

    closedir(dp); 
} 
+0

这和以前一样。它仍然打印出test/random/Untitled.txt。 –

+0

请注意,第一个函数调用是'strcpy'而不是'strcat'。 –

+0

是的,我有'strcpy'而不是'strcat'那条线。 –