像树命令一样的打印线

我正在尝试为工作中的任务学习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; } 

请给我一些想法!

 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; } 

您需要的洞察力是printf不必打印整行。 与其他语言中的其他打印function不同。

 for(i=0;idname); 

会做的伎俩。