Probleme beim Einlesen eines Strings wenn zuvor ein char eingelesen wurde



  • Ich verstehe das Verhalten bei diesem Code nicht:

    char test;
    	cin >> test;
    
    	string input;
    	getline(cin, input);
    
    	cout << input;
    

    wenn ich einen Character eingebe (z.B. 'a'), der in test gespeichert wird, so klicke ich nach dem eingeben von 'a' auf Return. Dann habe ich das Problem, dass er mir bei getline nichts einliest (bei dem cout steht dann "", also eigentlich nichts), gibt mir aber nicht die Möglichkeit einen neuen String einzugeben. Wenn ich aber nach dem 'a' ein Leerzeichen eingebe so bekomme ich die Möglichkeit einen String einzugeben.

    So wie ich das verstanden habe wird mittels cin >> solange eingelesen bis ein whitespace kommt, dieses wird jedoch nicht mitgelesen, sondern verworfen. Bei dem Leerzeichen nach dem 'a' klappt das auch, aber wieso nicht mit dem Return?

    MfG

    uncle bens



  • http://www.cplusplus.com/reference/string/string/getline/

    "Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, '\n', for (2))."



  • uncle bens schrieb:

    So wie ich das verstanden habe wird mittels cin >> solange eingelesen bis ein whitespace kommt, dieses wird jedoch nicht mitgelesen, sondern verworfen.

    Andersrum!
    Wenn du mit >> einliest, werden solange Whitespaces überlesen, wie welche da sind*. Dann wird deine Variable eingelesen.

    D.h. wenn du <space>X7<enter> eingibst, überliest der >> den Space und liest dann X in deine char-Variable ein. Das getline dagegen liest immer bis zum <enter>. In diesem Falle wäre also noch 7<enter> zu lesen und somit bekäme dein String dann den Wert 7.

    Was dich vielleicht verwirrt: das cin liest nicht genau einen Zeichendruck ein, sondern bei der Eingabe von Tastatur wird immer auf <enter> gewartet. Das <enter> ist dann aber noch als weiteres Zeichen im Eingabestrom drin und beeinflusst ggf. die folgende Eingabe.

    * das kannst du mit std::skipws & std::noskipws an- und ausschalten



  • Hallo uncle bens,

    man unterscheidet zwischen formatierten und unformatierten Einlesen. 'formatiert' bedeutet hier, dass führende (WS) White-Space-Character überlesen werden, bis etwas kommt, was 'druckbar' ist. Im Fall von ' cin >> test; ' werden - solange kein std::noskipws gesetzt ist - alle WS überlesen, bis ein druckbares Zeichen kommt.

    getline liest immer unformatiert, also 'doof'. Es startet bei der aktuellen Position des Leseziegers und liest bis EOL. Das EOL-Zeichen selbst wird verworfen. D.h wenn Du 'a' '<Return>' eingibst wird mit

    cin >> test;
        getline( cin, input );
    

    das Zeichen 'a' nach 'test' eingelesen und das '<Return>' mit getline gelesen, aber eben nicht in 'input' gespeichert. Fügst Du nach dem 'a' noch ein Space ein, so steht eben das Space-Zeichen später in 'input'. Dies ist aber auch der einzige Unterschied.

    uncle bens schrieb:

    Wenn ich aber nach dem 'a' ein Leerzeichen eingebe so bekomme ich die Möglichkeit einen String einzugeben.

    Das kann ich so nicht nachvollziehen, kannst Du dazu mal eine lauffähige Minimalversion posten.

    Ob formatiert oder unformatiert gelesen wird, ist nicht Sache von cin allein, sondern von der Funktion (oder Extractor) der aktuell aufgerufen wird.

    getline solltest Du nur benutzen, wenn Du wirklich NUR die Zeichenfolge lesen willst, und keine Zahl und kein Wort und auch keine sonst wie gearteten Strukturen. Und Du musst genau wissen, wo der Lesezeiger beim Aufruf von getline steht.



  • Mein Fehler lag in der Annahme das cin >> auch das whitespace, welches das Lesen beendet vom istream löscht. Das ist wohl nicht der Fall.

    Vielen Dank!