Seite 1 von 1

Problem mit string::erase();

Verfasst: Mo Mär 19, 2012 8:12 pm
von Kmitska
Hallo Leute,

habe wieder einen Problem.
Ich möchte in einen String dass ein "Wort" gelöscht wird.

Code: Alles auswählen

int begin = tmp.find(Variable);
                for(int i=begin; i<=tmp.length(); i++)
                {
                    if(tmp[i] == ';')
                    {
                        tmp.erase(begin, i );
                        break;
                    }
                }
tmp ist mein String und von 'Variable' aus soll es bis zum Semikolon gelöscht werden.
Aber das löscht viel mehr als ich will, woran kann das liegen?

KIND REGARDS,
Kmitska

Re: Problem mit string::erase();

Verfasst: Mo Mär 19, 2012 9:11 pm
von fat-lobyte
Kuck dir mal ganz genau an was passiert.
Sagen wir, der String tmp ist:
tmp == "Suche die Variable und löche; bis hierher"

Gut, tmp.find() gibt 10 zurück, also:
begin = 10;

Weiter im Text: in der Schleife setzt du i = begin;
also i == 10;
Dann versuchst du mit tmp.erase() was zu löschen. Allerdings ist dein Aufruf falsch! Diese Überladung löscht nicht VON der Position begin BIS i, sondern VON begin werden i Zeichen gelöscht (also 10 zeichen!). Bitte sieh dir die Referenz mal genau an: http://www.cplusplus.com/reference/string/string/erase/

Gut, jetzt ein paar Worte zum Stil:
1) Du darfst NIEMALSNIEMAlSNIEMALSNIE ein "int" für eine Position oder für eine Größe verwenden. Dafür gibt es std::size_t.
Das ist nur scheinbar das gleiche, es ist erstens unsigned (das ist wichtig um Überläufe zu verhindern) und zweitens ist es auf 64-Bit Systemen groß genug ("int" nicht!)
2) Ich würde den ganzen Algorithmus anders ansetzen: Finde "Variable", finde ";", dann subtrahiere die beiden Positionen und lösche von "Variable" weg die richtige Anzahl der Zeichen
3) Ganz cool wäre man, wenn man in diesem Fall nicht Positionen verwenden würde, sondern sogenannte "Iteratoren". Das sind mehr oder weniger "verkrüppelte" Zeiger. Du müsstest dann allerdings eine andere funktion zum suchen verwenden: std::search

Code: Alles auswählen

#include <iostream>
#include <string>
#include <algorithm> // für std::search

#include <cassert> // nur für assert(), das brauchst du nicht

int main()
{
    std::string tmp("Suche die Variable und löche; bis hierher");
    std::cout<<"Ursprünglicher String: "<<tmp<<'\n';

    std::string Variable("Variable");

    // suche nach Variable in tmp, setze begin auf die Position
    std::string::iterator begin = std::search(
        tmp.begin(), tmp.end(),
        Variable.begin(), Variable.end()
    );

    assert(begin != tmp.end()); // Wenn nicht gefunden, mach BUMM!

    // suche nach Semikolon
    std::string::iterator semik = std::find(tmp.begin(), tmp.end(), ';');

    assert(semik != tmp.end()); // Wenn nicht gefunden, mach BUMM!

    // lösche richtige Sequenz
    tmp.erase(begin, semik);

    std::cout<<"Resultierender String: "<<tmp<<'\n';

    return 0;
}
Merke: Iteratoren sind nix anders als Zeiger, nur ein bisschen Verkrüppelt.
Man kann auch sagen Iteratoren sind für Container was Zeiger für Arrays sind.

Re: Problem mit string::erase();

Verfasst: Di Mär 20, 2012 10:50 am
von Xin
fat-lobyte hat geschrieben:Merke: Iteratoren sind nix anders als Zeiger, nur ein bisschen Verkrüppelt.
Man kann auch sagen Iteratoren sind für Container was Zeiger für Arrays sind.
Iteratoren sind Iteratoren, Zeiger sind Zeiger.
Iteratoren funktionieren nach außen wie Arrayzeiger.
Iteratoren sind daher gerne mit Zeigern implementiert.

Grundsätzlich kannst Du Dich an fat-lobytes Aussage halten, diese "Haarspalterei" bezieht sich ja nicht konkret auf Deine Frage. Aber behalte im Hinterkopf, dass wenn Du mal selbst einen Iterator schreibst, Du nicht gezwungen bist ihn als Zeiger zu implementieren. Vielleicht ist etwas anderes ja praktischer.

Re: Problem mit string::erase();

Verfasst: Mi Mär 21, 2012 12:36 pm
von fat-lobyte
Xin hat geschrieben:Iteratoren sind Iteratoren, Zeiger sind Zeiger.
Um die Verwirrung vollständig zu machen:
Zeiger sind auch Iteratoren! :mrgreen:

Re: Problem mit string::erase();

Verfasst: Di Okt 30, 2012 5:23 pm
von Moevi
fat-lobyte hat geschrieben:Kuck dir mal ganz genau an was passiert.
Sagen wir, der String tmp ist:
tmp == "Suche die Variable und löche; bis hierher"

Gut, tmp.find() gibt 10 zurück, also:
begin = 10;

Weiter im Text: in der Schleife setzt du i = begin;
also i == 10;
Dann versuchst du mit tmp.erase() was zu löschen. Allerdings ist dein Aufruf falsch! Diese Überladung löscht nicht VON der Position begin BIS i, sondern VON begin werden i Zeichen gelöscht (also 10 zeichen!). Bitte sieh dir die Referenz mal genau an: http://www.cplusplus.com/reference/string/string/erase/

Gut, jetzt ein paar Worte zum Stil:
1) Du darfst NIEMALSNIEMAlSNIEMALSNIE ein "int" für eine Position oder für eine Größe verwenden. Dafür gibt es std::size_t.
Das ist nur scheinbar das gleiche, es ist erstens unsigned (das ist wichtig um Überläufe zu verhindern) und zweitens ist es auf 64-Bit Systemen groß genug ("int" nicht!)
2) Ich würde den ganzen Algorithmus anders ansetzen: Finde "Variable", finde ";", dann subtrahiere die beiden Positionen und lösche von "Variable" weg die richtige Anzahl der Zeichen
3) Ganz cool wäre man, wenn man in diesem Fall nicht Positionen verwenden würde, sondern sogenannte "Iteratoren". Das sind mehr oder weniger "verkrüppelte" Zeiger. Du müsstest dann allerdings eine andere funktion zum suchen verwenden: std::search

Merke: Iteratoren sind nix anders als Zeiger, nur ein bisschen Verkrüppelt.
Man kann auch sagen Iteratoren sind für Container was Zeiger für Arrays sind.
Du solltest Professor oder Lehrer werden. Hast das ziemlich detailiert und gut erklärt. Werde ich mal so umsetzen und versuchen, ob es klappt, da ich ein ähnliches Problem habe.

LG

Re: Problem mit string::erase();

Verfasst: Di Okt 30, 2012 10:57 pm
von fat-lobyte
Moevi hat geschrieben:Du solltest Professor oder Lehrer werden. Hast das ziemlich detailiert und gut erklärt. Werde ich mal so umsetzen und versuchen, ob es klappt, da ich ein ähnliches Problem habe.
Freut mich, wenn ich helfen konnte! Meld dich hier, wenn du nicht weiterkommst.