反向迭代并比较std :: vector的两个连续元素(C ++)

时间:2020-05-10 16:54:17

标签: c++ vector iterator

我正在遍历定义圆(封闭形状)的点列表。对于每个点,我都在检查该点与下一个点之间的距离,并决定细分该距离是否大于4。

for (vector<Node>::reverse_iterator i = nodes.rbegin(); i != nodes.rend(); ++i) // going through list in reverse
{
    ofVec3f v1 = i->position;
    i += 1;
    ofVec3f v2 = i->position;
    i -= 1;

    float distance = v1.distance(v2);
    if (distance > 4) {
        interpolate(v1, v2);
    }
}

问题是,我想拥有它,以便上次迭代的i + 1元素是列表的第一个元素(因为它是闭合形状)。我以前在C#中有一个非常方便的函数,但由于迭代器的工作方式而无法使用。

int DiffLine::idxFix(int i) {
int c = nodes.size();
if (i < 0) { return c - 1; }
else { return i % c; }
}

在c ++中如何实现类似的目标?

2 个答案:

答案 0 :(得分:1)

选中i + 1。如果是rend(),请从v2获取rbegin()。您说您的结构是一个“列表”,但是您使用+=告诉我您具有随机访问迭代器,因此我在编写以下代码时假设您具有随机访问迭代器(例如nodesstd::vector)。如果不是这种情况(例如nodes实际上是std::list),则需要进行一些修改。

for (auto i = nodes.rbegin(); i != nodes.rend(); ++i) // going through list in reverse
{

    ofVec3f v1 = i->position;
    ofVec3f v2;
    auto j = i + 1;
    if (j == nodes.rend()) {
        v2 = nodes.rbegin()->position;
    }
    else
    {
        v2 = j->position;
    }

    float distance = v1.distance(v2);
    if (distance > 4) {
        interpolate(v1, v2);
    }
}

当然,您不必不必使用迭代器。如果这是一个随机访问迭代器(再次假设nodesstd::vector),则可以使用索引为循环的good-ol'

for (std::size_t i = nodes.size(); i != 0; --i)
{
    ofVec3f v1 = nodes[i % nodes.size()].position;
    ofVec3f v2 = nodes[i - 1].position;

    float distance = v1.distance(v2);
    if (distance > 4) {
        interpolate(v1, v2);
    }
}

请注意,以上代码将在第一次迭代时将FIRST元素与LAST元素进行比较。如果不可接受,那么我们可以进行一些更改。

答案 1 :(得分:0)

您可以为随机访问迭代器实现包装器,该包装器执行与c#方法类似的操作:

#include <vector>
#include <iostream>

template <typename RandomAccessIterator>
class LoopWrapper {
 public:
  LoopWrapper(const RandomAccessIterator& first,
              const RandomAccessIterator& last)
      : first_(first), dist_(last-first) {}
  typename RandomAccessIterator::value_type& operator*() {
    return *(first_ + pos_);
  }
  LoopWrapper& operator++() {
    pos_++;
    if (pos_ == dist_) {
      pos_ = 0;
      wrapped_ = true;
    }
    return *this;
  }
  LoopWrapper& operator--() {
    pos_--;
    if (pos_ < 0) pos_ = dist_ - 1;
    return *this;
  }
  LoopWrapper operator+(int offset) {
    LoopWrapper result = *this;
    result.pos_ += offset;
    result.pos_ %= dist_;
    if (result.pos_ < 0) result.pos_ += dist_;
    return result;
  }
  LoopWrapper operator-(int offset) {
    LoopWrapper result = *this;
    result.pos_ -= offset;
    result.pos_ %= dist_;
    if (result.pos_ < 0) result.pos_ += dist_;
    return result;
  }
  operator RandomAccessIterator() { return first_ + pos_; }
  bool Done() const { return wrapped_; }

 private:
  const RandomAccessIterator first_;
  const int dist_;
  int pos_ = 0;
  bool wrapped_ = false;
};

int main() {
  std::vector<int> v{1, 2, 3};
  for (auto i = LoopWrapper(v.begin(), v.end()); !i.Done(); ++i) {
    std::cout << *i << ", " << *(i + 1) << std::endl;
  }
  return 0;
}
相关问题