Home > Blockchain >  Vector erase but I had vector subscript out of range error
Vector erase but I had vector subscript out of range error

Time:11-05

I want to erase radius < 20, but I received vector subscript out of range error.

for (int i = 0; i < ball.size() ; i  )
    for (int j = i   1; j < ball.size(); j  )
    {
        
        int a = ball[i].x - ball[j].x;
        int b = ball[i].y - ball[j].y;
        if (sqrt(a * a   b * b) <= ballr[i] ballr[j])
        {
            wx[i] = -wx[i];
            wx[j] = -wx[j];
            wy[i] = -wy[i];
            wy[j] = -wy[j];
            ballr[i] =ballr[i]- ballr[i] * 0.1;
            ballr[j] =ballr[j]- ballr[j] * 0.1;
        }
    }
for (int i = ball.size() - 1; i >= 0; i--)
{
    if (ballr[i] < 20)
    {
        ball.erase(ball.begin()   i);
    }
    else
    {
        i--;
    }
}

CodePudding user response:

for (int i = ball.size() - 1; i >= 0; i--)
{
    if (ballr[i] < 20)
    {
        ball.erase(ball.begin()   i);
    }
    else
    {
        i--;
    }
}

If, in some case, ballr[i] >= 20, then the else part got executed, and you decrement i. And, at the end of the for loop, you decrement i once again.

Instead, you want to increment i when you earse a value.

for (int i = ball.size() - 1; i >= 0; i--)
{
    if (ballr[i] < 20)
    {
        ball.erase(ball.begin()   i);
          i;
    }
}

CodePudding user response:

The out-of-range error is very likely with one of ballr, wx or wy vectors. Unfortunately, you did not provide the code that allocates them.

In any case, your code is fraught with errors. I presume you want to detect collisions between moving bubbles of various sizes.

You keep the information for each bubble in several arrays, I see ball[], wx[], wy[], ballr[]... These arrays have to be kept in sync at all times, especially when adding or erasing balls. In other words, this arrangement is like calling out for bugs to converge on your code :), as this is the case here.

Have you considered consolidating all information relating to a ball in one place? This is the basis of OOP, and it would make managing all of this information much easier.

Example:

struct ball
{
    double x;
    double y;
    double radius;
    double wx;
    double wy;  

    void reverseCourse()
    {
        wx = -wx;
        wy = -wy;
    }

    // a function to compute distance:
    friend double getDistance(const ball& a, const ball& b)
    {
        double dx = b.x - a.x;
        double dy = b/y - a.y;
        return sqrt((dx * dx)   (dy * dy)); 
    }

    friend bool collide(const ball& a, const ball& b)
    {
        return getDistance(a, b) <= (a.radius   b.radius);
    }

};

//...

std::vector<ball> balls;
//...


for (size_t i = 0; i < balls.size();   i)
{
    for (size_t j = i   1; j < balls.size();   j)
    {
        if (collide(balls[i], balls[j]))
        {
            balls[i].reverseCourse();  // this will probably not work as 
            balls[j].reverseCourse();  // you'd like, a bit of maths 
                                       // will be needed for a more 
                                       // realistic visual effect
            balls[i].radius *= .9;
            balls[j].radius *= .9;
        }
    }
}

// Since all information is kept in one single location, removing balls is a simple operation
// you could do it as you were attempting to do it before (minus the double decrement bug), 
// or using the std library.

// for c  11 and later:
balls.erase(std::remove_if(balls.begin(), balls.end(), 
                          [](const ball& b) { return (b.radius < 20); }),
            bakls.end());

// for c  98
struct local  // any dumb name will do
{
    static bool smallRadius(const ball& b) { return (b.radius < 20); };
};

balls.erase(std::remove_if(balls.begin(), balls.end(), local::smallRadius),
            balls.end());
  • Related