C++ for-Schleife - Bedingung wird nicht übernommen



  • Hallo Liebe Community!

    Ich bin ein C++ Anfänger und wollte gerade zu Übungszwecken ein Programm schreiben, dass alle Buchstaben eines Wortes nach dem 1. Leerzeichen (bis auf den ersten) durch 'X' ersetzt.

    `Aus

    "Das Ist eine Beispieleingabe" soll

    "Das IXX eXXX BXXXXXXXXXXXXXX" werden.`

    Wie gesagt, das Programm hat keinen Sinn sondern ist nur für mich zum näheren Verständnis.

    Durch "Step 1" etc. konnte ich verifizieren ob in das jeweilige Codesegment überhaupt vorgegangen wird.

    Problem: Das Problem liegt meines Erachtens in der for #2 Schleife: Das Programm hängt sich immer auch nachdem endlos "Step 3" ausgegeben wird. Anscheinend wird die Bedingung "A[k] != ' '" aus der Schleife nicht übernommen.

    Ich habe leider keine Idee warum nicht 😞
    Wäre über jegliche Hilfe sehr Dankbar! 👍

    Vielen Dank!

    char A[81];
    
        cout << "Geben Sie einen Text ein: ";
        cin.getline(A, sizeof(A));
    
        for (int i = 0; i <= strlen(A); i++) {           //for #1
            cout << "Step 1" << endl;
    
            if (A[i-2] == ' ') {                         //if #1
                cout << "Step 2" << endl;
    
                for (int k = i; A[k] != ' '; ++k) {      //for #2
                    cout << "Step 3" << endl;
    
                    A[k] = 'X';
    
                }   
            }
    
        }
    

  • Mod

    In C++ string für Zeichenketten nutzen!

    Deine Indizes sind ständig außerhalb des erlaubten Bereichs. Wenn beispielsweise beim i beim ersten Durchlauf gleich 0 ist, dann greifst du auf Index i-2, also -2 zu.

    Wenn etwas eine gewisse Länge hat und der erste Index 0 ist, welches ist dann der letzte gültige Index?

    Wann denkst du, endet dein Programm, nachdem das letzte Wort erreicht wird?



  • SeppJ schrieb:

    Wenn etwas eine gewisse Länge hat und der erste Index 0 ist, welches ist dann der letzte gültige Index?

    Die Länge des Strings -1 😕

    SeppJ schrieb:

    Wann denkst du, endet dein Programm, nachdem das letzte Wort erreicht wird?

    Der String endet ja eigentlich mit dem Nullterminator. Es müsste also " i < strlen(A) " in for #2 heissen um keine Bereichsüberschreitung zu begehen?

    Auch nach dem ändern auf i = 2 in for #1 gibt es keinen Unterschied am Problem 😕

    Danke für die schnelle Antwort!



  • Stephan239 schrieb:

    Es müsste also " i < strlen(A) " in for #2 heissen um keine Bereichsüberschreitung zu begehen?

    Berichtigung: in for #1.


  • Mod

    Stephan239 schrieb:

    SeppJ schrieb:

    Wenn etwas eine gewisse Länge hat und der erste Index 0 ist, welches ist dann der letzte gültige Index?

    Die Länge des Strings -1 😕

    Und bis zu welchem Index läufst du?
    edit: Ok, deine andere Antwort hat das korrigiert. Trotzdem: Nutze in C++ string statt char-Arrays! Und auch in C sollte strlen niemals in einer Schleifenbedingung stehen. Die C-Funktion strlen hat sehr hohe Laufzeitkosten, die dann bei jedem Schleifendurchgang anfallen.

    SeppJ schrieb:

    Wann denkst du, endet dein Programm, nachdem das letzte Wort erreicht wird?

    Der String endet ja eigentlich mit dem Nullterminator. Es müsste also " i < strlen(A) " in for #2 heissen um keine Bereichsüberschreitung zu begehen?

    Ich frage noch einmal genauer: Wann denkst du, endet die k-Schleife, nachdem das letzte Wort erreicht wird?



  • Ich verstehe die Frage nicht ganz. Beim erreichen des nächsten Leerzeichens sollte die Bedingung "A[k] != ' '" nicht mehr erfüllt sein und die Schleife somit bis zum Leerzeichen nach dem Wort laufen 😕



  • Stephan239 schrieb:

    Ich verstehe die Frage nicht ganz. Beim erreichen des nächsten Leerzeichens sollte die Bedingung "A[k] != ' '" nicht mehr erfüllt sein und die Schleife somit bis zum Leerzeichen nach dem Wort laufen 😕

    Ich seh kein Leerzeichen wenn ich beim letzten Wort bin.



  • Warum nicht einfach mit

    while(std::cin >> str) { ... }
    

    Wort für Wort einlesen, bei jedem Durchlauf alle Zeichen abgesehen von str[0] durch 'X' ersetzen und zusammen mit einem Leerzeichen an einen String mit der gesamten Eingabe anhängen?
    Das halte ich hier für die einfachste Lösung.



  • #include <string>
    #include <sstream>
    
    std::string translate_sentence(std::string s){
        std::stringstream stream{s};
        std::string word;
    
        if(!std::getline(stream, word, ' '))
            return "";
    
        s = word;
    
        while(std::getline(stream, word, ' ')){
            if(word.size())
                s += word[0] + std::string(word.size() - 1, 'X');
        }
    
        return s;
    }
    

    Lies zeilenweise rein.



  • Ganz simple Lösung ohne Strings zusammenzukleben:

    void outputX (char *s)
    {
        int f;
        for (f=0;*s;s++)
        {
            if (*s == ' ') f = 1;
            putchar (f-- < 0 ? 'X' : *s);
        }
    }
    


  • Danke für die neuen Ansätze!

    Mir würde es aber allein für das Verständnis von Schleifen sehr helfen, den Fehler in meinem ursprünglichen Code zu finden.

    Wäre darüber sehr dankbar!



  • Stephan239 schrieb:

    Mir würde es aber allein für das Verständnis von Schleifen sehr helfen, den Fehler in meinem ursprünglichen Code zu finden.

    Das hat dir SeppJ doch schon in der ersten Antwort erklärt: deine Indizes liegen z.B. völlig daneben. Die dürfen sich normalerweise nur im Bereich 0 <= n < array.length bewegen.



  • Stephan239 schrieb:

    Danke für die neuen Ansätze!

    Mir würde es aber allein für das Verständnis von Schleifen sehr helfen, den Fehler in meinem ursprünglichen Code zu finden.

    Wäre darüber sehr dankbar!

    Den Fehler in der ersten Schleife hast du korrigiert. Die Antwort für die zweite Schleife hat dir out bereits gegeben.

    Wofür brauchst du überhaupt eine zweite Schleife?

    In der (korrigierten) ersten Schleife läufst du doch bereits über alle Buchstaben im String. Dein Algorithmus sollte doch ungefähr so funktionieren:

    Schau dir jeden Buchstaben beginnend beim ersten an. Falls der Buchstabe ein Leerzeichen war, dann ersetze jeden weiteren Buchstaben durch ein "X".



  • temi schrieb:

    Schau dir jeden Buchstaben beginnend beim ersten an. Falls der Buchstabe ein Leerzeichen war, dann ersetze jeden weiteren Buchstaben durch ein "X".

    Naja, das ist nicht ganz richtig.
    Dann wird "Das ist ein Text" zu "Das XXXXXXXXXXXX" 😞



  • Andromeda schrieb:

    temi schrieb:

    Schau dir jeden Buchstaben beginnend beim ersten an. Falls der Buchstabe ein Leerzeichen war, dann ersetze jeden weiteren Buchstaben durch ein "X".

    Naja, das ist nicht ganz richtig.
    Dann wird "Das ist ein Text" zu "Das XXXXXXXXXXXX" 😞

    Du hast vollkommen recht!

    Hier ist eine kleine Ergänzung erforderlich und es stellt sich außerdem die Frage was passieren soll, wenn zwei Leerzeichen aufeinander folgen.

    Eine Möglichkeit wäre es, sich zu merken, dass ein Leerzeichen aufgetreten ist und in diesem Fall zu prüfen, ob das folgende Zeichen ein Buchstabe ist. Alle weiteren Zeichen werden durch "X" ersetzt.



  • temi schrieb:

    Hier ist eine kleine Ergänzung erforderlich und es stellt sich außerdem die Frage was passieren soll, wenn zwei Leerzeichen aufeinander folgen.

    Das ist eine interessante Frage. Witzigerweise kommt meine Triviallösung damit klar (siehe vorherige Seite).

    Aus:

    "Das      ist eine     Beispieleingabe und mehr nicht!"
    

    wird:

    "Dxx      ixx exxx     Bxxxxxxxxxxxxxx uxx mxxx nxxxxx"
    

    🙂



  • Danke nochmal für die zahlreichen Antworten.

    Nach langem Herumprobieren bin ich nun auf folgende funktionierende Lösung gekommen:

    char A[81];
        int wortlaenge = -1;
        int wortanfang_i = 0;
    
        cout << "Geben Sie den Text ein: ";
        cin.getline(A, sizeof(A));
    
        for( int i = 0; i <= strlen(A); i++ ) {
            wortlaenge = wortlaenge + 1;
    
            if( A[i] == ' ' || A[i] == '\0' ) {
                wortanfang_i = i-wortlaenge;
    
                for( int j = wortanfang_i+1; j < i; j++ ) {
                    A[j] = 'X';  
                } 
            wortlaenge = -1;
            wortanfang_i = 0;
            } 
        }
    

    Statt dem ersetzen von 'X' könnte man das Programm jetzt Grossbuchstaben nach dem 1. Buchstaben in Kleinbuchstaben umwandeln (HALLO -> Hallo). (Damit das Programm auch mal Sinn ergeben würde :D)

    Danke an das Forum! 👍



  • Ich würde dem ganzen noch ein bisschen C++-Anstrich geben, d.h. std::string statt char-Array und iteratoren statt Zeiger.



  • Techel schrieb:

    Ich würde dem ganzen noch ein bisschen C++-Anstrich geben, d.h. std::string statt char-Array und iteratoren statt Zeiger.

    Man ist ja nerdish by nature. 😉



  • Bitte Bitte 🙂

    Mal ne andere Frage: Womit lernst du C++? Tutorial? Skript aus der Schule? Buch?
    Und welche Entwicklungsumgebung nutzt du?

    Ich habe genauso wie du angefangen, in meiner Ausbildung. Am Ende der Ausbildung musste ich feststellen, dass das alles Schrott war und hab dann mit C++ von vorne angefangen. Das passiert vielen Leuten - denn selbst die Profs haben oft keinen Plan - und bei dir scheint das auch der Fall zu sein. Machs lieber gleich richtig und verschwende keine Jahre ;). Außerdem macht korrektes C++ mehr Spaß und ist zudem noch einfacher.


Anmelden zum Antworten