迭代一个STL容器,而不是从.begin()函数开始

iterate an STL container not from the .begin()ing and wrap around

本文关键字:begin 函数 开始 容器 一个 STL 迭代      更新时间:2023-10-16

我有一个std::向量,为了简单起见,我们说它是整数。

std::vector<int> ivec;
ivec.push_back(1);
ivec.push_back(2);
... //omitting some push back's 3 to 99
ivec.push_back(100);

标准的迭代方式是已知的

std::map<int>::iterator it;
for( it = ivec.begin(); it != ivec.end(); it++ ) 
  print();

该迭代将打印1,2,3,…100 .

我想从预定义的索引开始遍历所有向量元素,而不是从它开始。我想打印

3、4、5、6……99、100、1,2

你能在这里分享你的想法吗?

可以分两步完成

for( it = ivec.begin()+index; it != ivec.end(); it++ ) and then (if index !=0)
for ( it = ivec.begin; it = it = ivec.begin() + (index-1); it++)

您可以:

  • 开发一个迭代器类,包装vector::iterator并公开你喜欢的行为(特别是:++检查end()并将其替换为begin()并调整其他"border值")

  • 从3开始填充矢量,并在100处换行,这样标准迭代将看起来像你想要的。

选择取决于vector的其他用途以及需要迭代的其他内容。

假设您已经有了一个起始迭代器。如何实现这一点取决于您是使用可索引(vector)类型还是仅使用前向迭代器,还是使用键控类型。然后你可以像这样做一个循环:

type::iterator start_iter = /* something from collection, perhaps begin()+index */
type::iterator cur_iter = start_iter;
do
{
  //do something with cur_iter
  ++cur_iter;
  if( cur_iter == collection.end() )
    cur_iter = collection.begin();
} while( cur_iter != start_iter );

这是基本的循环

bool wrapped = false;
for (auto it = vec.begin() + index; (it != vec.begin() + index) || !wrapped; ++it)
{
    if (it == vec.end())
    {
        it = vec.begin();
        wrapped = true;
    }
    std::cout << *it;
}

我知道这是一个相当老的问题,但是没有人提到std::rotate,我认为,在某些情况下,它可能是适合这项工作的工具。

从http://www.cplusplus.com/reference/algorithm/rotate/:

修改的例子
#include <iostream>     // std::cout
#include <algorithm>    // std::rotate
#include <vector>       // std::vector
int main () {
  std::vector<int> myvector;
  // set some values:
  for (int i = 1; i < 10; ++i) myvector.push_back(i); // 1, 2, 3, ... 9
  std::rotate(myvector.begin(), myvector.begin() + 2, myvector.end());
                                                  // 3, 4, 5, 6 ... 9, 1, 2
  // print out content:
  std::cout << "myvector contains:";
  for (auto it = myvector.begin(); it != myvector.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << 'n';
  return 0;
}

cpp.sh/3 rdru

输出:

myvector contains: 3 4 5 6 7 8 9 1 2

注意,因为my_vector是由std::rotate函数修改的,如果你只想迭代向量一次,这既不是很有效也不是很有用。

然而,虽然这可能不是这个问题的最佳答案,但我希望它仍然可以为有类似问题的人提供一些价值。

使用随机访问容器的解决方案非常简单,参见下面的代码。

std::vector<int> v ({1,3,4,5,6,7,8,9,10}); /* c++11 */
...
for (int i = 2; i < (10+2); ++i)
  std::cout << v[i % 10] << " ";

方法,当使用只有双向/正向迭代器的容器时:

  std::list<int> l ({1,3,4,5,6,7,8,9,10}); /* c++11 */
  Iter start = l.begin ();
  std::advance (start, 4);
  ...
  Iter it = start;
  do {
    std::cerr << *it << std::endl;
  } while (
    (it = ++it == l.end () ? l.begin () : it) != start
  );

有无数种方法可以做到这一点,并且可能所有方法(或多或少)都是相同的,因此最终取决于个人偏好和编码风格惯例。我可能会这样做:

std::cout << v[idx] << "n";
for( auto it = v.begin() + idx + 1; it != v.begin()+idx; ++it )
{
    if( it == v.end() ) it = v.begin();
    std::cout << *it << "n";
}