How to Navigate Through a Vector Using Iterators? (C++)

How to navigate through a vector using iterators? (C++)

You need to make use of the begin and end method of the vector class, which return the iterator referring to the first and the last element respectively.

using namespace std;  

vector<string> myvector; // a vector of stings.

// push some strings in the vector.
myvector.push_back("a");
myvector.push_back("b");
myvector.push_back("c");
myvector.push_back("d");

vector<string>::iterator it; // declare an iterator to a vector of strings
int n = 3; // nth element to be found.
int i = 0; // counter.

// now start at from the beginning
// and keep iterating over the element till you find
// nth element...or reach the end of vector.
for(it = myvector.begin(); it != myvector.end(); it++,i++ ) {
// found nth element..print and break.
if(i == n) {
cout<< *it << endl; // prints d.
break;
}
}

// other easier ways of doing the same.
// using operator[]
cout<<myvector[n]<<endl; // prints d.

// using the at method
cout << myvector.at(n) << endl; // prints d.

Iterate through a C++ Vector using a 'for' loop

Is there any reason I don't see this in C++? Is it bad practice?

No. It is not a bad practice, but the following approach renders your code certain flexibility.

Usually, pre-C++11 the code for iterating over container elements uses iterators, something like:

std::vector<int>::iterator it = vector.begin();

This is because it makes the code more flexible.

All standard library containers support and provide iterators. If at a later point of development you need to switch to another container, then this code does not need to be changed.

Note: Writing code which works with every possible standard library container is not as easy as it might seem to be.

How to navigate through a list using iterators? (C++)

A list has a bidirectional iterator only (You can only increment or decrement the iterator via ++ or --). To advance the iterator by three you could std::advance(it, 3), but that might pass the end and lead to an infinite loop / undefined behavior.

Hence:

#include <iostream>
#include <list>

int main()
{
std::list<int> foo;
for (int i = 0; i < 20; i++) {
foo.push_back(i);
}
std::list<int>::iterator it = foo.begin();
while(it != foo.end()) {
std::cout << *it << ' ';
// Advance by three, stop at end
for(int i = 0; i < 3 && it != foo.end(); ++i, ++it);
}
return 0;
}

Note: You might choose a different container supporting random access (std::array, std::vector, std::deque) instead.

Iterating C++ vector from the end to the beginning

One way is:

for (vector<my_class>::reverse_iterator i = my_vector.rbegin(); 
i != my_vector.rend(); ++i ) {
}

rbegin()/rend() were especially designed for that purpose. (And yes, incrementing a reverse_interator moves it backward.)

Now, in theory, your method (using begin()/end() & --i) would work, std::vector's iterator being bidirectional, but remember, end() isn't the last element — it's one beyond the last element, so you'd have to decrement first, and you are done when you reach begin() — but you still have to do your processing.

vector<my_class>::iterator i = my_vector.end();
while (i != my_vector.begin())
{
--i;
/*do stuff */

}

UPDATE: I was apparently too aggressive in re-writing the for() loop into a while() loop. (The important part is that the --i is at the beginning.)

What's the cleanest way to walk and unwalk a std::vector using iterators?

While using reverse iterators via rbegin() and rend() works nicely, unfortunately I find that converting between reverse and non-reverse iterarotrs tends to be quite confusing. I can never remember without having to go through a logic-puzzle exercise whether I need to increment or decrement before or after the conversion. As a result I generally avoid the conversion.

Here's the way I'd probably code your error handling loop. Note that I'd think that you wouldn't have to call undoStuff() for the iterator that failed - after all, doStuff() said it didn't succeed.

// handle the situation where `doStuff() failed...

// presumably you don't need to `undoStuff()` for the iterator that failed
// if you do, I'd just add it right here before the loop:
//
// iter->undoStuff();

while (iter != m_list.begin()) {
--iter;
iter->undoStuff();
}

What's faster, iterating an STL vector with vector::iterator or with at()?

Why not write a test and find out?

Edit: My bad - I thought I was timing the optimised version but wasn't. On my machine, compiled with g++ -O2, the iterator version is slightly slower than the operator[] version, but probably not significantly so.

#include <vector>
#include <iostream>
#include <ctime>
using namespace std;

int main() {
const int BIG = 20000000;
vector <int> v;
for ( int i = 0; i < BIG; i++ ) {
v.push_back( i );
}

int now = time(0);
cout << "start" << endl;
int n = 0;
for(vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
n += *it;
}

cout << time(0) - now << endl;
now = time(0);
for(size_t i = 0; i < v.size(); ++i) {
n += v[i];
}
cout << time(0) - now << endl;

return n != 0;
}

How (is it possible) to access class members using iterators in C++?

cout << this->customClassCustomVectorArray[*it]->getCustomMember() << endl;

That is not right. [] expects a numeric index into the vector, but *it is not a numeric index. It is an iterator. It already points to the correct position in the vector.

cout << (*it)->getCustomMember() << endl;

[] is only for when you are iterating using numeric indices, not iterators.

how to get iterator to a particular position of a vector

Just add 10 to the iterator. They are intended to "feel" like pointers.

iterator for 2d vector

Although your question is not very clear, I'm going to assume you mean a 2D vector to mean a vector of vectors:

vector< vector<int> > vvi;

Then you need to use two iterators to traverse it, the first the iterator of the "rows", the second the iterators of the "columns" in that "row":

//assuming you have a "2D" vector vvi (vector of vector of int's)
vector< vector<int> >::iterator row;
vector<int>::iterator col;
for (row = vvi.begin(); row != vvi.end(); row++) {
for (col = row->begin(); col != row->end(); col++) {
// do stuff ...
}
}


Related Topics



Leave a reply



Submit