Listenelement löschen



  • Hallo!

    Ich habe eine Liste die ich mithilfe einer for Schleife und einem Iterator durchgehe. Eine if Bedingung die sich im inneren der Schleife befindet entscheidet darüber ob das Element auf das der Iterator zeigt gelöscht wird oder nicht. Ich erhalte dann dauernd einen Fehler(wenn ein Element gelöscht wird) da ja der Iterator auf nichts mehr zeigt und dadurch meine Bedingung zum Abbruch der for SChleife nicht mehr überprüft werden kann. Ich habe versucht das ich nach dem löschen wieder auf den begin der Liste zeigen zu lasse, aber das bringt nichts.
    Hatt irgendjemand bitte eine Lösung für das Problem?

    for(iter=liste->begin();iter != liste->end();iter++){
    
    		if(iter > x){
    			liste->remove(iter);
    			iter=liste->begin();
    		}
        }
    

    Mfg

    Dosunmu



  • Du sagst es ja bereits, du möchtest das Objekt auf das der Iterator "zeigt" überprüfen also musst du auch das nette Sternchen vor iter setzten, also so: *iter. Im moment loescht du nämlich deinen Iterator und das es dann zu Zugriffsverletzungen kommt ist klar;)



  • Wenn du alle Elemente löschen willst, die größer als x sind geht doch auch das hier.

    liste->remove_if(bind2nd(greater<typ>(),(x)));
    

    Noch zur Erweiterung von dem was guennne sagte
    remove löscht die angegebenen Objekte (und zwar alle).
    erase löscht das Objekt auf welches der Iterator zeigt den du übergibst.



  • ich würde es mit erase löschen, remove sucht die liste nochmal durch...



  • Wenn du mit erase ein Element löschst bekommst do als Rückgabewert das nächste Element, also könnte man das z.B. so machen.

    iter = liste->begin();
    while(iter != liste->end()){         
      if(iter > x){ 
        iter = liste->erase(iter); 
      }else{
        iter++;
      } 
    }
    


  • besser...

    for ( iter = liste.begin(); iter != liste.end(); ++it )
      if ( (*iter) > x )
        liste.erase(iter);
    


  • turing_mob schrieb:

    besser...

    for ( iter = liste.begin(); iter != liste.end(); ++it )
      if ( (*iter) > x )
        liste.erase(iter);
    

    ⚠



  • was soll daran gefährlich sein? abgesehen davon, dass der iterator einmal falsch geschrieben ist?



  • Weil dein Iterator nach dem erase ungültig wird und so auch nicht mehr inkrementiert werden kann.
    So sollte es gehen.

    iter = liste.erase(iter);
    

    Was gefällt euch eigentlich an meiner Lösung oben nicht? 😞



  • Braunstein schrieb:

    Weil dein Iterator nach dem erase ungültig wird und so auch nicht mehr inkrementiert werden kann.
    So sollte es gehen.

    iter = liste.erase(iter);
    

    Schon besser 🙂 Aber da ist immer noch ein Fehler ...

    Braunstein schrieb:

    Was gefällt euch eigentlich an meiner Lösung oben nicht? 😞

    Die ist zu schööön 🙂



  • Stimmt. Man muss den Iterator noch zuweisen. Ich war wohl bei Windowslisten, dort findet das Inkrementieren teilweise automatisch statt.

    Braunstein, deine Lösung ist bestimmt richtig. Aber ich finde sie drückt rein semantisch kaum die Absicht des Algorithmus aus. Jemand, der diesen Code liest, wird zunächst nicht verstehen, was eigentlich gemeint ist, ohne irgendwo nachschlagen zu müssen.



  • Meinst du so ?

    for ( iter = liste.begin(); iter != liste.end(); ++it ) 
      if ( (*iter) > x ) 
        iter = liste.erase(iter);
    

    das waere aber auch nicht richtig da jedesmal wenn ein Element geloescht wird das naechste uebersprungen wird.
    Also du hast z.B. die Elemente 1,2,3,4 und 2 wird geloescht dann wird der iterator aufs naechste Element gesetzt also 3 dann kommt der naechste Schleifen-Durchlauf, iter wird inkrementiert und steht jetzt auf 4. Fuer die 3 wuerde also die Bedingung gar nie geprueft werden.



  • Tanren schrieb:

    Meinst du so ?

    for ( iter = liste.begin(); iter != liste.end(); ++it ) 
      if ( (*iter) > x ) 
        iter = liste.erase(iter);
    

    das waere aber auch nicht richtig da jedesmal wenn ein Element geloescht wird das naechste uebersprungen wird.
    Also du hast z.B. die Elemente 1,2,3,4 und 2 wird geloescht dann wird der iterator aufs naechste Element gesetzt also 3 dann kommt der naechste Schleifen-Durchlauf, iter wird inkrementiert und steht jetzt auf 4. Fuer die 3 wuerde also die Bedingung gar nie geprueft werden.

    😉

    Sollte also demnach besser so aussehen:

    for ( list<int>::iterator iter = a.begin(), next = iter; iter != a.end(); iter = next )
    {
        ++next;
        if ( (*iter) > 3 )
            a.erase(iter);
    
    }
    

    turing_mob schrieb:

    Braunstein, deine Lösung ist bestimmt richtig. Aber ich finde sie drückt rein semantisch kaum die Absicht des Algorithmus aus. Jemand, der diesen Code liest, wird zunächst nicht verstehen, was eigentlich gemeint ist, ohne irgendwo nachschlagen zu müssen.

    Braunstein schrieb:

    liste->remove_if(bind2nd(greater<typ>(),(x)));
    

    liste -- lösche wenn -- größer als x
    Mit ein bisschen Phantasie geht das schon 😉 ( bind2nd mal ignoriert 😃 )


Anmelden zum Antworten