FWIW, я догадался, в чем проблема (это глупо распространено), прежде чем увидел обновление, и посмеялся про себя при других догадках (хотя они дают очень хорошие замечания, даже если пропустили проблему ОП).
Строка кода работает правильно и в соответствии с объявлением. Это не работает так, как вы хотите.
Когда вы читаете из std :: cin, не приостанавливает программу и ожидает ввода. Причиной паузы является отсутствие достаточных входных данных для операции чтения.
Вход подается в вашу программу по очереди. Помните, что консольное окно - это тоже программа. Он отвечает за преобразование нажатий клавиш пользователем в текстовые символы (в действительности, байты), обработку таких вещей, как клавиша возврата и сбор всего текста в строки.
Допустим, вы прочитали int
с помощью operator>>
, а затем прочитали строку с getline
. Программа не увидит int
, пока пользователь не нажмет клавишу Return, потому что это заставит консоль передать строку ввода в вашу программу.
operator>>
пропустит пробел пробела, прочитает целое число, а оставит только пробел . Символы новой строки являются пробелами. На входе есть символ новой строки (очевидно, в конце строки).
getline()
не будет пропустить ни одного начального пробела и будет читать до следующего символа новой строки. Самым следующим символом является символ новой строки, поэтому getline()
с радостью читает пустую строку, и программа продолжает это.
Так как вы это исправите? Скорее всего, если вы читаете все свои входные данные из cin
, вы хотите, чтобы программа приостанавливала каждый раз, когда вы приходите к операции чтения. Способ сделать это состоит в том, чтобы в этот момент никогда не было доступных данных, и способ сделать это - прочитать все, что доступно, то есть всю строку, каждый раз, когда вы что-то читаете.
Итак, всегда читайте полную строку из cin
. Как отмечает wilx, используйте для этого бесплатную функцию std::getline
. Не используйте функцию-член .getline
потока. Используйте std::string
для представления строк текста. Вот для чего это. Это сделает вашу жизнь намного, намного проще. Это также означает, что если вы ожидаете целое число и пользователь вводит «76 тромбонов», вы избавляетесь от данных «тромбонов» (и можете решить хотите ли вы просто выбросить его или закричать на пользователя и заставить его повторно ввести номер без каких-либо забавных комментариев).
Но тогда что? У вас просто есть строка, где вы, возможно, хотели int. К счастью, для этого есть простое решение. Мы можем рассматривать строку как источник данных потока , используя стандартный класс библиотеки std::stringstream
. Мы просто создаем поток строки из строки, а затем используем его так же, как std::cin
- т.е. мы можем читать из него с помощью operator>>
, проверять состояние потока, чтобы увидеть, было ли чтение успешным, и т. Д.
Как отмечает sbi, всегда проверяйте, было ли чтение успешным! Если вы пытаетесь прочитать int
, а поток содержит текст типа "hi mom", то (a) переменная int
будет не будет изменено (поэтому, если он был неинициализирован, он все еще неинициализирован, в очень опасном состоянии), и (b) поток перейдет в состояние «сбой» и не читайте дальше, пока вы не очистите его, и (c) даже если вы очистите его, данные все равно будут там, что может вызвать бесконечный цикл, если вы не будете осторожны.
К счастью, с отдельным stringstream
мы избегаем всевозможных осложнений. Если чтение не удается, то все это происходит с объектом stringstream
, а не с std::cin
. Операция getline
всегда будет успешной на std::cin
, если только пользователь явно не указывает конец файла (символ control-D в Linux или control-Z в Windows). Мы можем легко проверить, находится ли stringstream
в состоянии сбоя, выполнить цикл и просто создать еще один - старый автоматически очистится.
Мы даже можем создать вспомогательную функцию, например:
template <typename T>
// Attempt to read into to_read, and return whether successful.
bool read_primitive_from_input(std::istream& input, T& to_read) {
std::string line;
std::getline(std::cin, line);
std::istringstream iss(line);
return iss >> to_read;
}
std::stringstream
предоставляется заголовком стандартной библиотеки <sstream>
. std::string
происходит от <string>
, конечно.