2016-10-02 124 views
0

我想學習C編程的工作任務,我已經設置了一個小項目,其中包括讀取文件樹,包括所有子目錄獲取有關每個文件的信息。像樹命令打印線

我沒能解決的問題是,如何讓行打印時,所有的真正的樹命令執行的目錄。

,這是我的示例代碼:

enum { doSkip, isFile, isDir } testDir(char *path, char *name) 
{ 
    struct stat st_buf;   
    if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { 
     return doSkip; 
    } 
    stat(path, &st_buf); 
    if (S_ISDIR(st_buf.st_mode)) 
     return isDir; 
    return isFile; 
} 

void list(const char *path, int indentlevel) 
{ 
    DIR *dirp = opendir(path); 
    struct dirent *dentry; 
    char buf[1024]; 
    if (!dirp) { 
     printf("%*sNo access\n",indentlevel,""); 
     return; 
    } 

    while ((dentry = readdir(dirp)) != NULL) { 

     sprintf(buf,"%s/%s", path, dentry->d_name); 
     switch (testDir(buf,dentry->d_name)) { 
     case doSkip: 
      /* do nothing */ 
      break; 
     case isDir: 
      printf("%*s%s:\n",indentlevel,"",dentry->d_name); 
      list(buf,indentlevel+4); 
      break; 
     case isFile: 
      printf("%*s%s\n",indentlevel,"",dentry->d_name); 
      break; 
     } 
    } 
    closedir(dirp); 
} 

int main() 
{ 
    list(".", 0); 
    return 0; 
} 

,請給我一些想法!

+1

您需要一個縮進級別的列表,爲多於一個子目錄深度繪製多個並行分支。 – tripleee

+0

我看到的唯一區別是樹命令的輸出是排序的。因此,如果您想對結果進行排序,只需將它們放入某種容器中,然後進行分類和打印。如果有更多的分類,讓我知道。 – Klaus

+0

如何製作縮進級別列表? @tripleee – Hmmmmm

回答

0
list(buf,indentlevel+4); 

你應該更改爲list(buf,indentlevel+1),因爲你只打算一級。這樣您可以跟蹤目錄級別。添加另一個功能來添加額外的空格。看下面的例子:

void space(int level, int file) 
{ 
    int i; 
    for (i = 0; i < level + 1; i++) 
     printf("\x0b3 "); // add the '│' character 
    if (file) 
     printf("\x0c3\x0c4 "); // add '├' and '─' characters 
} 

void list(const char *path, int indentlevel) 
{ 
    DIR *dirp = opendir(path); 
    struct dirent *dentry; 
    char buf[1024]; 
    if (!dirp) 
    { 
     printf("%*sNo access\n",indentlevel,""); 
     return; 
    } 

    int i; 
    while ((dentry = readdir(dirp)) != NULL) 
    { 
     sprintf(buf,"%s/%s", path, dentry->d_name); 
     switch (testDir(buf,dentry->d_name)) 
     { 
     case doSkip: 
      break; 
     case isDir: 
      space(indentlevel, 1); 
      putchar('\n'); 
      space(indentlevel, 0); 
      printf("[ %s ]\n",dentry->d_name); 
      list(buf,indentlevel+1); 
      break; 

     case isFile: 
      space(indentlevel-1, 1); 
      printf("%s\n",dentry->d_name); 
      break; 
     } 
    } 

    closedir(dirp); 
} 

這裏是一個更復雜的版本,它在緩衝區中存儲數據,所以它可以找到文件夾中的最後一個孩子,並得出正確的「方緣」字的最後一個項目。它仍然打印一些額外的垂直線,需要照顧。

//store directory information 
typedef struct TT_dir 
{ 
    char* name; 
    int isdir; 
    int level; 
    int islast; 
} T_dir; 

//vector for holding lines of data 
typedef struct TT_vector 
{ 
    T_dir *data; 
    int capacity; 
    int size; 
} T_vector; 

void vector_add(T_vector *pvec, char *buf, int isdir, int level) 
{ 
    if (pvec->size == pvec->capacity) 
    { 
     pvec->capacity += 16; 
     pvec->data = realloc(pvec->data, pvec->capacity * sizeof(T_dir)); 
    } 

    char *duplicate = malloc(strlen(buf) + 1); 
    strcpy(duplicate, buf); 
    pvec->data[pvec->size].name = duplicate; 
    pvec->data[pvec->size].isdir = isdir; 
    pvec->data[pvec->size].level = level; 
    pvec->data[pvec->size].islast = 0; 
    pvec->size++; 
} 

void list(const char *path, int level, T_vector *pvec) 
{ 
    DIR *dirp = opendir(path); 
    struct dirent *dentry; 
    char buf[4096]; 
    if (!dirp) 
    { 
     printf("%*sNo access\n", level, ""); 
     return; 
    } 

    int haschildren = 0; 
    while ((dentry = readdir(dirp)) != NULL) 
    { 
     sprintf(buf, "%s/%s", path, dentry->d_name); 
     switch (testDir(buf, dentry->d_name)) 
     { 
     case doSkip: 
      break; 
     case isDir: 
      //show progress: 
      printf("."); 

      //add directory info to vector array 
      vector_add(pvec, dentry->d_name, 1, level); 

      //next dir... 
      list(buf, level + 1, pvec); 
      haschildren = 1; 
      break; 

     case isFile: 
      //add directory info to vector array 
      vector_add(pvec, dentry->d_name, 0, level); 
      haschildren = 1; 
      break; 
     } 
    } 

    //needs this information for drawing the correct character 
    if (haschildren) 
     pvec->data[pvec->size - 1].islast = 1; 

    closedir(dirp); 
} 

int main() 
{ 
    T_vector vec; 
    vec.capacity = 0; 
    vec.size = 0; 
    vec.data = 0; 

    list(".", 0, &vec); 
    printf("\n"); 

    int i, k; 
    for (i = 0; i < vec.size; i++) 
    { 
     if (vec.data[i].isdir) 
     { 
      for (k = 0; k < vec.data[i].level; k++) printf("\x0b3 "); 
      printf("\x0b3\n"); 

      for (k = 0; k < vec.data[i].level; k++) printf("\x0b3 "); 

      printf(vec.data[i].islast ? "\x0c0" : "\x0c3"); 

      printf("\x0c4 %s:\n", vec.data[i].name); 
     } 
     else 
     { 
      for (k = 0; k < vec.data[i].level; k++) printf("\x0b3 "); 

      printf(vec.data[i].islast ? "\x0c0" : "\x0c3"); 

      printf("\x0c4 %s\n", vec.data[i].name); 
     } 
    } 

    return 0; 
} 
-1

您所需的洞察力是的printf不必打印全系列。不像其他一些其他語言的打印功能。

for(i=0;i<identlevel;i++) 
    printf("-"); 
printf("[ %s ]\n", dentry->dname); 

會做的伎倆。