Problem mit string::erase();

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Kmitska
Beiträge: 349
Registriert: Fr Sep 23, 2011 8:49 pm
Wohnort: Karlsruhe, Pforzheim

Problem mit string::erase();

Beitrag von Kmitska » Mo Mär 19, 2012 8:12 pm

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

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Problem mit string::erase();

Beitrag von fat-lobyte » Mo Mär 19, 2012 9:11 pm

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.
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Problem mit string::erase();

Beitrag von Xin » Di Mär 20, 2012 10:50 am

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.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Problem mit string::erase();

Beitrag von fat-lobyte » Mi Mär 21, 2012 12:36 pm

Xin hat geschrieben:Iteratoren sind Iteratoren, Zeiger sind Zeiger.
Um die Verwirrung vollständig zu machen:
Zeiger sind auch Iteratoren! :mrgreen:
Haters gonna hate, potatoes gonna potate.

Moevi
Beiträge: 1
Registriert: Di Okt 30, 2012 4:41 pm

Re: Problem mit string::erase();

Beitrag von Moevi » Di Okt 30, 2012 5:23 pm

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

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Problem mit string::erase();

Beitrag von fat-lobyte » Di Okt 30, 2012 10:57 pm

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.
Haters gonna hate, potatoes gonna potate.

Antworten