C++ - for(auto v: obj)

Hello!

Im just wondering, is it possible to do something like this:

for(auto v : obj)
{                     //Here is the question: v+1 
if(v == 'something' && v+1 == 'something')
{ 
do this
...
}

else{ ... }
}

I want to compare the next element to. Ive tried everything i could think of and i cant find anything help full on google…
Best regards!

PS ive tried stuff like:
auto temp = v + 1; if(temp == something)

if(v +1)
if (v[+1]

what you need to look for is iterating through a vector, with a range-based for loop. Should get you in the right direction.

1 Like

yea, i think youre right! Ended up with a raw pointer and that work out good. But now ive a logic bugg hehe
But the question remains, isnt there a way/syntax for this? For rangebased?

there should be

http://en.cppreference.com/w/cpp/language/range-for

The for loop does not have a this but as you iterate through a vector you can use a this IIRC

1 Like

If you are going to use pointers, don’t use raw pointers. Instead use smart pointers. They almost always are the better option and less prone to implementation errors.

This is true in general, but you definitely don’t want to use smart pointers when iterating over data structures. Smart pointers free the data once deleted (that’s their point after all), despite the data being owned by the container.

1 Like

And there is not wrong to use pointers(with my understading), especially when in my case its only for reads, no new no passing arround…?

Yeah it’s good. In arrays there’s not much difference between pointers and iterators anyway. Hence why iterators use the *syntax and pointers can be used as iterators.

@comfreak is right though, that in general you should use smart pointers whenever possible. In my programs virtually all data is held either by a std::unique_ptr or std::shared_ptr, with almost no manual new and delete being used.

What you wish to do using a range based for loop is going to be tricky as you either work on a copy of each value in the range, as in your example code (auto deduces types less reference, const and volatile), or a reference to each individual element. Neither of which is going to allow you to see the next item in the iteration. Also what happens on the last iteration when there is no next element in the range?

You might like to check out the intro reference material on cppreference.com on range based for loops:

http://en.cppreference.com/book/intro/range_for

I also located this blog post which has a nice section on the effects of the various forms of auto on the loop variable:

https://blog.petrzemek.net/2016/08/17/auto-type-deduction-in-range-based-for-loops/

If do wish to use a range based for then you would probably need to maintain a state variable to note when the previous item was a match and check this in addition to whether you have a match for the item values. For example:

#include <iostream>

int main()
{
    int obj[] = {1,2,3,4,5, 6, 7, 6,6 ,8,9, 6,6,6, 0};
    int something{6};
    bool have_prev_match{false};
    for ( auto v : obj )
    {
        if ( v == something )
        { 
            if ( have_prev_match )
            {
                std::cout << "Doing something!!\n";
            }
            have_prev_match = true;
        }
        else
        {
            have_prev_match = false;
        }
    }
}

Which was built using g++ 5.4.0:

g++ -std=c++14 -Wall -Wextra -pedantic -o main main.cpp

And when run should produce:

Doing something!!
Doing something!!
Doing something!!

Hope this is helpful

3 Likes

Yepp thanks for that, just realized my code is probably broken. Thanks! haha
Because i did this:

for(auto...){

char *nextElement = &v + 1;

[if-statement that use nextElement...]
if (*nextElement != ' ' && *nextElement != '\n' && *nextElement != '\0')

Maybe its possible to check that i dont use my pointer to point outside the range?

Best regards!
PS sorry for a late respons!

if (*nextElement != ' ' && *nextElement != '\n' && *nextElement != '\0')

should be OR

if (*nextElement != ' ' || *nextElement != '\n' || *nextElement != '\0')

because there’s no way nextElement can equal any of the three at the same time.

1 Like

Indeed you can obtain a pointer from the reference and use pointer arithmetic on it but if you have gone to all that trouble why not just use a good old for-loop, and stop one before the last element of the array, which sticking with pointers could look like so:

#include <iostream>
int main()
{
    int obj[] = {1,2,3,4,5, 6,6, 7,8,9, 6,6,6, 0};
    int something{6};
    auto obj_size = sizeof obj / sizeof(int);
    auto obj_begin = obj;
    auto obj_one_before_end = obj_begin + obj_size - 1;
    for ( auto pElement = obj_begin; pElement!=obj_one_before_end; ++pElement )
    {
        auto pnextElement = pElement + 1;
        if ( *pElement == something && *pnextElement == something )
        { 
            std::cout << "Doing something!!\n";
        }
    }
}

I have made the above a bit more verbose than it needs to be to try to be as clear as possible.

Or using array index values:

int main()
{
    int obj[] = {1,2,3,4,5, 6,6, 7,8,9, 6,6,6, 0};
    int something{6};
    auto obj_size = sizeof obj / sizeof(int);
    auto range_length = obj_size - 1u;
    for ( auto idx = 0u; idx != range_length; ++idx )
    {
        if ( obj[idx] == something && obj[idx+1] == something )
        { 
            std::cout << "Doing something!!\n";
        }
    }
}

As you can see in both these forms the end of the loop case causes no problems as we have stopped one before the last item in the array.

Hope this provides you with food for thought if nothing else.