Verwenden von getline(cin, s) nach cin [duplicate]

Lesezeit: 7 Minuten

Verwenden von getlinecin s nach cin duplicate
pauliwago

Ich benötige das folgende Programm, um die gesamte Zeile der Benutzereingabe zu übernehmen und in Zeichenfolgennamen einzufügen:

cout << "Enter the number: ";
int number;
cin >> number;

cout << "Enter names: ";
string names;

getline(cin, names);

Mit dem cin >> number Befehl vor dem getline() Befehl jedoch (was meiner Meinung nach das Problem ist), erlaubt es mir nicht, Namen einzugeben. Warum?

Ich habe etwas über a gehört cin.clear() Befehl, aber ich habe keine Ahnung, wie das funktioniert oder warum das überhaupt notwendig ist.

  • Angenommen, Sie haben Folgendes eingegeben: 5<enter>John<enter>. Dann cin >> number liest GERADE 5. Belassen des Zeilenumbruchzeichens (Enter) im Stream. Also, wenn Sie versuchen, den Namen mit zu lesen getline(cin,name) es liest bis zum Ende der Zeile. ABER ACHTUNG dort ist ein New-Line-Zeichen, das gelesen werden kann (daher sind Namen leer (weil Sie das New-Line-Zeichen nach der 5 nicht abgelesen haben). Wenn Sie zwischen >> und getline() wechseln wollen, brauchen Sie Seien Sie vorsichtig mit dem nachgestellten Zeilenende bei Ihrer Eingabe.

    – Martin York

    21. April 2011 um 8:41 Uhr

  • @LokiAstari: Das ist besser Antworten als alle unten geposteten. Könntest du es so posten?

    – Leichtigkeitsrennen im Orbit

    29. Mai 2015 um 18:39 Uhr

cout << "Enter the number: ";
int number;
cin >> number;

cin.ignore(256, '\n'); // remaining input characters up to the next newline character
                       // are ignored

cout << "Enter names: ";
string names;
getline(cin, names);

Eine andere Möglichkeit, dies zu tun, besteht darin, a zu setzen

cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' ); 

nach ihrem cin>>number; um den Eingabepuffer vollständig zu leeren (alle zusätzlichen Zeichen abzulehnen, bis ein Zeilenumbruch gefunden wird). Du musst #include <limits> um das zu bekommen max() Methode.

  • @jonsca: “Alle zusätzlichen Zeichen abzulehnen” ist in den meisten Produktionssystemen zweifelhaft … es ist gut, Leerzeichen zu essen, aber das Verwerfen unbekannter Daten kann leicht und stillschweigend zu falschen Ergebnissen führen.

    – Toni Delroy

    21. April 2011 um 6:03 Uhr

  • @cnicutar es variiert von Implementierung zu Implementierung

    – Jonska

    21. April 2011 um 6:08 Uhr

  • @Tony Wie wäre es, wenn Sie anstelle einer getline eine Schleife haben, die Zeichen nach der cin-Anweisung aufnimmt? Sicherlich werden die zusätzlichen Charaktere einen Schraubenschlüssel hineinwerfen. Reden Sie eher von Sicherheitslücken?

    – Jonska

    21. April 2011 um 6:10 Uhr


  • “Schleife, die Zeichen einnimmt” … wenn Sie meinen while (isspace(cin.peek())) cin.ignore()… Sieht gut für mich aus. Bezüglich oben dachte ich eher an einen Benutzer, der die Anforderungen an das Eingabeformat missverstanden hat, oder an ein Skript, das die Eingabeunterbrechungen generiert, aber die fehlerhafte Eingabe scheint erfolgreich verarbeitet zu werden, weil sie ignoriert wird – sie können am Ende fehlerhaften Ergebnissen vertrauen. Wenn die Eingabe nicht den Spezifikationen entspricht, ist es besser, Ihr Programm einen Fehler generieren zu lassen.

    – Toni Delroy

    21. April 2011 um 6:26 Uhr

  • @Tony Ah, okay, ich habe falsch interpretiert, was du sagen wolltest. Guter Punkt zur Validierung.

    – Jonska

    21. April 2011 um 6:39 Uhr

1647211209 172 Verwenden von getlinecin s nach cin duplicate
Toni Delroy

cout << "Enter the number: ";
int number;
if (cin >> number)
{
    // throw away the rest of the line 
    char c;
    while (cin.get(c) && c != '\n')
        if (!std::isspace(c))
        {
            std::cerr << "ERROR unexpected character '" << c << "' found\n";
            exit(EXIT_FAILURE);
        }
    cout << "Enter names: ";
    string name;
    // keep getting lines until EOF (or "bad" e.g. error reading redirected file)...
    while (getline(cin, name))
        ...use name...
}
else
{
    std::cerr << "ERROR reading number\n";
    exit(EXIT_FAILURE);
}

Im obigen Code ist dieses Bit …

    char c;
    while (cin.get(c) && c != '\n')
        if (!std::isspace(c))
        {
            std::cerr << "ERROR unexpected character '" << c << "' found\n";
            exit(EXIT_FAILURE);
        }

…überprüft den Rest der Eingabezeile, nachdem die Zahl nur Leerzeichen enthält.

Warum nicht einfach ignorieren?

Das ist ziemlich ausführlich, also mit ignore im Stream danach >> x ist ein oft empfohlener alternativer Weg, um Inhalte bis zum nächsten Zeilenumbruch zu verwerfen, aber es besteht die Gefahr, dass Nicht-Leerzeichen-Inhalte weggeworfen werden und dabei beschädigte Daten in der Datei übersehen werden. Es kann Ihnen egal sein, ob der Inhalt der Datei vertrauenswürdig ist, wie wichtig es ist, die Verarbeitung beschädigter Daten zu vermeiden usw.

Wann würden Sie also clear verwenden und ignorieren?

Damit, std::cin.clear() (und std::cin.ignore()) ist dafür nicht erforderlich, aber nützlich, um den Fehlerstatus zu entfernen. Zum Beispiel, wenn Sie dem Benutzer viele Chancen geben möchten, eine gültige Nummer einzugeben.

int x;
while (std::cout << "Enter a number: " &&
       !(std::cin >> x))
{
    if (std::cin.eof())
    {
        std::cerr << "ERROR unexpected EOF\n";
        exit(EXIT_FAILURE);
    }

    std::cin.clear();  // clear bad/fail/eof flags

    // have to ignore non-numeric character that caused cin >> x to
    // fail or there's no chance of it working next time; for "cin" it's
    // common to remove the entire suspect line and re-prompt the user for
    // input.
    std::cin.ignore(std::numeric_limits<std::streamsize>::max());
}

Geht es nicht einfacher mit skipws oder ähnlichem?

Eine weitere einfache, aber halbgare Alternative zu ignore für Ihre ursprüngliche Anforderung verwendet std::skipws um eine beliebige Menge an Leerzeichen zu überspringen, bevor Zeilen gelesen werden …

if (std::cin >> number >> std::skipws)
{
    while (getline(std::cin, name))
        ...

…aber wenn es eine Eingabe wie “1E6” bekommt (z. B. ein Wissenschaftler versucht, 1.000.000 einzugeben, aber C++ unterstützt diese Notation nur für Gleitkommazahlen), wird das nicht akzeptiert, würden Sie damit enden number einstellen 1und E6 gelesen als erster Wert von name. Unabhängig davon, wenn Sie eine gültige Nummer gefolgt von einer oder mehreren Leerzeilen hätten, würden diese Zeilen stillschweigend ignoriert.

  • Ähm, das beantwortet weder die Frage noch behebt das Problem. -1

    – Leichtigkeitsrennen im Orbit

    11. September 2015 um 0:19 Uhr

  • @LightnessRacesinOrbit: Wie wird das Problem “nicht behoben”? Der erste Anruf bei getline verbraucht den Zeilenumbruch nach der Zahl und Schleifen, bis es eine nicht leere Zeile findet … scheint mir behoben zu sein. Die Frage des OP lautete nicht “warum?” Das Problem ist aufgetreten, hat aber kommentiert, dass er nicht sicher war, warum clear könnte notwendig sein – jemand anderes hat die 5 Jahre alte Frage vor 2 Tagen bearbeitet, um dies hinzuzufügen und den Kern wesentlich zu ändern.

    – Toni Delroy

    13. September 2015 um 14:01 Uhr


  • Jetzt haben Sie bearbeitet [someone else’s] antworte es ist besser

    – Leichtigkeitsrennen im Orbit

    13. September 2015 um 15:33 Uhr

  • @LightnessRacesinOrbit: Ich habe den Kern meines Kommentars zu Jonscas Antwort von 2011 bearbeitet – nichts Neues.

    – Toni Delroy

    14. September 2015 um 0:24 Uhr


Versuchen:

int number;

cin >> number;

char firstCharacterOfNames;
cin >> firstCharacterOfNames;  // This will discard all leading white space.
                               // including new-line if there happen to be any.

cin.unget();                   // Put back the first character of the name.

std::string  names;
std::getline(cin, names);      // Read the names;

Alternative. Wenn Sie wissen, dass Nummer und Namen immer in verschiedenen Zeilen stehen.

cin >> number;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
std::getline(cin, names);

Sie können std::ws verwenden, um alle Leerzeichen im Eingabepuffer zu extrahieren, bevor Sie getline verwenden. Header für std::ws ist sstream.

cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
cin>>ws;
getline(cin, names);

1647211209 986 Verwenden von getlinecin s nach cin duplicate
Zoe steht mit der Ukraine

Probieren Sie cin.ignore() aus, wenn Sie cin vor der Funktion getline() verwenden

void inputstu(){
    cout << "Enter roll Number:";
    cin >> roll_no;
    cin.ignore(); //ignore the withspace and enter key
    cout << "Enter name:";
    getline(cin, stu_name);
}

Oder Sie können den Eingabepuffer leeren, um die Zeichenfolge zu lesen

spülen (stdin)

es ist im Header definiert stdio.h.

Dieser Code funktioniert..

cout << "Enter the number: ";
int number;
cin >> number;

cout << "Enter names: ";
string names;
fflush(stdin);  //FLUSHING STDIN
getline(cin, names);

999230cookie-checkVerwenden von getline(cin, s) nach cin [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy