Vector mit Strings: Leere Elemente löschen.



  • Hi!

    void remove_empty_strings ( vector <string>& v )
    {
    	for ( vector <string>::iterator it = v.begin(); it != v.end(); it++ )
    		if ( it->empty() )
    			v.erase(it);
    }
    
    vector <string> vs;
    	vs.push_back ("0");
    	vs.push_back ("");
    	vs.push_back ("1");
    

    Es sollen die leeren Strings entfernt werden, nach dem Löschen bekomme ich in
    der Forschleife eine Debug Assertion:

    Expression:("this->_Has_container()",0)

    Nehme ich nen zweiten Iterator zur Hilfe, dann klappt es:

    void remove_empty_strings ( vector <string>& v )
    {
    	vector <string>::iterator save;
    	for ( vector <string>::iterator it = v.begin(); it != v.end(); it++ )
    		if ( it->empty() )
    		{
    			save = it;
    			save--;
    			v.erase(it);
    			it = save;
    		}
    }
    

    Geht das irgendwie einfacher, oder ist das ok so?



  • Gibt erase nicht einen gültigen Iterator zurück? Also so:

    it = v.erase(it);
    


  • ja, da gibts was fertiges.
    http://www.cplusplus.com/reference/algorithm/remove_if/
    nimmst halt

    bool IsEmtty (string const& i) { return i==""; }
    

    oder gabs da nicht sogar

    bool IsEmtty (string const& i) { return i.empty(); }
    

    ?

    dazu noch
    http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove



  • @TyRoXx:
    Habe es so versucht:

    void remove_empty_strings ( vector <string>& v )
    {
     	for ( vector <string>::iterator it = v.begin();	it != v.end(); it++ )
    		if ( it->empty() )
    			it = v.erase (it);
    }
    

    Wenn ich sowas habe:

    vector <string> vs;
    	vs.push_back ("");
    	remove_empty_strings(vs);
    

    Gibt es leider nen Absturz.

    @Volkard:
    Hier mache ich vermutlich noch etwas falsch:

    bool is_empty ( string& s )
    {
    	return s.empty();
    }
    
    int main ( int argc, char* argv[] ) 
    { 
    	vector <string> vs;
    	vs.push_back ("");
    	vs.push_back ("0");
    
    	cout << vs.size() << endl; // 2 OK
    	remove_if ( vs.begin(), vs.end(), is_empty );
    	cout << vs.size() << endl; // 2 Nicht OK, sollte 1 sein.
    

    Ich habe die Ausgabe kommentiert, eigentlich sollte der vector nur noch ein Element haben.



  • ➡

    void remove_empty_strings ( vector <string>& v )
    {
     	for ( vector <string>::iterator it = v.begin();	it != v.end(); /*Hier nix*/ )
    		if ( it->empty() )
    			it = v.erase (it);
    		else
    			++it;
    }
    

    Zum Zweiten:

    volkard schrieb:

    dazu noch
    http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove



  • Nein, std::remove_if() kann den Container selber nicht antasten, da es nur zwei Iteratoren hat. Um ein Element aus dem Container zu entfernen, müsste man diesen kennen. Also manipuliert der STL-Algorithmus die Sequenz, indem einzelne Elemente umkopiert oder getauscht werden.

    Du kannst den Rückgabetypen von std::remove_if() verwenden, um den Anfang des zu löschenden Bereichs zu erhalten. Dann löschst du diesen mit std::vector::erase() - also von dem zurückgegebenen Iterator bis end() .



  • Ah, ok. Funzt.
    Vielen Dank euch allen !


Anmelden zum Antworten