Почему getline пропускает строку после cin в C++

После ввода числа программа сразу печатает пустое имя? На примере разбираем, что осталось после Enter и когда выбрать cin.ignore() или std::ws.

Содержание

Программа спрашивает возраст, затем имя. Вы вводите 17, нажимаете Enter — и программа уже печатает Имя: []. Ввести имя она даже не предложила. Куда делась строка? Посмотрим, что именно успели прочитать std::cin >> age и std::getline.

Повторим ошибку за минуту

main.cpp
C++
#include <iostream>
#include <string>

int main() {
    int age;
    std::string name;
    if (!(std::cin >> age)) return 1;
    std::getline(std::cin, name);
    std::cout << "Имя: [" << name << "]\n";
}

Введите две строки или вставьте сразу весь пример. Квадратные скобки в выводе нужны только для того, чтобы пустое имя было видно.

Ввод
TXT
17
Анна Маркова
Вывод
TXT
Имя: []

Что осталось после ввода числа

Когда вы нажимаете Enter, во входной поток попадает символ перевода строки — \n. Если представить весь ввод одной записью, получится 17\nАнна Маркова\n. После чтения числа курсор стоит сразу за семёркой, перед первым \n.

std::getline берёт символы до ближайшего перевода строки. Сам перевод строки она забирает из потока, но в результат не кладёт. Сейчас он встретился первым, поэтому имя получилось пустым. Текст Анна Маркова всё ещё ждёт в потоке.

Если имя начинается с новой строки

По условиям формы возраст занимает целую строку, а имя должно начинаться со следующей. После успешного чтения числа пропустим остаток его строки вместе с переводом строки. Для этого у потока есть ignore.

Исправленный main.cpp
C++
#include <iostream>
#include <limits>
#include <string>

int main() {
    int age;
    std::string name;
    if (!(std::cin >> age)) return 1;
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::getline(std::cin, name);
    std::cout << "Имя: [" << name << "]\n";
}
Теперь вывод
TXT
Имя: [Анна Маркова]

ignore останавливается на \n и забирает его. Первый аргумент снимает обычное ограничение по числу пропущенных символов. Поэтому всё работает, даже если после 17 случайно поставили два пробела. Простой вызов cin.ignore() убирает всего один символ — при таком вводе он потратится на первый пробел.

Когда удобно написать std::ws

Если пустые строки и начальные пробелы у имени по правилам можно пропустить, строка чтения будет короче. Замените вызов getline в первой программе этой строкой:

Чтение имени
C++
std::getline(std::cin >> std::ws, name);

std::ws пропускает все пробельные символы перед первым словом. Поэтому Анна Маркова останется целиком, включая пробел между именем и фамилией. Но если пустая строка означает «имя не указано», программа пропустит её и будет ждать текст дальше. Для такой формы берите вариант с ignore.

Проверьте себя на другом формате

Теперь возраст и имя находятся в одной строке: 17 Анна Маркова. Что сделает вариант с ignore? Он выбросит и пробел, и всё имя до конца строки. Здесь подходит std::ws, если разделительные пробелы не нужны. А когда важен каждый символ после числа, обычный getline прочитает остаток той же строки вместе с первым пробелом.

Перед следующим вызовом getline задайте один вопрос: «С какого символа я хочу начать чтение?» Ответ подскажет, нужно ли убрать остаток строки, пропустить пробелы или читать сразу.

Источники

  1. Рабочий проект стандарта C++: чтение строки [Электронный ресурс]. — URL: https://eel.is/c++draft/string.io (дата обращения: 09.11.2026).
  2. Рабочий проект стандарта C++: функция ignore [Электронный ресурс]. — URL: https://eel.is/c++draft/istream.unformatted (дата обращения: 09.11.2026).
  3. Рабочий проект стандарта C++: манипулятор ws [Электронный ресурс]. — URL: https://eel.is/c++draft/istream.manip (дата обращения: 09.11.2026).
C++Ввод и вывод