How to handle checked iterators? - c++

for debug mode in VS2013 I receive an out of range exception if I add a constant value to an iterator and this iterator will go out of range afterwards.
For example:
#include <cstdlib>
#include <vector>
int main(void) {
std::vector<unsigned char> data(10, 0);
auto it = data.begin();
while (it != data.end()) {
if ((it + 3) <= data.end()) {
it += 3;
}
else {
it = data.end();
}
}
return EXIT_SUCCESS;
}
In the fourth run of the while-loop the check it + 3 <= data.end() fails and the exception is thrown.
A short workaround for the VS compiler would be to insert #define _ITERATOR_DEBUG_LEVEL 0 that disables the option for checked iterators in debug mode.
But I would appreciate a better, common solution that will work for both, VS and GCC compiler!
I'm sure there already exists a way by the STL to handle iterator distances and checks like this :) but I don't know it yet...

The better common solution is the following
while ( std::distance( it, data.end() ) >= 3 )
{
// some code
std::advance( it, 3 );
// some code
}
Or
while ( it != data.end() )
{
// some code
std::advance( it, std::min<int>( 3, std::distance( it, data.end() ) ) );
// some code
}
The choice between these two variants depends on whether you want to process the iterator at least one time even if data.end() - it is less than 3.
If a non-random access iterator is used then the loop can look as
while ( it != data.end() )
{
// some code
( ++it != data.end() ) && ( ++it != data.end() ) && ( ++it != data.end() );
// some code
}

That's because end() points to the element beyond the last actual element of the vector. So your condition if ((it + 3) <= data.end()) will eventually evaluate to end() + 1 (when it already equals end()), which is invalid. To fix it, change it to if ((it + 3) < data.end()).
To reiterate: the last available element of a vector, or any other STL container, is located at end() - 1. If the container is empty, begin() is the same as end(). It is always an error to dereference an iterator pointing to end().

Related

Can you use advance() in a string::iterator in C++?

for( string::iterator it = line.begin(); it != line.end(); it++ )
{
advance( it, 1 );
}
I get a segmentation fault. I'm trying to get the next value in the iterator so that I can compare it to a hexadecimal.
You sure can use advance there, but beware:
Unless you break the loop before you get too near to the end, or the length of the string is even, you will have a buffer-overrun and UB.
for( string::iterator it = line.begin(); it != line.end(); it++ )
{
advance( it, 1 );
}
Is equivalent too:
for(auto it = line.begin(); it != line.end(); it += 2 )
{}
Because advance(it, 1); is equivalent to ++i;.
See here: http://en.cppreference.com/w/cpp/iterator/advance
If you only want the next value, check for its existence with it+1 != line.end() and get it with it[1].
It looks like you may want to change it++ to ++it. I referenced this example case here http://www.cplusplus.com/reference/string/string/begin/. I think that will advance the iterator for you, so I don't think you'll need both that and advance. Try something like
this,
string::iterator it = line.begin();
while(it != line.end()){
//Do something with the iterator
advance( it, 1 );
}
This is another reference that I found useful. http://www.cplusplus.com/reference/iterator/advance/

Best way to further split some elements in vector

Here is a sample vector
vector<string> v;
v.push_back("one");
v.push_back("two");
v.push_back("three four");
v.push_back("five");
// print
one
two
three four
five
i need to split the element number 3 so now the vector look (without creating another vector)
// print
one
two
three
four
five
Should i use iterator or simple loop? it should have good performance too.
As has been pointed out in the comments, if you're inserting
elements into the vector (which you will be), you have to avoid
using an invalidated iterator. Still, something along the lines
of the following should work:
std::vector<std::string> iter = v.begin();
while ( iter != v.end() ) {
std::string::iterator breakpoint = std::find( iter->begin(), iter->end(), ' ' );
if ( breakpoint == iter->end() ) {
++ iter;
} else {
std::string next( breakpoint + 1, iter->end() );
iter->erase( breakpoint, iter->end() );
iter = v.insert( iter + 1, next );
}
}
In such cases, I generally prefer generating into a copy,
however.

Increment an iterator c++

