Używanie getline (cin, s) po cin

Potrzebuję poniższego programu, aby pobrać całą linię danych wejściowych użytkownika i umieścić ją w nazwach łańcuchów:

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

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

getline(cin, names);

Z poleceniem cin >> number przed poleceniem getline() jednak (co chyba jest problemem), nie pozwoli mi to na wprowadzanie nazw. Dlaczego?

Słyszałem coś o cin.clear() poleceniu, ale nie mam pojęcia, jak to działa i dlaczego jest to w ogóle konieczne.

Author: Michael Currie, 2011-04-21

12 answers

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);
}

W powyższym kodzie, ten bit...

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

...sprawdza, czy reszta linii wejściowej po numerze zawiera tylko białe znaki.

Dlaczego po prostu nie użyć ignorować?

To dość gadatliwe, więc używanie ignore w strumieniu po >> x jest często zalecanym alternatywnym sposobem odrzucania zawartości do następnego znaku nowego wiersza, ale grozi wyrzuceniem zawartości nie zawierającej białych znaków, a tym samym pominięciem uszkodzonych danych w pliku. Może cię to obchodzić lub nie, w zależności od tego, czy zawartość pliku jest zaufana, jak ważne jest unikanie przetwarzania uszkodzonych danych itp..

Kiedy użyjesz clear I ignore?

Tak więc, std::cin.clear() (i std::cin.igore()) nie jest do tego konieczne, ale jest przydatne do usuwania stanu błędu. Na przykład, jeśli chcesz dać użytkownikowi wiele szans na wprowadzenie poprawnego numeru.

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());
}

Nie może być prostsze z skipws lub podobne?

Kolejną prostą, ale na wpół upieczoną alternatywą dla ignore dla Twojego pierwotnego zapotrzebowania jest użycie std::skipws aby pominąć dowolną ilość białych znaków przed odczytaniem linii...

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

...ale jeśli Dane wejściowe będą takie jak" 1E6 " (np. jakiś Naukowiec próbuje wprowadzić 1,000,000, ale C++ obsługuje tylko ten zapis dla liczb zmiennoprzecinkowych) nie zaakceptuje tego, skończysz z number ustawionym na 1 i E6 odczytanym jako pierwsza wartość name. Oddzielnie, jeśli masz poprawny numer, po którym następuje jedna lub więcej pustych linii, linie te będą po cichu ignorowane.

 9
Author: Tony Delroy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-16 04:04:38
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);
 16
Author: Cristiano Miranda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-08 19:11:47

Innym sposobem jest umieszczenie

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

Po cin>>number; spłukać bufor wejściowy całkowicie (odrzucając wszystkie Dodatkowe znaki, dopóki nie zostanie znaleziony nowy wiersz). Musisz #include <limits>, aby uzyskać metodę max().

 15
Author: jonsca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-21 05:53:23

Try:

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;

Alternatywnie. Jeśli wiesz, że liczba i nazwiska będą zawsze na różnych liniach.

cin >> number;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
std::getline(cin, names);
 9
Author: Martin York,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-21 08:47:58

Możesz użyć STD::ws do wyodrębnienia białych znaków w buforze wejściowym przed użyciem getline. Nagłówek dla STD:: ws to sstream.

cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
cin>>ws;
getline(cin, names);
 5
Author: Rajeev Atmakuri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-16 17:50:21

Lub możesz spłukać bufor wejściowy, aby odczytać łańcuch

Fflush (stdin)

Jest zdefiniowany w nagłówku stdio.h .

Ten kod działa..

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

cout << "Enter names: ";
string names;
fflush(stdin);  //FLUSHING STDIN
getline(cin, names);
 1
Author: Pzy64,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-12 13:23:43
cout << "Enter the number: ";
int number;
cin >> number;

cout << "Enter names: ";
string names;
getline(cin, names);//works on the \n left behind
getline(cin, names);//continues and rewrites names

Jest całkiem samowystarczalny, w strumieniu, którego używa cin >> number, który zostaje przypisany do nazw po raz pierwszy. Ponowne użycie linii get zapisuje teraz poprawną wartość.

 1
Author: Aditya Gullapalli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-19 17:11:05

Możesz znaleźć żądaną odpowiedź w cppreference .

Gdy zostanie użyte bezpośrednio po wejściu rozdzielonym białymi znakami, np. po int n; std::cin >> n;, getline zużywa znak końcowy pozostawiony w strumieniu wejściowym przez operatora> > i natychmiast powraca. Powszechnym rozwiązaniem jest ignorowanie wszystkich pozostałych znaków w linii wejścia za pomocą cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); przed przełączeniem na wejście zorientowane liniowo.

 0
Author: shuaihanhungry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-20 02:17:39

Chcesz użyć cin.ignoruj () po poleceniach cin, ponieważ chcesz zignorować "\n " pozostawione w buforze po pobraniu zmiennej int z cin.

Mam podobny program, którego używałem z podobnym problemem:

#include <iostream>
#include <iomanip>
#include <limits>

using namespace std;

int main() {
    int i = 4;
    double d = 4.0;
    string s = "HackerRank ";

    // Declare second integer, double, and String variables.
    int n;
    double d2;
    string str;

    // Read and save an integer, double, and String to your variables.
    cin >> n;
    cin >> d2;

    cin.ignore();

    getline(cin, str);

    // Print the sum of both integer variables on a new line.
    cout << i + n << endl;


    // Print the sum of the double variables on a new line.
    cout << d + d2 << endl;

    // Concatenate and print the String variables on a new line
    cout << s << str << endl;

    // The 's' variable above should be printed first.

    return 0;
}
 0
Author: lopezdp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-16 18:49:15

Właśnie użyłem

getline(cin >> ws,lard.i_npute);

Ze standardem

#include <iostream>

Nagłówek w przypadkach, w których miałem problemy ze zwrotami karetki i manipulator ws działał. Prawdopodobnie zacznę osadzać funkcje pętli jako klasy i używać constructor i destructor conajmniej.

 0
Author: 1911 Soldier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 17:25:31

Koncepcyjnie, myślę, że chcesz, aby każda odpowiedź była starannie jedna linijka. Więc dlaczego nie spróbujesz tego?

cout << "Enter the number: ";
string line;
getline(cin, line);
int number = std::stoi(line);

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

Kod poprawnie pobiera pierwszy znak nowej linii, podaje liczbę, jeśli linia jest poprawna, lub rzuca wyjątek, jeśli nie. Wszystko za darmo!

 0
Author: ngọcminh.oss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-09 12:56:45
#include <iostream>
#include <string>

using namespace std;

int main()
{
    cout << "Enter the number: ";
    int number;
    cin >> number;
    cout << "Enter names: ";
    string names;

    // USE peek() TO SOLVE IT! ;)
    if (cin.peek() == '\n') {
        cin.ignore(1 /*numeric_limits<streamsize>::max()*/, '\n');
    }

    getline(cin, names);

    return 0;
}

Wystarczy zajrzeć do przodu używając cin.peek() i sprawdzić, czy '\n' jest nadal w wewnętrznym buforze cin. Jeśli tak, to ignoruj (w zasadzie pomiń)

 -1
Author: max,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-03 09:55:03