2015-11-08 170 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'那條線。 –