我想使用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()
的方法,无法比较。
我不知道我的代码与for range循环有什么不同,除了存储迭代器和有一个额外的条件。
如果您查看std::filesystem::recursive_directory_iterator非成员函数,您可以看到:
// 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
循环,以防迭代器已经在它的"end"当输入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 "";
}