我必须递归列出给定目录的所有子目录,但我可以使它正常工作,但是却无序列出了它们。我希望它列出给定目录的所有子目录,然后转到下一个子目录,我知道这是因为我的递归位于while循环内,但是我无法弄清楚如何在循环外实现它。我曾考虑过用子目录的路径创建一个字符串数组并将其用作堆栈,但是在查找之后,我认为这是不可能的。
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
int listDir(char *name)
{
DIR *dir;
struct dirent *cDir;
dir = opendir(name);
if(dir != NULL)
{
while((cDir=readdir(dir)) != NULL)
{
char* subName = cDir->d_name;
if(strcmp(subName, ".")==0 || strcmp(subName, "..")==0)
continue;
else
{
// Checks if it's a directory
if(cDir->d_type == DT_DIR)
{
printf("%s\n", subName);
char *path;
path = malloc(sizeof(name) + sizeof(subName) + 2);
strcat(path, name);
strcat(path, "/");
strcat(path, subName);
listDir(path);
}
}
}
closedir(dir);
}
}
int main(int argc, char *argv[])
{
printf("%s\n", argv[1]);
listDir(argv[1]);
return 0;
}
要在BFS中打印目录结构,可以使用队列。由于C标准库中没有这样的东西,因此您必须自己滚动或使用一个库。这是一个简单的示例,说明了它如何工作以及DFS的清理版本。
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void listDirBFS(char *name)
{
int q_front = 0;
int q_back = 1;
int q_cap = 4;
char **q = malloc(q_cap * sizeof(*q));
for (q[0] = strdup(name); q_front != q_back;)
{
name = q[q_front++];
DIR *dir = opendir(name);
if (!dir) continue;
printf("%s\n", name);
size_t name_len = strlen(name);
struct dirent *cDir;
while ((cDir = readdir(dir)))
{
char *subName = cDir->d_name;
if (strcmp(subName, ".") && strcmp(subName, "..") &&
cDir->d_type == DT_DIR)
{
char *path = malloc(name_len + strlen(subName) + 2);
sprintf(path, "%s/%s", name, subName);
if (q_back >= q_cap &&
!(q = realloc(q, sizeof(*q) * (q_cap *= 2))))
{
fprintf(stderr, "%s:%d realloc\n", __FILE__, __LINE__);
exit(1);
}
q[q_back++] = path;
}
}
free(name);
closedir(dir);
}
free(q);
}
void listDir(char *name)
{
DIR *dir = opendir(name);
if (!dir) return;
printf("%s\n", name);
size_t name_len = strlen(name);
struct dirent *cDir;
while ((cDir = readdir(dir)))
{
char *subName = cDir->d_name;
if (strcmp(subName, ".") && strcmp(subName, "..") &&
cDir->d_type == DT_DIR)
{
char *path = malloc(name_len + strlen(subName) + 2);
sprintf(path, "%s/%s", name, subName);
listDir(path);
free(path);
}
}
closedir(dir);
}
int main(int argc, char **argv)
{
puts("== DFS ==");
listDir(".");
puts("\n== BFS ==");
listDirBFS(".");
return 0;
}
输出:
== DFS ==
.
./a
./a/b
./a/b/e
./a/bb
./a/bb/f
./a/bb/f/g
./aa
./aa/c
./aaa
./aaa/d
./aaa/d/h
./aaa/d/hh
== BFS ==
.
./a
./aa
./aaa
./a/b
./a/bb
./aa/c
./aaa/d
./a/b/e
./a/bb/f
./aaa/d/h
./aaa/d/hh
./a/bb/f/g
关于您的代码的几点评论和建议:
sizeof(name) + sizeof(subName)
不正确。 sizeof
返回指针的大小; strlen
可能是您想要获得指向的字符串的长度的目的。这样可以避免由于strcat
超出分配的内存而导致的未定义行为。free
内存以避免内存泄漏。-Wall
标志进行编译以打开警告,这表明控制已到达非无效函数的末尾。如果您实际上没有返回整数,请将返回类型从int
更改为void
。我必须递归列出给定目录的所有子目录
请注意,目录对于C11标准是未知的。通过阅读n1570进行检查。与目录相关的API是operating system特定的。在Windows上是WinAPI。
在Linux系统上,您应该使用nftw(3);它会为您完成大部分工作。或考虑使用Glib之类的库。
您将向某个函数传递一些函数,这些函数会填充(和/或nftw
)一些指向经过仔细定义的realloc的全局指针
注意struct
为GNU findutils。您可以研究其源代码以获取灵感。
注意free software或sash具有内置的busybox命令,并且为find
。您可以研究其源代码以获取灵感。
open source(还有zsh
shell)具有强大的外壳扩展功能,包括像zsh
这样的递归fish
shell,因此您可以研究其源代码以获取灵感。