Home > Enterprise >  Find element in a vector with previous and next element equal to 0
Find element in a vector with previous and next element equal to 0

Time:12-02

I want to go through a given vector of integers and find an integer which the value of the next and previous integer are 0.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> sample = { 0,3,0 };
    for (int i : sample)
    {
        if (sample[i - 1] == sample[i   1] == 0)
        {
            cout << "hello";
        }
    }
}

However, I keep getting a "vector subscript out of range" error. I think it's because when i is 0, sample[-1] doesn't exist, same with i = 2.

Is there an easy fix for it?

CodePudding user response:

This range based for loop

for (int i : sample)
{
    if (sample[i - 1] == sample[i   1] == 0)
    {
        cout << "hello";
    }
}

does not make a sense because there are used values of the vector as indices to the vector.

The range based for loop is not suitable for such a task.

You can use for example the standard algorithm std::adjacent_find.

Here is a demonstration program.

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

int main() 
{
    std::vector<int> v = { 0, 1, 0, 2, 0, 3, 0 };
    
    auto condition = []( const auto &a, const auto &b )
    {
        return a != 0 && b == 0;
    };
    
    if ( not v.empty() )
    {
        for ( auto current = std::next( std::begin( v ) ), last = std::end( v ); 
          ( current = std::adjacent_find( current, std::end( v ), condition ) ) != last;
          std::advance( current, 2 ) )
        {
            if ( *std::prev( current ) == 0 )
            {
                std::cout << *prev( current ) << ", " 
                          << *current << ", " 
                          << *std::next( current ) << '\n';
            }
        }
    }       
    
    return 0;
}

The program output is

0, 1, 0
0, 2, 0
0, 3, 0

CodePudding user response:

In a range-for loop, i is set to the value of each element in the array. It is NOT set to the index of each element, as you are currently assuming it does.

You need to use an indexed-based loop instead:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> sample = ...;
    if (sample.size() > 2)
    {
        for (size_t i = 1; i < sample.size()-1;   i)
        {
            if (sample[i-1] == 0 && sample[i 1] == 0)
            {
                cout << sample[i] << endl;
            }
        }
    }
}

Otherwise, use an iterator-based loop instead:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> sample = ...;
    if (sample.size() > 2)
    {
        for (auto iter = sample.begin() 1; iter != sample.end()-1;   iter)
        {
            if (*(iter-1) == 0 && *(iter 1) == 0)
            {
                cout << *iter << endl;
            }
        }
    }
}

CodePudding user response:

There's two problems that you run into here.

The first is that using the range-for loop notation, the variable i corresponds to the array values 0, 3, and 0. Not their indexes.

The second problem is that, if you iterate from index 0 to the end, you will be checking indexes -1 and 3, which are out of bounds of the vector.

Here is code that solves the problem in two ways, the first uses indexes and the second uses iterators. For the second one, you effectively treat p as a pointer to the current item in the list. I made the list a little longer to give more cases. It outputs that integers 2 and 5 are surrounded by zeros.

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> sample = { 0, 3, 6, 0, 2, 0, 5, 0 };
    for(int i = 1; i < sample.size() - 1; i  ){
        if(sample[i-1] == 0 && sample[i 1] == 0)
            cout << "integer " << sample[i] << " surrounded by 0\n";
    }

    for(std::vector<int>::iterator p = sample.begin()   1; p != sample.end() - 1; p  ){
        if(*(p-1) == 0 && *(p 1) == 0)
            cout << "integer " << *p << " surrounded by 0\n";
    }
}

For the second example, std::vector<int>::iterator is often changed to auto to be shorter.

  • Related