Zeichenkette mit Abbruch von "STOP" einlesen



  • Guten Abend!

    Ich versuche folgendes Beispiel zu lösen:
    Lesen Sie maximal 50 Zeichenketten ein (jede Zeichenkette hat maximal 80 Zeichen, Abschluß durch Eingabe von "Stop") sowie einen Wert n. Geben Sie dann alle Zeichenketten ein, die maximal n Zeichen lang sind. Die Verwendung von Stringfunktionen (strlen etc.) ist nicht gestattet.
    Anmerkung: Beachten Sie, dass beim Einlesen eine Zeichenkette durch ein Leerzeichen beendet wird. z.B.

    Eingabe: C++ ist ganz schön kompliziert so im Allgemeinen Stop n=4
    Ausgabe: C++ ist ganz so im

    Mir bereitet die Abbruchbedingung mit STOP Probleme.
    Mein Ansatz sieht bisher so aus:

    char zeichenketten[50][81];
        char abbruch[5] = {"STOP"};
    
        cout << "Eingabe Zeichenketten: " << endl;
    
        for(int i = 0; i < 50; ++i){
            for(int j = 0; zeichenketten[i][j] != '\0' && j < 81; j++){
                for(int k = 0; k < 5; ++k){
    
                   if(zeichenketten[i][k] == abbruch[k]){
                           i = 50;
                           j = 81;
                           break;
                       }
    
                }
    
                cin >> zeichenketten[i][j];
            }
    
        }
    

    Wenn ich meinen Beispielssatz einlese, hätte ich gerne
    i = 0 j= erstesWort
    i = 1 j=zweitesWort
    ...

    Leider funktioniert das so nicht.
    Vielleicht kann mir jemand verraten was ich falsch mache oder mir einen kleinen Tipp geben.

    Danke



  • Man kann C-Strings nicht per == vergleichen. Das ginge mit std::strcmp() . Da du aber ja keine fertigen Stringfunktionen verwenden darst, musst du dir entweder deine eigene Vergleichsfunktion schreiben, oder im if wirklich jedes der fünf Zeichen vergleichen.
    Wieso ließt du eigentlich Zeichenweise von cin ?



  • Wieso ließt du eigentlich Zeichenweise von cin?

    Wenn ich nicht zeichenweise mit cin einlesen möchte, wie könnte ich es den dann machen?



  • Vielleicht sollte ich mein Problem etwas visualisieren, um es besser verständlich zu machen.

    wenn ich

    cout << "i " << i << "j " << j  << " " << zeichenketten[i][j] << endl;
    

    bei der Eingabe meiner Testzeile
    C++ ist ganz schön kompliziert so im Allgemeinen Stop
    eingebe, erhalte ich

    Eingabe Zeichenketten:
    C++ ist ganz schön kompliziert so im Allgemeinen STOP
    i 0j 0 C
    i 0j 1 +
    i 0j 2 +
    i 0j 3 i
    i 0j 4 s
    i 0j 5 t

    i 1j 0 g
    i 1j 1 a
    i 1j 2 n
    i 1j 3 z
    i 1j 4 s

    i 50j 81 c

    Program ended with exit code: 0

    Jedoch hätte ich gerne, dass sich nach jedem Leerzeichen i um eins erhöht und erst durch die Eingabe von STOP abbricht.



  • estrella schrieb:

    Eingabe Zeichenketten:
    C++ ist ganz schön kompliziert so im Allgemeinen STOP

    [...]

    Program ended with exit code: 0

    Ähm ... nein? Der von Dir im Eröffnungspost gezeigte Code zeigt sicher nicht das von dir jetzt beschriebene Verhalten.

    estrella (sinngemäß) schrieb:

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    	char zeichenketten[50][81];  // <-- uninitialisiert. Da steht jetzt irgendein Muell drin.
    	char abbruch[ /* 5 <-- brauchst du nicht angeben, wenn du eh initialisierst */ ] = "STOP";
    
    	cout << "Eingabe Zeichenketten: " << endl;
    
    	for (int i = 0; i < 50; ++i) {  // <-- gut, maximal in zeichenketten[0...50] einlesen.
    
    		for (int j = 0; zeichenketten[i][j] != '\0' && j < 81; j++) {  // <-- aehm. siehe unten 1)
    			
    			for (int k = 0; k < 5; ++k) {                 // --+ 
    				if (zeichenketten[i][k] == abbruch[k]) {  //   |
    					i = 50;                               //   +- lass' ich jetzt mal aus 3)
    					j = 81;                               //   |
    					break;                                // --+
    				}
    			}
    
    			cin >> zeichenketten[i][j];  // <-- Wirklich? 2)
    		}
    	}
    }
    
    1. for (int j = 0; zeichenketten[i][j] != '\0' && j < 81; j++)
      Warum brauchst du zum wortweisen ("Beachten Sie, dass beim Einlesen eine Zeichenkette durch ein Leerzeichen beendet wird.") Einlesen eine Schleife von 0...80 ? Weiters verwendest du ein uninitialisiertes zeichenketten[i][j] in der Bedingung. Aber du brauchst diese Schleife sowieso nicht.

    2. cin >> zeichenketten[i][j]
      Damit ließt Du ein Zeichen nach zeichenketten[i][j] . Wenn du "C++ ist [...][Enter]" eingibst,
      landet das 'C' in zeichenketten[0][0] . Der Rest ( "++ ist [...][Enter]" ) bleibt im Eingabepuffer.
      j=1 : '+' landet in zeichenketten[0][1] . Der Rest ( "+ ist [...][Enter]" ) bleibt im Eingabepuffer.
      j=2 : '+' landet in zeichenketten[0][2] . Der Rest ( " ist [...][Enter]" ) bleibt im Eingabepuffer.
      j=3 : ' ' landet in zeichenketten[0][3] . Der Rest ( "ist [...][Enter]" ) bleibt im Eingabepuffer.
      j=4 : 'i' landet in zeichenketten[0][4] . Der Rest ( "st [...][Enter]" ) bleibt im Eingabepuffer.
      j=5 : 's' landet in zeichenketten[0][5] . Der Rest ( "t [...][Enter]" ) bleibt im Eingabepuffer.
      j=6 : 't' landet in zeichenketten[0][6] . Der Rest ( " [...][Enter]" ) bleibt im Eingabepuffer.

    ... aber Moment mal, nach "C++" sollte die erste Zeichenkette zeichenketten[0] doch schon zu Ende sein (Leerzeichen) und das "ist" in zeichenketten[1] landen!? So wird das also nichts.

    Vergiss mal das Array aus 50 Zeichenketten für je maximal 80 Zeichen ... wie liest man denn ein Wort in ein char -Array? Genau:

    #include <iostream>
    
    int main()
    {
    	char wort[ 81 ];
    	std::cin >> wort;
    
    	// Ausgabe zur Prüfung:
    	std::cout << '\"' << wort << "\"\n";
    }
    

    Konsole:

    C++[Enter]
    "C++"
    

    Yeah, funktioniert! So, jetzt mit drei Wörtern:

    #include <iostream>
    
    int main()
    {
    	char wort1[ 81 ];
    	std::cin >> wort1;
    
    	char wort2[ 81 ];
    	std::cin >> wort2;
    
    	char wort3[ 81 ];
    	std::cin >> wort3;
    
    	// Ausgabe zur Prüfung:
    	std::cout << '\"' << wort1 << "\"\n";
    	std::cout << '\"' << wort2 << "\"\n";
    	std::cout << '\"' << wort3 << "\"\n";
    }
    

    Konsole:

    C++ ist ganz[Enter]
    "C++"
    "ist"
    "ganz"
    

    Yeah, funktioniert auch! So, jetzt mit einem Array für drei Wörter:

    #include <cstddef>
    #include <iostream>
    
    int main()
    {
    	char wort[ 3 ][ 81 ];
    
    	for( std::size_t i = 0; i < 3; ++i )
    		std::cin >> wort[ i ];
    
    	// Ausgabe zur Prüfung:
    	for( std::size_t i = 0; i < 3; ++i )
    		std::cout << '\"' << wort[ i ] << "\"\n";
    }
    

    Konsole:

    C++ ist ganz[Enter]
    "C++"
    "ist"
    "ganz"
    

    Aaah, so funktioniert das also 😉

    1. Prüfen auf "STOP"
      Wenn du keine fertigen Stringfunktionen verwenden darfst, dann wird es wohl das einfachste sein, einfach alle Zeichen in einem if zu prüfen.

    Zusammengesetzt:

    #include <cstddef>
    #include <iostream>
    
    int main()
    {
    	char zeichenketten[ 50 ][ 81 ];
    	std::size_t anzahl;
    
    	for( anzahl = 0; anzahl < 50; ++anzahl ) {
    
    		std::cin >> zeichenketten[ anzahl ];
    
    		if( zeichenketten[ anzahl ][ 0 ] == 'S' &&
    		    zeichenketten[ anzahl ][ 1 ] == 'T' &&
    		    zeichenketten[ anzahl ][ 2 ] == 'O' &&
    		    zeichenketten[ anzahl ][ 3 ] == 'P' &&
    		    zeichenketten[ anzahl ][ 4 ] == '\0' )
    		{
    			break;  // for-Schleife abbrechen.
    		}
    	}
    
    	// Ausgabe zur Prüfung:
    	for( std::size_t i = 0; i < anzahl; ++i ) {
    
    		std::cout << "Wort " << i + 1 << ": \"" << zeichenketten[ i ] << "\"\n";
    	}
    }
    

    Konsole:

    C++ ist ganz schön kompliziert so im Allgemeinen STOP[Enter]
    Wort 1: "C++"
    Wort 2: "ist"
    Wort 3: "ganz"
    Wort 4: "schön"
    Wort 5: "kompliziert"
    Wort 6: "so"
    Wort 7: "im"
    Wort 8: "Allgemeinen"
    


  • Vielen lieben Dank für deine verständliche Erklärung und wunderbare Unterstützung.



  • Kein Problem. Jetzt wirds eh nochmal spannend mit dem "n=sonstwas" . 😉



  • Es sollte allerdings noch ein Overflow vermieden werden:

    std::cin >> std::setw(81) >> zeichenketten[anzahl];
    

    (Header iomanip einbinden)
    Das sorgt dafür, dass maximal 80 Zeichen eingelesen werden.


Anmelden zum Antworten