My problem is as follows: I use an iterator, and I want to compare each element to the next element. Prototype looks like below, how can I increase the iterator to be able to compare?
Also, how can I set a proper condition for this to happen? I mean how to point on the last element, not on the next after the last like with end() function:
std::vector<T>::const_iterator it;
std::vector<T>::const_iterator it2;
for (it = set.begin(), it != set.end(); it++)
{
// some things happen
if ( final == it )
{
if ( it != set.end()-1 ) // how to write properly condition?
{
it2 = it + 1; //how to assign the next here?
if (...)//some condition
{
if ( it->func1() - it2->func1()) < 20 ) //actual comparison of two consecutive element values
// do something
}
}
}
}
In C++11 use the functions std::next() and std::prev().
Your code could become:
// before
it != std::set.end()-1
// after
it != std::prev(set.end())
and
// before
it2 = it + 1;
// after
it2 = std::next(it);
That is true also for non-vector containers, such as map,set or others.
NOTE: after std::next(it), "it" iterator remains unmodified!
NOTE 2: Use it2 = std::next(it,n); to increment as much as you need.
You can use adjacent_find to solve that. You should use the second form of that function (with predicate) and pass to the predicate your some things happen and some condition in c-tor
auto found = std::adjacent_find( set.begin(), set.end(),
[some_comdition]( const T & left, const T & right ) {
if ( some_comdition ) {
if ( left.func1() - right.func1() < 20 ) {
do_smth();
// return true; if there's no need to continue
}
}
return false;
}
);
Based on the fact that it++ is acceptable, we should define a new iterator called itplusone, which is initialized as itplusone = ++it. In this way, you can safely use the meaning of an iterator pointing to the next item of it. Also clearly, the range of iterator of itplusone bounded by terms itplusone != set.end(). I use this method to compute the total weight of a path, which is defined as a list object.
In the for loop, you use it++ which means it = it + 1, which is perfectly ok. So this one will be fine also it2 = it + 1. it2 will be pointing to the next value.
In the for loop again, you use it != set.end(), which is again perfectly ok. So you can also it + 1 < set.end(), just like you did in your code.
I don't see anything wrong in your code, just wanted to explain.
somewhat late, just discovered it, but like mentioned above, ++ iterator works fine.
vector<string> P
auto itA = begin(P);
while(itA != end(P))
{
if(itA != end(P))
{
++itA; //
}
}

Half edge twins

