Wörter in einem String ersetzen



  • würde mal gerne was zu diesem codeschnipsel frage 🙂

    warum braucht man prototypes ?
    void ersetzen( string &text, string alt, string neu );

    warum sollte man die function erst deklarieren und dann definieren, wenn man sie doch sofort deklarieren/definieren kann?



  • meeydoo schrieb:

    würde mal gerne was zu diesem codeschnipsel frage 🙂

    warum braucht man prototypes ?
    void ersetzen( string &text, string alt, string neu );

    warum sollte man die function erst deklarieren und dann definieren, wenn man sie doch sofort deklarieren/definieren kann?

    Braucht man nicht. Einfach die Funktion oben definieren. Wer so noch Prototypen quetscht, hat wohl Jürgen Wolf gelesen.



  • Vielen Dank für eure Hilfe,

    string::npos kannte ich noch nicht, so wie ich das jetzt verstanden habe ist das so was wie eine Konstante oder ein Typdef in der String-Klasse das einfach -1 an die Stelle setzt (so als würde ich statt string::npos einfach direkt -1 dort hinschreiben). Mehr konnte ich zu string::npos leider nicht finden.

    Ich vermute mal das sich ein "Cursor" auf der Suche durch den String bewegt der seine aktuelle Position zurück gibt und eben -1 zurück gibt wenn Er das Ende des Strings erreicht hat. Unter der Annahme kann ich eure Lösung nachvollziehen.

    Das würde allerdings bedeuten das der suchen und ersetzen Vorgang in einem Durchlauf von statten geht (Das konnte ich in der Funktion mit einer Textausgabe auch verifizieren). Deshalb Frage ich jetzt mal ganz naiv ob es überhaupt Sinn macht eine Schleife zu verwenden, wenn diese in jedem Fall nur einmal durchlaufen wird?

    Dein Ansatz hat noch ein größeres Problem: Wenn der zu ersetzende Text im Ersatztext vorkommt, provozierst du eine Endlosschleife.

    Eine Endlosschleife konnte ich so nicht provozieren, allerdings wird das selbe Wort dann ein paar mal hintereinander gehängt, was auch nicht wünschenswert ist. Euer Ansatz verursacht da keine Probleme, vielen dank für den Hinweis.

    volkard schrieb:

    meeydoo schrieb:

    würde mal gerne was zu diesem codeschnipsel frage 🙂

    warum braucht man prototypes ?
    void ersetzen( string &text, string alt, string neu );

    warum sollte man die function erst deklarieren und dann definieren, wenn man sie doch sofort deklarieren/definieren kann?

    Braucht man nicht. Einfach die Funktion oben definieren. Wer so noch Prototypen quetscht, hat wohl Jürgen Wolf gelesen.

    Erwischt, ja ich hatte mit "Grundkurs C++" von J. W. angefangen, bevor ich hier im Forum über den Autor gelesen habe. Hab das Buch jetzt bei Seite gelegt und mir Herbert Schild's "C++ Die professionelle Referenz" zugelegt. Mächtiger Schinken aber abwechselnd mit ein Paar Tutorial's im Netz beiße ich mich da jetzt so allmählich durch.


  • Mod

    NilsV schrieb:

    string::npos kannte ich noch nicht, so wie ich das jetzt verstanden habe ist das so was wie eine Konstante oder ein Typdef in der String-Klasse das einfach -1 an die Stelle setzt (so als würde ich statt string::npos einfach direkt -1 dort hinschreiben). Mehr konnte ich zu string::npos leider nicht finden.

    Das ist die falsche Einstellung. Wenn soclhe Konstanten angeboten werden, dann nutzt man sie auch. Schreib da nie -1! Dann weiß niemand was du meinst und falls das mal geändert werden sollte, bist du angeschmiert.

    Ich vermute mal das sich ein "Cursor" auf der Suche durch den String bewegt der seine aktuelle Position zurück gibt und eben -1 zurück gibt wenn Er das Ende des Strings erreicht hat. Unter der Annahme kann ich eure Lösung nachvollziehen.

    Wozu vermuten? Referenzen lesen!

    http://www.cplusplus.com/reference/string/string/find/

    edit: Und noch mal: Da wird nicht -1 zurück gegeben, sondern npos!

    Das würde allerdings bedeuten das der suchen und ersetzen Vorgang in einem Durchlauf von statten geht (Das konnte ich in der Funktion mit einer Textausgabe auch verifizieren). Deshalb Frage ich jetzt mal ganz naiv ob es überhaupt Sinn macht eine Schleife zu verwenden, wenn diese in jedem Fall nur einmal durchlaufen wird?

    Verstehe ich nicht. Der Schleifenkörper wird so oft durchlaufen, wie das Wort vorkommt. Und das ist alles was nötig ist. Willst du mit Absicht mehr Arbeit machen als nötig, damit deine Schleifen öfter durchlaufen werden?



  • Das ist die falsche Einstellung. Wenn soclhe Konstanten angeboten werden, dann nutzt man sie auch. Schreib da nie -1! Dann weiß niemand was du meinst und falls das mal geändert werden sollte, bist du angeschmiert.

    Hatte ich nicht vor, ging mir nur darum ob ich richtig verstanden habe was da wie passiert.

    Wozu vermuten? Referenzen lesen!

    Ich dachte das hätte ich, aber die verlinkte Beschreibung gibt mehr her als die in meinem Referenz Buch (oder ich muss wieder an einer anderen Stelle Suchen).

    Verstehe ich nicht. Der Schleifenkörper wird so oft durchlaufen, wie das Wort vorkommt. Und das ist alles was nötig ist. Willst du mit Absicht mehr Arbeit machen als nötig, damit deine Schleifen öfter durchlaufen werden?

    Da melde ich mal vorsichtig Zweifel an.

    Code:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    void ersetzen( string &text, string alt, string neu );
    
    int main( void ) {
        string text = "Das Lernen macht Spaß, das Lernen ist gut, "
                      "vom Lernen krieg ich nie genug.";
    
        cout << "Alter Text: " << text << endl;
        ersetzen(text, "Lernen", "Leben");    
        cout << "Neuer Text: " << text << endl;
    
        return 0;
    }
    
    void ersetzen( string &text, string alt, string neu ) { 
        for (size_t x = text.find(alt); x != string::npos; x = text.find(alt,x+neu.length())) 
            text.replace(x, alt.length(), neu); 
            cout << "Schleifendurchlauf" << endl;
    }
    

    Ausgabe:

    Alter Text: Das Lernen macht Spaß, das Lernen ist gut, vom Lernen krieg ich nie genug.
    Schleifendurchlauf
    Neuer Text: Das Leben macht Spaß, das Leben ist gut, vom Leben krieg ich nie genug.
    

    Das Wort "Lernen" wurde an 3 Stellen ersetzt, die Schleife aber nur 1 mal durchlaufen. Was sich damit deckt wie ich die Funktion verstanden zu haben glaube.



  • NilsV schrieb:

    Was sich damit deckt wie ich die Funktion verstanden zu haben glaube.

    Was genau verstehst du denn nicht?



  • Ich bin nur von dieser Aussage irritiert:

    Verstehe ich nicht. Der Schleifenkörper wird so oft durchlaufen, wie das Wort vorkommt.

    Denn wenn das zutrifft widerspricht das meinem Verständnis des Codes völlig.


  • Mod

    Mach's mal richtig:

    void ersetzen( string &text, string alt, string neu ) {
        for (size_t x = text.find(alt); x != string::npos; x = text.find(alt,x+neu.length()))
         {
            text.replace(x, alt.length(), neu);
            cout << "Schleifendurchlauf" << endl;
         }
    }
    

    Denn wenn das zutrifft widerspricht das meinem Verständnis des Codes völlig.

    Das ist nicht gut. 1. verstehst du den Code offensichtlich völlig falsch. 2. Sollte man so einen Code nicht falsch verstehen. Mir ist gar nicht klar, was da beim Verstehen bei dir schieflaufen könnte



  • NilsV schrieb:

    Erwischt, ja ich hatte mit "Grundkurs C++" von J. W. angefangen, bevor ich hier im Forum über den Autor gelesen habe. Hab das Buch jetzt bei Seite gelegt und mir Herbert Schild's "C++ Die professionelle Referenz" zugelegt. Mächtiger Schinken aber abwechselnd mit ein Paar Tutorial's im Netz beiße ich mich da jetzt so allmählich durch.

    😮
    Fast alle Bücher von Herb Schildt über C und C++ sind nicht zu gebrauchen!
    Buchbewertungen von kompetenten Leuten: http://accu.org/index.php?module=bookreviews&func=search&q=schildt&stype=author
    Das "not recommended" fast überall sollte Dir zu denken geben.



  • NilsV schrieb:

    Dein Ansatz hat noch ein größeres Problem: Wenn der zu ersetzende Text im Ersatztext vorkommt, provozierst du eine Endlosschleife.

    Eine Endlosschleife konnte ich so nicht provozieren, allerdings wird das selbe Wort dann ein paar mal hintereinander gehängt, was auch nicht wünschenswert ist. Euer Ansatz verursacht da keine Probleme, vielen dank für den Hinweis.

    Das kommt ganz darauf an, welche Eingabewerte du übergibst. Mit ungünstigen Eingaben kracht es

    @npos: Das wichtigste daran ist, daß es ein speziell von string definierter size_t-Wert ist. Und dieser Wert wird für zwei Zwecke verwendet - find() und Kollegen geben es als Zeichen für "nichts gefunden" zurück, und bei vielen anderen Methoden wird es als (Default-)Argument für "arbeite bis zum Stringende" verwendet.

    @Prototypen: Bei so kleinen Programmen ist es sinnlos, interessant wird es erst wenn du deine Programme in unabhängige Übersetzungseinheiten gliederst.



  • Hallo,

    vielen Dank für eure zahlreichen Hilfestellungen, mein Verständnisproblem lag darin was string::npos eigentlich genau ist, mein Missgeschick mit den fehlenden Klammern bei der for-Schleife hat meiner Verwirrung dann den Rest gegeben. Der sprichwörtliche Groschen ist jetzt aber gefallen.


Anmelden zum Antworten