JRR
JRR

Reputation: 6152

check if second to last in an iterator

Is there a clean way to check if I am currently at the second to last element in an iteration in C++? As in:

for (vector::iterator it = v.begin(); it < v.end(); ++it)
{
   if (it points to second to last element)
      cout << "at second to last";
}

Upvotes: 3

Views: 3523

Answers (4)

vsoftco
vsoftco

Reputation: 56547

A solution below:

auto pos = std::next(std::begin(v), std::distance(std::begin(v), std::end(v))-2);
for (auto it = std::begin(v); it != std::end(v); ++it)
{
   if (it == pos)
      cout << "at second to last: " << *pos;
}

pos is now an iterator pointing to the second to last position, and the functions std::next and std::distance use the best implementation possible (i.e. constant complexity for random iterators, linear complexity for bidirectional/forward iterators).

Upvotes: 1

John Zwinck
John Zwinck

Reputation: 249133

The easiest way would be to compare your iterator against one which does indeed point to the second-to-last. And an easy way to get that is:

vector::iterator secondLast = v.end() - 2;

Assuming of course that v.size() >= 2. But the above doesn't generalize to other container types, for which you could do this:

vector::iterator secondLast = (++v.rbegin()).base();

This should rewind from the last element one step, then convert to a regular (forward) iterator. This will work with other container types like lists.

Or perhaps clearer for the general solution:

vector::iterator secondLast = v.end();
std::advance(secondLast, -2);

Again this requires size of 2 and iterators of random access or bidirectional type.

And finally, a C++11 solution:

auto secondLast = std::prev(v.end(), 2);

Upvotes: 6

perreal
perreal

Reputation: 97938

You can do this with some containers:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec {1, 2, 3, 4, 5}; 
    for (auto it = vec.begin(); it != vec.end(); it++) {
        if (vec.end() - it == 3) {
            std::cout << *it << std::endl;
        }
    }   
    return 0;
}

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 595827

Try something like this:

vector::iterator end = v.end(), stl;
bool has_stl = (v.size() >= 2);
if (has_stl) stl = end-2;

for (vector::iterator it = v.begin(); it < end; ++it)
{
   if ((has_stl) && (it == stl))
      cout << "at second to last";
}

Upvotes: 1

Related Questions