I have implemented a Half-edge data structure for loading 3d objects. I find that the part of assigning twin/pair edges takes the longest computation time (especially for objects which have hundreds of thousands half edges). The reason is that I use nested loops to accomplish this. Is there a simpler and efficient way of doing this?
Below is the code which I've written. HE is the half-edge data structure. hearr is a vector containing all the half edges. vert is the starting vertex and end is the ending vertex. Thanks!!
HE *e1,*e2;
for(size_t i=0;i<hearr.size();i++){
e1=hearr[i];
for(size_t j=1;j<hearr.size();j++){
e2=hearr[j];
if((e1->vert==e2->end)&&(e2->vert==e1->end)){
e1->twin=e2;
e2->twin=e1;
}
}
}
I used some simple keywords like break and continue, and also set the value of j in the inner loop as j=i. This improved the speed significantly. Earlier it took my 403 seconds for a set of data. Now its 11 seconds. These are the changes. Any comments are welcome. Thanks!
for(size_t i=0;i<hearr.size();i++){
e1=hearr[i];
if(e1->twin!=0)
continue;
for(size_t j=i;j<hearr.size();j++){
e2=hearr[j];
if(e2->twin!=0)
continue;
if((e1->vert==e2->end)&&(e2->vert==e1->end)){
e1->twin=e2;
e2->twin=e1;
break;
}
}
}
Here is a solution. I haven't compiled it.
The basic idea is to sort the range by (vert then end) and by (end then vert). Each of these takes nlgn time.
We then walk both lists in parallel looking for ranges where the vert-major sorted list's end equals the end-major sorted list's end.
One we have these ranges, we call DoTwins. This walks the ranges in question, looking for where the vert-major list's end matches the end-major list's vert. I then check if there are multiple edges that are exactly equivalent (if there are, things go poorly, so I assert), then hook up the twins.
Each iteration of each loop (inner or outer) advances where we are analyzing in a list by 1, and each outer loop never looks back. So this is O(n).
Note that the DoTwins loop and the loop that calls DoTwins follow basically the same logic with slightly different tests. Refactoring that logic might improve the code.
Disclaimer: Code has not been compiled (or run, or debugged), just written from scratch, so expect there to be typos and errors. But the basic idea should be sound.
// A procedure to solve a subproblem -- the actual assignment of the
// twin variables. The left range's "vert" field should equal the
// right range's "end" field before you call this function. It proceeds
// to find the subsets where the left "end" equals the right "vert",
// and sets their twin field to point to each other. Note that things
// go squirrly if there are multiple identical edges.
template< typename HEPtrRange >
void DoTwins( HEPtrRange EqualVertRange, HEPtrRange EqualEndRange )
{
auto it1 = EqualVertRange.first;
auto it2 = EqualEndRange.first;
while( it1 != EqualVertRange.second && it2 != EqualEndRange.second )
{
Assert((*it1)->vert == (*it2)->end);
if ((*it1)->end > (*it2)->vert)
{
++(*it2);
continue;
}
if ((*it1)->end < (*it2)->vert)
{
++(*it1);
continue;
}
Assert((*it1)->end == (*it2)->vert);
// sanity check for multiple identical edges!
auto it3 = it1;
while (it3 != EqualVertRange.second && (*it3)->end == (*it1)->end)
++it3;
auto it4 = it2;
while (it4 != EqualVertRange.second && (*it4)->end == (*it2)->end)
++it4;
// the range [it1, it3) should have its twin set to the elements
// in the range [it2, it4). This is impossible unless they
// are both of size one:
Assert( it3 - it1 == 1 );
Assert( it4 - it2 == 1 );
for (auto it = it1; it != it3; ++it)
(*it)->twin = it2;
for (auto it = it2; it != it4; ++it)
(*it)->twin = it1;
it1 = it3;
it2 = it4;
}
}
Elsewhere:
// A vector of the edges sorted first by vert, then by end:
std::vector<HE*> vertSorted(&hearr[0], (&hearr[0]).size());
std::sort(vertSorted.begin(), vertSorted.end(),
[](HE* e1, HE* e2)
{
if (e1->vert != e2->vert)
return e1->vert < e2->vert;
return e1->end < e2->end;
}
);
// A vector of the edges sorted first by end, then by vert:
std::vector<HE*> endSorted = vertSorted;
std::sort(endSorted.begin(), endSorted.end(),
[](HE* e1, HE* e2)
{
if (e1->end != e2->end)
return e1->end < e2->end;
return e1->vert < e2->vert;
}
);
// iterate over both at the same time:
auto it1 = vertSorted.begin();
auto it2 = endSorted.begin();
while(it1 != vertSorted.end() && it2 != endSorted.end())
{
// we are looking for cases where left->vert == right->end.
// advance the one that is "lagging behind":
if ((*it1)->vert > (*it2)->end)
{
++it2;
continue;
}
if ((*it1)->vert < (*it2)->end)
{
++it1;
continue;
}
Assert( (*it1)->vert == (*it2)->end );
// Find the end of the range where left->vert == right->end
auto it3 = it1;
while (it3 != vertSorted.end() && (*it3)->vert == (*it1)->vert)
{
++it3;
}
auto it4 = it2;
while (it4 != endSorted.end() && (*it4)->vert == (*it2)->vert)
{
++it4;
}
auto EqualVertRange = std::make_pair(it1, it3);
auto EqualEndRange = std::make_pair(it2, it4);
// Delegate reverse lookups and assignment of twin variable to a subprocedure:
DoTwins( EqualVertRange, EqualEndRange );
it1 = it3;
it2 = it4;
}
A better solution would be to sort the array, then perform a binary search providing your own comparison. Or consider hashing each node, then performing a lookup while providing a custom comparison

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

