【发布时间】:2019-06-09 19:27:00
【问题描述】:
我有一个比较简单的文本文件解析器。我解析的文本被分割成由{ block data } 表示的块。
我的解析器有一个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
}
我四处搜索,看看是否可以使用迭代器来完成,但我不知道我是否可以拥有像这样没有定义开始或结束的惰性迭代器。也就是说,它的开始是阅读器的当前位置(字符向量中的整数偏移量),它的结束是找到标记} 的时间。
我不需要构造任意迭代器,或者反向迭代,或者查看两个迭代器是否相等,因为它纯粹是为了减少线性迭代的重复性。
目前每次想读一个block,都需要重写如下:
stream.skip(); // {
while ((token = stream.read()) != "}")
{
// block
// data
}
这变得非常混乱,尤其是当我在块内有块时。为了支持块内的块,迭代器必须都引用同一个读取器的偏移量,这样内部块将提前偏移量,而外部块将从该高级偏移量重新开始迭代(内部完成后)。
这可以在 C++ 中实现吗?
【问题讨论】:
-
是的,很有可能。您所需要的只是为您的文件解析器制作一个类似迭代器的包装器。
begin()、end()、operator++、operator*和operator==应该足够了。 -
如果我不知道什么时候到达终点,那将如何运作?
-
所有迭代不都是这样工作的吗?你循环直到你到达终点,然后你停下来。因此,当您的解析器到达 } 时,这将相当于
end()迭代器。