-1
void foodAgainstCreatures(vector<creature>& displayCreatures, vector<Food>& displayFood)
{
bool hungry = true;
int differenceInX = 0;
int differenceInY = 0;
for (unsigned int j = 0; j < displayCreatures.size(); j++)
{
    hungry = true;
    for (unsigned int i = 0; i < displayFood.size(); i++)
    {
        differenceInX = displayCreatures[j].getXValue() - displayFood[i].getXValue();
        differenceInY = displayCreatures[j].getYValue() - displayFood[i].getYValue();
        if ((differenceInX <= 5 && differenceInX >= -5) && (differenceInY <= 5 && differenceInY >= -5))
        {
            displayCreatures[j].addToEnergy(3);
            displayFood.erase(displayFood.begin() + i);
            hungry = false;

        }
        else
        {
            if (displayCreatures[j].getEnergy() == 0)
            {
                displayCreatures.erase(displayCreatures.begin() + j);
            }
        }

    }
    if (hungry == true)
    {
        displayCreatures[j].addToEnergy(-1);
    }
}
}

//once a "creature" "eats" a "food" it gains "energy" which works fine what i need help with is then removing that "food" that has been "eaten" from the vector. can i do this within the loop or not?

KPullet
  • 21
  • 3
  • 3
    be an angel and use std::size_t rather than unsigned int as your loop counter. – Bathsheba Mar 03 '16 at 15:25
  • haha I will do thank you – KPullet Mar 03 '16 at 15:28
  • Your problem description is lacking. Anyhow, it's sometimes easier to copy the elements you want to keep to a new vector and swap that with the previous one. If you don't consider that removing an element will shift the other elements and what implications that has for your loop. Also, please check the list of related questions on the right, yours isn't new at all. – Ulrich Eckhardt Mar 03 '16 at 15:28
  • I understand the implications of what will happen with the loop that is why I am asking. But anyhow thank you for your input as I can now see a solution. – KPullet Mar 03 '16 at 15:32

3 Answers3

0

You have a couple of options.
1. Iterate vector in reverse order, this way deletion won't affect elements you're about to visit.
2. Use more appropriate collection, like list.
3. If order is not important, you can use "fast delete", just replace the current item with the last one, decrease current index and vector size.

Sergi0
  • 1,084
  • 14
  • 28
0

Yes, you can remove items within a loop. Since you are using indices to access the items, you have to ensure that the indices are valid.

std::vector<int> container = {...};
for (std::size_t i = 0; i < container.size(); ++i) {
    if (shouldRemove(container[i]) {
        container.erase(container.begin() + i);
        --i; // We don't want to miss the next item
        continue;
    }
}

But sometimes you may want to use iterators. When you are using range-based for loops, you are using iterators as well. Something like this would not be valid:

std::vector<mystruct_t> container = {...};
for (mystruct_t &item : container) {
    if (item.please_remove_an_item) {
        container.erase(container.begin() + item.the_item_to_be_removed);
    }
}

What you can do while using iterators depends on the type of the container. You can find some rules about it here. While using std::vector, it is not allowed to use the iterators after removing an entry. Since erease returns the iterator to the next elelemt, it is possible to do something like this:

auto it = container.begin();
while (it != container.end()) {
    if (shouldRemove(*it)) {
        it = container.erase(it)
        continue;
    }
    ++it;
}
Community
  • 1
  • 1
JojOatXGME
  • 3,023
  • 2
  • 25
  • 41
0

You should not iterate by index and remove by the same time. The correct way is to erase by iterator. Depending on surrounding code, you can smth like the following:

for (auto it = displayCreatures.begin(); it != displayCreatures.end(); ) {

    if (need_to_erase(it)) {
        it = container.erase(it)
        continue;
    }

    ...
    ++it;
}

upd: I edited, because of typo in code -- .erase moves iterator (that's the whole idea), in this case ++it is not needed

rezdm
  • 165
  • 1
  • 11
  • You would skip an entry after removing another with this code. If you remove item *0*, you will never look at item *1*, which is on position *0* now. – JojOatXGME Mar 03 '16 at 16:33
  • that won't work, you need to erase an item OR to increment the iterator, cause erase returns next valid iterator. – Sergi0 Mar 03 '16 at 19:27
  • Ouch, yes, true. Sorry. was writing without double-check. Indeed if .erase, no need in ++it. – rezdm Mar 04 '16 at 10:40