I have a situation where I'm marching through a vector, doing things:
std::vector<T>::iterator iter = my_list.begin();
for ( ; iter != my_list.end(); ++iter )
{
if ( iter->doStuff() ) // returns true if successful, false o/w
{
// Keep going...
}
else
{
for ( ; iter != m_list.begin(); --iter ) // ...This won't work...
{
iter->undoStuff();
}
}
}
Under normal conditions - assuming everything goes well - I march all the way to my_list.end() and end the loop successfully.
However, if something goes wrong while I'm doing stuff, I want to be able to undo everything - basically retrace my steps back to the very beginning of the vector, undoing everything one at a time in reverse order.
My problem is that when I get to my_list.begin() - as shown in the nested for loop - I'm really not done yet because I still need to call undoStuff() on my first element in the list. Now, I could just make the final call outside of the loop, but this seems a little unclean.
The way I see it, I'm only done when I get to my_list.rend(). However, I can't compare a std::vector::iterator to a std::vector::reverse_iterator.
Given what I'm trying to do, what's the best choice of iterator-type / loop combination?
I'm a little rusty when it comes to STL vectors, but would it be possible to create a std::vector::reverse_iterator from your initial iterator? Then you would only need to start at the last item you were at when going forward, and would be able to compare it to my_list.rend() to make sure that the first item is processed.
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();
}
There is of course no reason not to use the vectors operator[]() if that makes your code clearer, simpler and/or more efficient.
It depends on what your doStuff() function does, and how important performance is in your context. If possible, it would probably be clearer (ie - easier for the reader) to work on a copy of your vector, and only if everything is okay, swap the vectors.
std::vector<Foo> workingCopy;
workingCopy.assign(myVector.begin(), myVector.end());
bool success = true;
auto iter = workingCopy.begin();
for( ; iter != workingCopy.end() && success == true; ++iter )
success = iter->doStuff();
if( success )
myVector.swap(workingCopy);
Without using a reverse_iterator, you can walk backwards this way:
while(iter-- != m_list.begin())
{
iter->undoStuff();
}
Though this creates a copy of iter, the cost shouldn't be too great. You can refactor for better speed:
while(iter != m_list.begin())
{
--iter;
iter->undoStuff();
}
You need to use rbegin() to get a reversible iterator.
Personally I still prefer
for (int i=0;i<vecter.size();i++) { }
Ok, I'll go out on a limb here..
std::vector iterator iter = my_list.begin();
bool error = false;
while(iter != my_list.end())
{
error = !iter->doStuff();
if(error)
break
else
iter++;
}
if(error)
do
{
iter->undoStuff();
iter--;
}
while(iter != my_list.begin())
This is what I call over engineering, but it is so much fun
// This also can be done with adaptators I think
// Run DoStuff until it failed or the container is empty
template <typename Iterator>
Iterator DoMuchStuff(Iterator begin, Iterator end) {
Iterator it = begin;
for(; it != end; ++it) {
if(!*it->DoStuff()) {
return it;
}
}
return it;
}
// This can be replaced by adaptators
template <typename Iterator>
void UndoMuchStuff(Iterator begin, Iterator end) {
for(Iterator it = begin; it != end; ++it) {
it->UndoStuff();
}
}
// Now it is so much easier to read what we really want to do
typedef std::vector<MyObject*> MyList;
typedef MyList::iterator Iterator;
typedef MyList::reverse_iterator ReverseIterator;
Iterator it = DoMuchStuff(my_list.begin(), my_list.end());
if(it != my_list.end()) {
// we need to unprocess [begin,it], ie including it
UndoMuchStuff(ReverseIterator(1+it), ReverseIterator(my_list.begin()));
}
This can be done with a reverse_iterator:
bool shouldUndo(false);
std::vector::iterator iter(my_list.begin()), end(my_list.end());
for ( ; iter != end && !shouldUndo; ++iter )
{
shouldUndo = iter->doStuff(); // returns true if successful, false o/w
}
if (shouldUndo) {
reverse_iterator<std::vector::iterator> riter(iter), rend(my_list.rend());
//Does not call `undoStuff` on the object that failed to `doStuff`
for ( ; riter != rend; ++riter )
{
iter->undoStuff();
}
}