【问题标题】:Read And Write Iterators - C++读写迭代器 - C++
【发布时间】:2016-08-25 12:01:39
【问题描述】:

我是 C++ 新手(来自 C 和 Java),想编写一个简单的数独求解器作为练习。我正在考虑使用迭代器来迭代数独字段的行/列/块并阅读this c++Reference page

现在我有两个问题:

  • 对我来说似乎存在两种迭代器 Input-(read only)/Output(write only)-iterators 并且有不同的种类输入迭代器(Contiguous/RandomAccess/etc)。如果我想遍历数独字段,我希望能够读取 写入元素。我的迭代器应该扩展什么迭代器?

  • 我实际上认为我需要两个迭代器,一个迭代不同的行/列/块,另一个迭代这些行/列/块中的元素。在这里使用的通用命名约定是什么?我在考虑 RowIterator 迭代行和 RowElementIterator 迭代 RowIterator 指向的对象内包含的元素。

我也希望能在 C++ 迭代器中引入良好的资源。

【问题讨论】:

  • 这里给你一个很好的参考:en.cppreference.com/w/cpp/iterator
  • 迭代器是一个通用概念,用于访问容器中的元素。我怀疑迭代器是访问数独网格元素的自然方式。
  • 没有办法扩展迭代器(除了手动复制和添加行为)。您可以从迭代器继承,但这不一样并且有很多缺点。实际上没有理由继承任何东西。您只需从头开始编写一个迭代器。允许读取和写入的迭代器是常态,只有流需要技巧,例如只读或只写迭代器。也就是说,您可能只想使用简单的int 索引。
  • @NathanOliver 此页面包含在我的问题中...
  • @nwp 我想要一种方便的方法来遍历数独块,使用int 索引会变得非常丑陋。例如,当第一个数独块的索引为 { 0, 1, 2, 9, 10, 11, 18, 19, 20 }

标签: c++ c++11 iterator


【解决方案1】:

迭代器结构和你想象的不一样。 RandomAccess 迭代器可以同时输入和输出。即使是低级的 ForwardIterators 也能做到这一点。

另外,这些不是真正的基类。相反,它们是iterator categories。这意味着“InputIterator”类别完全包含“RandomAccess”类别。并非每个迭代器都允许写访问和/或随机访问,因此“OutputIterator”和“RandomAccess”类别是正交的。

在您的情况下,您所有的迭代器都可以是 RandomAccess;没有真正的理由限制它们。没有明显的命名约定,或名称的真正原因。既然我们有for (auto& row : board) { for (auto& cell : row) { ... } ... },你通常不会使用这些名字

【讨论】:

  • 感谢您的回答。因为我会有三个不同的迭代器,所以我的循环可能看起来像这样:for (auto& row : board.GetRows()) { ... }for (auto& row : board.GetColumns()) { ... }for (auto& row : board.GetBlocks()) { ... },对吧?
  • RandomAccess iterators are capable of both input and output. 这并不总是正确的。例如std::vector<int>::iterator是随机访问迭代器和输出迭代器,而std::vector<int>::const_iterator是随机访问迭代器而不是输出迭代器。
  • @cpplearner:正确、更新的答案使其更加明确。
【解决方案2】:

我可能错了,但我怀疑迭代器在解决数独问题上对你有多大帮助。

假设您将迭代器(行、列、块)编写为 RandomAccess 迭代器 - 以允许“按范围运算符寻址”而不仅仅是增量。作为“线性容器中的当前位置”的抽象替代品,简约有效的随机访问迭代器不会提供“原始索引”。 如果将迭代器的使用与位置索引的直接使用进行比较,这会有点令人反感:

“按行/列导航 迭代器” - 如果您通过逐行迭代然后通过 col-inside-the-row 到达某个位置,您将需要一个额外的步骤来获取“切换行但保留列”完成。 在代码中:

// go by row first, then by col inside the row
auto elemPos=board.row_iterator()[row].col_iterator()[col];
// now, keep the col, but switch the row
auto newPos=board.getColIterator(elemPos)[newRow];
//                ^ this is an extra operation 
//                  to perform the switch from row first
//                  to column first navigation

将上述内容与“按索引寻址”进行比较 - 您拥有行/列位置,可以根据需要随意增加/减少 两者中的任何一个

auto elem=board[row][col];
auto newElem=board[newRow][col];

是的,我明白了:用于学习目的的宠物项目很有价值,但是...我认为可能有很多其他领域,通过迭代器进行寻址比 2D 网格更有意义。

【讨论】:

    猜你喜欢
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多