【问题标题】:2D iterator for loop循环的二维迭代器
【发布时间】:2019-04-23 11:00:24
【问题描述】:

我在实现与 .end() 相关的迭代器类时遇到问题。我遇到的问题是当我尝试在我的迭代器类中使用 for 循环时;它当前在 2D 向量中的最后一个元素之前停止。但是,我希望它在最后一个元素之后一个元素而不导致编译器错误,并在 print 语句中包含最后一个字符。

main.cpp

// file contents            
// aaa                          
// bbb                          
// cce 

// factory method (adds file contents to 2D <char> vector)
Base *a = Base::create("file");       
cout << *a; // overloaded '<<'

打印

a a a b b b c c e

现在,当我在迭代器类中使用 for 循环时,它不包含最后一个字符。

for(auto it = a->begin(); it != a->end(); it++) 
    cout << *it << ' ';

打印

a a a b b b c c

.end 打印以下内容

Base::iterator it = aa->end();
cout << *it << '\n';
// prints e

当我尝试 while 循环时,它包含最后一个字符。

// Note: my iterator class is a nested class inside Base class.

const Base::iterator et = a->begin(); 
int i = 0;
while(i < 13) {
    cout << *et << ' ';
    et++;
}

打印

a a a b b b c c e e e e e

我知道 a->end() 应该指向最后一个字符,但我不明白如何实现它。当我在 operator++(int) 中递增超过最后一个值时,它会显示分段错误。目前,我的重载增量方法在最后一个字符处停止并且不会超过它。话虽如此,我如何实现我的 ++(int) 方法以在从 for 循环打印时包含最后一个元素?我应该在向量中添加一个空元素或类似的东西吗?

Base.cpp 内部

// This function is whats causing the issue. I know it looks ugly.
Base::iterator Base::iterator::operator++(int) {

    // base is a Base *, x and y are coordinates for 2D vector
    Base::iterator temp(base, x, y); // save value 

    // if iterator has not reached end
    if( !((x == base->vec.size()-1) && (y == base->vec[0].size()-1)) )
    {
      // if y < row size
      if(y < base->vec[0].size()-1)
          y++;

      // if y has reached end of row, increment x and start y on a new row
      else if(x < base->vec.size() && y == base->vec[0].size()-1) {
          y=0;
          x++;
      }
    }
    return temp;
}

Base::iterator Base::begin() {
    return Base::iterator(this, 0, 0);
}

Base::iterator Base::end() {
    return Base::iterator(this, vec.size()-1, vec[0].size()-1);
}

Base.cpp 的其余部分

#include "Base.h"

using namespace std;

// Factory method (instantiates 2D vector with file contents)
Base *Base::create(string filename) {/*removed irrelevant code */}

Base::~Base(){}

// prints 2D vector
ostream &operator<<(ostream &os, const Base &val){/*removed irrelevant code*/}

Base::iterator::iterator(Base *b, int m, int n): base(b), x(m), y(n) {}
Base::iterator::~iterator(){}

// returns a character inside 2D vector
char &Base::iterator::operator*() const {
    return base->vec[x][y];
}  

bool Base::iterator::operator==(const Base::iterator& rhs) const {
    return base->vec[x][y] == *rhs;
}

bool Base::iterator::operator!=(const Base::iterator& rhs) const {
    return base->vec[x][y] != *rhs;
}

// Bunch of other functions

任何帮助将不胜感激。

【问题讨论】:

  • 如果您要包装 2D 向量,最好在底层实现中使用 1D 向量。
  • 是的,我想过,但这需要完全重做我所有的方法来处理一维向量并添加额外的类变量。最坏的情况,我可能最终会这样做。只是看看是否有任何二维迭代器的解决方案。

标签: c++ iterator


【解决方案1】:

Base::iterator(this, vec.size()-1, vec[0].size()-1); 这将返回一个有效的最后一个元素。因此,您需要将其更改为Base::iterator(this, vec.size(), 0);,并更新条件以切换到循环中的新行。

类似:

// if iterator has not reached end
if(x < base->vec.size())
{
  ++y;

  // if y has reached end of row, increment x and start y on a new row
  if(y >= base->vec[0].size() {
      y=0;
      ++x;
  }
}

迭代器也是错误的:

bool Base::iterator::operator==(const Base::iterator& rhs) const {
    return base == rhs.base && x == rhs.x && y == ris.y;
}

bool Base::iterator::operator!=(const Base::iterator& rhs) const {
    return !(base == rhs.base && x == rhs.x && y == ris.y);
}

【讨论】:

  • 如何解决分段错误?返回 Base::iterator(this, vec.size(), vec[0].size());显示分段错误。 (3, 3) 超出范围。二维向量只有索引 (0,0) -> (2,2)。
  • 糟糕,边界错误,x
  • 仍然给出分段错误。也许我必须对我的迭代器类构造函数做些什么?这就是它当前将其标记为分段错误的地方。这是说它不能将值 (3,0) 分配给 base*[x][y] ,因为它超出了范围。
  • 这可能与您的比较运算符有关。只需比较基数,x,y。您不能取消对 end 的引用,因为它始终是一个不存在的对象。
  • 比较基数、x 和 y,不要比较值本身,对于不同的迭代器,它们甚至可能相同。迭代器比较“指针”,而不是指向的值。
猜你喜欢
  • 1970-01-01
  • 2017-09-15
  • 2010-12-19
  • 2019-05-06
  • 2023-03-09
  • 2014-03-26
  • 1970-01-01
  • 2012-05-16
  • 1970-01-01
相关资源
最近更新 更多