MST
星途 面试题库

面试题:C语言递归实现目录遍历

在C语言环境下,编写一个递归函数,实现对给定目录及其所有子目录的遍历,输出目录下所有文件的完整路径。假设你使用的是POSIX系统(如Linux或macOS),可以使用<dirent.h>头文件中的相关函数。在实现过程中,要考虑到符号链接、权限问题以及可能出现的目录循环等特殊情况,并说明如何优化该递归遍历以提高效率。
40.2万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
#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);
}

优化思路

  1. 减少系统调用:每次调用statlstat都是系统调用,开销较大。可以在读取目录项时,尽量一次性获取所需信息,减少不必要的系统调用。
  2. 使用栈代替递归:递归调用会占用栈空间,如果目录结构非常深,可能导致栈溢出。可以使用栈数据结构手动模拟递归过程,这样可以避免栈溢出问题,并且在一定程度上提高效率。
  3. 并行处理:对于多核系统,可以考虑使用多线程或多进程并行处理子目录的遍历,从而加快整个遍历过程。但要注意处理好同步和资源竞争问题。

你可以在main函数中调用traverse_directory函数,例如:

int main() {
    traverse_directory(".");
    return 0;
}

上述代码中,traverse_directory函数递归遍历给定目录及其子目录,并输出所有文件的完整路径。在遍历过程中,通过lstat函数处理符号链接,避免目录循环,通过跳过...目录项处理权限问题(因为访问..目录可能存在权限问题)。同时提供了一些优化思路以提高遍历效率。