Использование getline (cin, s) после cin - PullRequest
37 голосов
/ 21 апреля 2011

Мне нужна следующая программа, чтобы взять всю строку ввода пользователя и поместить ее в имена строк:

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

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

getline(cin, names);

С помощью команды cin >> number перед командой getline() (что яугадывание - проблема), это не позволит мне вводить имена.Почему?

Я что-то слышал о команде cin.clear(), но я понятия не имею, как это работает или почему это даже необходимо.

Ответы [ 14 ]

19 голосов
/ 08 июля 2012
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 голосов
/ 21 апреля 2011

Другой способ сделать это - поставить

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

после вашего cin>>number;, чтобы полностью очистить буфер ввода (отвергая все лишние символы, пока не будет найдена новая строка). Вам нужно #include <limits>, чтобы получить метод max().

10 голосов
/ 21 апреля 2011
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);
}

В приведенном выше коде этот бит ...

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

... проверяет оставшуюся строку ввода после того, как число содержит только пробел.

Почему бы и нетпросто используйте ignore?

Это довольно многословно, поэтому использование ignore в потоке после >> x - это часто рекомендуемый альтернативный способ отбросить контент до следующей новой строки, но он рискует выбросить незаполненные пробелысодержание и при этом, пропуская поврежденные данные в файле.Вы можете или не можете заботиться, в зависимости от того, является ли содержимое файла надежным, насколько важно избегать обработки поврежденных данных и т. Д.

Так когда бы вы использовали очистку и игнорирование?

Итак,std::cin.clear()std::cin.igore()) не требуется для этого, но полезен для устранения состояния ошибки.Например, если вы хотите дать пользователю много шансов ввести действительный номер.

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

Разве это не может быть проще с пропусками или аналогичными?

Еще одна простая, но недоделанная альтернатива ignore для вашего первоначального требования - использовать std::skipws, чтобы пропустить любое количествопробела перед чтением строк ...

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

... но если он получит ввод наподобие "1E6" (например, какой-то ученый пытается ввести 1 000 000, но C ++ поддерживает только эти обозначения для чисел с плавающей запятой)Если вы не согласитесь с этим, вы получите number, установленное на 1, и E6, прочитанное как первое значение name.Отдельно, если у вас есть действительный номер, за которым следуют одна или несколько пустых строк, эти строки будут игнорироваться.

9 голосов
/ 21 апреля 2011

Попробуйте:

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;

В качестве альтернативы.Если вы знаете, что номер и имена всегда будут в разных строках.

cin >> number;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
std::getline(cin, names);
5 голосов
/ 16 апреля 2015

Вы можете использовать std :: ws для извлечения любых пробельных символов во входном буфере перед использованием getline.Заголовок для std :: ws является sstream.

cout << "Enter the number: ";
int number;
cin >> number;
cout << "Enter names: ";
string names;
cin>>ws;
getline(cin, names);
2 голосов
/ 09 декабря 2018

Попробуйте cin.ignore (), когда вы используете cin перед функцией getline ()

void inputstu(){
    cout << "Enter roll Number:";
    cin >> roll_no;
    cin.ignore(); //ignore the withspace and enter key
    cout << "Enter name:";
    getline(cin, stu_name);
}
1 голос
/ 19 марта 2018
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

это самоочевидно, в потоке, который использует cin >> number, остается \ n, который присваивается именам при первом его использовании. Повторное использование getline пишет правильное значение сейчас.

1 голос
/ 12 сентября 2016

Или вы можете очистить буфер ввода, чтобы прочитать строку

fflush (STDIN)

определено в заголовке stdio.h .

Этот код работает ..

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

cout << "Enter names: ";
string names;
fflush(stdin);  //FLUSHING STDIN
getline(cin, names);
0 голосов
/ 03 апреля 2019
cout << "Enter the number: ";

int number;
cin >> number;

getc(stdin);  //you need add this line 

cout << "Enter names: ";

string names;

getline(cin, names);
0 голосов
/ 09 ноября 2017

Концептуально, я думаю, вы хотите, чтобы каждый ответ был аккуратно в одну строку. Так почему бы тебе не попробовать это?

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

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

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

...