面试题答案
一键面试#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <limits.h>
// 遍历目录及其子目录
void traverse_directory(const char *path) {
DIR *dir;
struct dirent *entry;
struct stat statbuf;
char new_path[PATH_MAX];
dir = opendir(path);
if (dir == NULL) {
perror("opendir");
return;
}
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
// 构建新路径
snprintf(new_path, PATH_MAX, "%s/%s", path, entry->d_name);
if (stat(new_path, &statbuf) == -1) {
perror("stat");
continue;
}
if (S_ISDIR(statbuf.st_mode)) {
// 处理符号链接(避免目录循环)
if (lstat(new_path, &statbuf) == -1) {
perror("lstat");
continue;
}
if (S_ISLNK(statbuf.st_mode)) {
// 这里简单处理符号链接,不深入遍历
continue;
}
traverse_directory(new_path);
} else if (S_ISREG(statbuf.st_mode)) {
printf("%s\n", new_path);
}
}
closedir(dir);
}
优化思路
- 减少系统调用:每次调用
stat
或lstat
都是系统调用,开销较大。可以在读取目录项时,尽量一次性获取所需信息,减少不必要的系统调用。 - 使用栈代替递归:递归调用会占用栈空间,如果目录结构非常深,可能导致栈溢出。可以使用栈数据结构手动模拟递归过程,这样可以避免栈溢出问题,并且在一定程度上提高效率。
- 并行处理:对于多核系统,可以考虑使用多线程或多进程并行处理子目录的遍历,从而加快整个遍历过程。但要注意处理好同步和资源竞争问题。
你可以在main
函数中调用traverse_directory
函数,例如:
int main() {
traverse_directory(".");
return 0;
}
上述代码中,traverse_directory
函数递归遍历给定目录及其子目录,并输出所有文件的完整路径。在遍历过程中,通过lstat
函数处理符号链接,避免目录循环,通过跳过.
和..
目录项处理权限问题(因为访问..
目录可能存在权限问题)。同时提供了一些优化思路以提高遍历效率。