Reputation: 6758
I have an std::vector, let's say of integers for simplicity.
std::vector<int> ivec;
ivec.push_back(1);
ivec.push_back(2);
... //omitting some push back's 3 to 99
ivec.push_back(100);
The standard way to iterate is known
std::map<int>::iterator it;
for( it = ivec.begin(); it != ivec.end(); it++ )
print();
That iteration will print 1,2,3, ... 100.
I want to traverse all vector elements starting from a predefined index and not from it.begin(). I would like to print
3,4,5,6 ... 99, 100, 1, 2
Can you share your thoughts here?
It might ok to do it in two steps
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++)
Upvotes: 10
Views: 6081
Reputation: 8071
I know this is a pretty old question, but nobody mentioned std::rotate
, which I think, in some cases, can be the right tool for the job.
Modified example from 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;
}
Output:
myvector contains: 3 4 5 6 7 8 9 1 2
Note, since my_vector
is modified by the std::rotate
function, this is neither very efficient nor useful if you just want to iterate the vector once.
However, while this is probably not the best answer to this SO question, I hope it can still provide some value for people with similar issues.
Upvotes: 3
Reputation: 55395
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;
}
Upvotes: 3
Reputation: 31861
I'll assume that you already have a starting iterator. How you get this depends on whether you are using an indexable (vector) type or a forward iterator only, or a keyed type. Then you can do a loop something like this:
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 );
That's the basic loop.
Upvotes: 4
Reputation: 63797
A solution when using a random-access container is very simple, see the code below.
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] << " ";
Method when using containers only having bidirectional/forward iterators:
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
);
Upvotes: 2
Reputation: 16046
There are endless ways to do it, and probably all are (more or less) equivalent, so in the end it depends on personal preference and maybe coding style conventions. I would probably do it like:
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";
}
Upvotes: 0
Reputation: 20730
You can either:
develop an iterator class that wraps the vector::iterator and expose the behaviour you like (in particular: ++ checks for end() and replace it with begin() and adjust the other "border values")
fill the vector starting from 3 and wrap at 100, so that standard iteration will look as you want.
The choice depends on what else the vector is purposed and what else that iteration is needed.
Upvotes: 7