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

iterating through all the directories and subdirectories in c++

我想使用 std::filesystem::recursive_directory_iterator class 创建一个 class 方法遍历所有子目录并处理找到的 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) Returns a default-constructed recursive_directory_iterator, which serves as the end iterator. The argument is ignored.

所以你会检查it是否不等于std::end(it),所以看看有没有更多的元素。而且你必须增加 it 而不是 p.

您还需要在执行 !is_xml(*it.path())

之前检查是否 it != std::end(it)
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 根本没有理由成为 class 成员。应该改成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 "";
}