juan
juan

Reputation: 17

how to end a loop at a particular time in unordered_multiset

Good morning,

I am trying for a loop when a particular condition is met in an unordered_multiset with the end operation. But it does not work and I get a Segmentation fault in the next iteration of the loop.

Code:

std::unordered_multiset<Element, ElementHash>::iterator itr;
Element elementTemp1("");
for (itr = almacen.begin(); itr != almacen.end(); ++itr) {
    Element tmp(*itr);
    if(tmp.getNombre() == "prueba"){
       itr = almacen.end();
    }
}

How can I solve it? Or maybe my structure is not the right one.

Upvotes: 1

Views: 114

Answers (2)

Torben Schramme
Torben Schramme

Reputation: 2140

What about this:

unordered_multiset<Element, ElementHash> :: iterator itr;
Element elementTemp1("");
for (itr = almacen.begin(); itr != almacen.end(); ++itr) {
Element tmp(*itr);
    if(tmp.getNombre == "prueba"){
       break;
    }
}

The break stops the execution of the for loop at that point. Is that what you want?

As mentioned by Sneftel in the comment: Your program crashes because a for-loop is executed in a way that after each iteration

  1. The increment/change operation gets executed (in your code: ++itr)
  2. The check is performed whether the loop is executed another time (in your code: itr != almacen.end()

But when you set the iterator within your loop already to almacen.end() you cannot increment it any further. But that is what happens after that iteration of the loop with Step 1 I described. And there your program crashes.

Upvotes: 2

Jarod42
Jarod42

Reputation: 218138

Your issue is that you increment end() afterward, the correct way would have been:

std::unordered_multiset<Element, ElementHash>::iterator itr;
Element elementTemp1("");
for (itr = almacen.begin(); itr != almacen.end(); /* Empty */) {
    Element tmp(*itr);
    if (tmp.getNombre() == "prueba"){
        itr = almacen.end();
    } else {
        ++itr;
    }
}

but break would be simpler, and you can also use for-range:

std::unordered_multiset<Element, ElementHash>::iterator itr;
Element elementTemp1("");
for (/*const*/auto& element : almacen) {
    if (element.getNombre() == "prueba"){
       break;
    }
}

but as-is, the loop is mostly useless.

So maybe you want to find the position where your predicate is true, then you might use std::find_if

auto itr = std::find_if(almacen.begin(), almacen.end(),
                        [](/*const*/auto& element){ return element.getNombre() == "prueba"; });
if (itr != almacen.end()) {
    /*const*/ auto& element = *itr;
    // ...
}

Upvotes: 2

Related Questions