遍历c++中的所有目录和子目录

问题描述

我想使用 std::filesystem::recursive_directory_iterator 类创建一个方法,它遍历所有子目录并处理找到的 xml 文件

我在互联网上找到的唯一方法是使用这样的 for 循环:

for (fs::directory_entry p : fs::recursive_directory_iterator("my_file"))
    do_something(p);

问题是我需要在函数调用之间存储我的迭代器(或至少它指向的位置),因为我一次只能处理一个文件。我试着像这样实现它:

class C {
private:
    std::filesystem::recursive_directory_iterator it;
    std::filesystem::directory_entry p;
public:
    C(std::filesystem::path);
    std::string find_file();
};

C::C(std::filesystem::path path)
{
    it = fs::recursive_directory_iterator(path);
    p = fs::directory_entry(it.begin());
}

std::string C::find_file()
{
    do { //using do while so my function won't load the same file twice
        ++p;
    } while (!is_xml(p.path()) && p != it.end());

}

但似乎 std::filesystem::recursive_directory_iterator 没有 begin()end() 方法,无法进行比较。

我不知道我的代码与工作范围循环有何不同,除了存储迭代器和有一个额外的条件。

解决方法

如果您查看 std::filesystem::recursive_directory_iterator Non-member functions,您可以看到:

// range-based for loop support
begin(std::filesystem::recursive_directory_iterator)
end(std::filesystem::recursive_directory_iterator)

然后 std::filesystem::begin(recursive_directory_iterator),std::filesystem::end(recursive_directory_iterator) 提供更多详细信息:

end(recursive_directory_iterator) 返回一个默认构造的 recursive_directory_iterator,用作结束迭代器。参数被忽略。

因此您将检查 it 是否不等于 std::end(it),然后查看是否还有更多元素。并且您必须增加 it 而不是 p

您还需要在执行it != std::end(it)之前检查是否!is_xml(*it.path())

std::string C::find_file()
{
    do { //using do while so my function won't load the same file twice

        ++it;
    } while (it != std::end(it) && !is_xml(*it.path()));

}
,

recursive_directory_iterator 本身已经是一个迭代器(它的名字说得很对),所以你根本不需要使用 begin()end()。它实现了 operator==operator!=operator->operator++,在本例中您只需要这些。

此外,p 根本没有理由成为班级成员。应该是find_file()的局部变量(其实这种情况下是可以完全消除的)。并且循环应该是 while 循环而不是 do..while 循环,以防在输入 find_file() 时迭代器已经处于“结束”。

试试这个:

class C {
private:
    std::filesystem::recursive_directory_iterator it;
public:
    C(std::filesystem::path);
    std::string find_file();
};

C::C(std::filesystem::path path)
    : it(path)
{
}

std::string C::find_file()
{
    static std::filesystem::directory_iterator end;
    while (it != end) {
        auto p = it->path();
        if (is_xml(p))
            return p.string();
        ++it;
    }
    return "";
}