【问题标题】:iterating through all the directories and subdirectories in c++遍历 C++ 中的所有目录和子目录
【发布时间】:2021-07-29 09:39:25
【问题描述】:

我想使用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()方法,无法比较。

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

【问题讨论】:

  • 尝试开始(它),结束(它)
  • 哦,nvm,我更改了 p 类型,它现在可以工作了,ty

标签: c++ c++17 boost-filesystem std-filesystem


【解决方案1】:

如果你查看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。

你还需要在!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(it) 和例如向量的 it.begin() ?
  • @skrzype 如果std::begin 和std::end 没有重载,它们将默认调用.begin() 和.end() 传递的值。因此,您可以将std::begin(var) 和std::end(var) 用于通用代码,而不是使用var.begin() 和var.end()。但是,如果您查看Range-based for loop: Explanation,您可以看到基于范围如何决定使用什么。所以它实际上检查成员函数是否存在,如果不存在,它将回退到使用std::begin/std::end
【解决方案2】:

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 "";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-22
    • 2019-01-10
    • 1970-01-01
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多