gpt4 book ai didi

C++ 自定义惰性迭代器

转载 作者:行者123 更新时间:2023-11-30 04:46:50 25 4
gpt4 key购买 nike

我有一个比较简单的文本文件解析器。我解析的文本被分成由 { block data } 表示的 block 。

我的解析器有一个 string read() 函数,它可以取回标记,例如在上面的示例中,第一个标记是 {,然后是 block 后跟 data 后跟 }

为了减少重复性,我想编写一个类似于生成器的迭代器,它允许我编写类似于此 JavaScript 代码的内容:

* readBlock() {
this.read(); // {

let token = this.read();

while (token !== '}') {
yield token;

token = this.read();
}
}

这又允许我使用简单的 for-of 语法:

for (let token of parser.readBlock()) {
// block
// data
}

对于 C++,我想要类似的东西:

for (string token : reader.read_block())
{
// block
// data
}

我四处搜索,看看是否可以使用迭代器完成此操作,但我不知道是否可以使用这样一个没有定义开始或结束的惰性迭代器。也就是说,它的开头是读取器的当前位置(字符 vector 中的整数偏移量),它的结尾是找到标记 } 的时间。我不需要构造任意迭代器,也不需要反向迭代,也不需要查看两个迭代器是否相等,因为这纯粹是为了减少线性迭代的重复性。

目前每次要读取一个block,都需要重写如下:

stream.skip(); // {
while ((token = stream.read()) != "}")
{
// block
// data
}

这变得非常困惑,尤其是当我在 block 中有 block 时。为了支持嵌套block,迭代器必须全部引用同一个读取器的偏移量,这样内部 block 将推进偏移量,并且外部 block 将从该提前偏移量重新开始迭代(内部 block 完成后)。

这可以用 C++ 实现吗?

最佳答案

为了在 for-range 循环中可用,类必须具有返回迭代器的成员函数 begin() 和 end()。

什么是迭代器?满足一组要求的任何对象。有几种迭代器,具体取决于哪些操作允许您。我建议实现一个输入迭代器,这是最简单的:https://en.cppreference.com/w/cpp/named_req/InputIterator

class Stream
{
public:
std::string read() { /**/ }
bool valid() const { /* return true while more tokens are available */ }
};

class FileParser
{
std::string current_;
Stream* stream_;
public:
class iterator
{
FileParser* obj_;
public:
using value_type = std::string;
using reference = const std::string&;
using pointer = const std::string*;
using iterator_category = std::input_iterator_tag;
iterator(FileParser* obj=nullptr): obj_ {obj} {}
reference operator*() const { return obj_->current_; }
iterator& operator++() { increment(); return *this; }
iterator operator++(int) { increment(); return *this; }
bool operator==(iterator rhs) const { return obj_ == rhs.obj_; }
bool operator!=(iterator rhs) const { return !(rhs==*this); }
protected:
void increment()
{
obj_->next();
if (!obj_->valid())
obj_ = nullptr;
}
};


FileParser(Stream& stream): stream_ {&stream} {};
iterator begin() { return iterator{this}; }
iterator end() { return iterator{}; }
void next() { current_ = stream_->read(); }
bool valid() const { return stream_->valid(); }
};

因此您的文件末尾迭代器由指向任何对象的迭代器表示。

然后你可以像这样使用它:

int main()
{
Stream s; // Initialize it as needed
FileParser parser {s};
for (const std::string& token: parser)
{
std::cout << token << std::endl;
}
}

关于C++ 自定义惰性迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56517753/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com