Почему это происходит?
Это имеет мало общего с вводом, который вы предоставили сами, а скорее с поведением по умолчанию, которое имеет std::getline()
. Когда вы указывали свой возраст (std::cin >> age
), вы не только вводили следующие символы, но также к потоку добавлялся неявный символ новой строки, когда вы нажимали Enter:
"10\n"
К вашему вводу всегда добавляется новая строка, когда вы выбираете Enter или Return при отправке с терминала. Он также используется в файлах для перехода к следующей строке. Новая строка остается в буфере после извлечения в age
до следующей операции ввода-вывода, где она либо отбрасывается, либо считывается. Когда поток управления достигает std::getline()
, он увидит "\nMr. Whiskers"
и новая строка в начале будет отброшена, но операция ввода немедленно прекратится. Причина, по которой это происходит, заключается в том, что работа std::getline()
состоит в том, чтобы попытаться прочитать символы и остановиться, когда он находит новую строку. Таким образом, остальная часть вашего ввода остается в буфере непрочитанной.
Решение
cin.ignore()
Чтобы исправить это, один из вариантов — пропустить новую строку перед выполнением std::getline()
. Вы можете сделать это, вызвав std::cin.ignore()
после первой операции ввода. Он отбросит следующий символ (символ новой строки), чтобы он больше не мешал.
std::cin >> age;
std::cin.ignore();
std::getline(std::cin, name);
Сопоставьте операции
Когда вы сталкиваетесь с подобной проблемой, это обычно происходит из-за того, что вы комбинируете форматированные операции ввода с неформатированными операциями ввода. Операция форматированного ввода — это когда вы берете ввод и форматируете его для определенного типа. Вот для чего operator>>()
. Неформатированные операции ввода — это что угодно, кроме этого, например std::getline()
, std::cin.read()
, std::cin.get()
и т. д. Эти функции не заботятся о формате ввода и обрабатывают только необработанный текст.
Если вы придерживаетесь одного типа форматирования, вы можете избежать этой досадной проблемы:
// Unformatted I/O
std::string age, name;
std::getline(std::cin, age);
std::getline(std::cin, name);
or
// Formatted I/O
int age;
std::string first_name, last_name;
std::cin >> age >> first_name >> last_name;
Если вы решите читать все как строки, используя неформатированные операции, вы можете впоследствии преобразовать их в соответствующие типы.
person
0x499602D2
schedule
05.02.2014
std::cin >> name && std::cin >> std::skipws && std::getline(std::cin, state)
также должен работать должным образом. (В дополнение к ответам ниже). - person jww   schedule 11.11.2018