Подтвердить что ты не робот

Когда и зачем мне нужно использовать cin.ignore() в С++?

Я написал очень базовую программу на С++, которая попросила пользователя ввести число, а затем строку. К моему удивлению, при запуске программы он никогда не останавливался, чтобы попросить строку. Он просто пропустил это. После некоторого чтения в StackOverflow я узнал, что мне нужно добавить строку, в которой говорится:

cin.ignore(256, '\n');

перед строкой, которая получает строковый ввод. Добавив это, проблема была решена и запустила работу программы. Мой вопрос в том, почему С++ нуждается в этой строке cin.ignore() и как я могу предсказать, когда мне нужно будет использовать cin.ignore()?

Вот программа, которую я написал:

#include <iostream>
#include <string>

using namespace std;

int main()
{
    double num;
    string mystr;

    cout << "Please enter a number: " << "\n";
    cin >> num;
    cout << "Your number is: " << num << "\n";
    cin.ignore(256, '\n'); // Why do I need this line?
    cout << "Please enter your name: \n";
    getline (cin, mystr);
    cout << "So your name is " << mystr << "?\n";
    cout << "Have a nice day. \n";

}
4b9b3361

Ответ 1

Игнорирование - это именно то, что подразумевает название.

Он не "выбрасывает" то, что вам не нужно, он игнорирует количество символов, которые вы указываете при его вызове, вплоть до char, который вы указываете в качестве точки останова.

Он работает как с входными, так и с выходными буферами.

По существу, для операторов std::cin, которые вы используете игнорировать перед вызовом getline, потому что, когда пользователь вводит что-то с std::cin, они нажимают enter и a '\n' char попадает в cin буфер. Затем, если вы используете getline, он получает новую строку char вместо нужной строки. Таким образом, вы делаете std::cin.ignore(1000,'\n') и должны очистить буфер до нужной строки. (1000 помещается туда, чтобы пропустить определенное количество символов до указанной точки прерывания, в этом случае символ \n символа новой строки.)

Ответ 2

Ты думаешь об этом неправильно. Вы каждый раз думаете логически, когда используются cin или getline. Ex. Сначала попросите номер, затем попросите имя. Это неправильный способ думать о cin. Таким образом, вы сталкиваетесь с условием гонки, потому что считаете, что поток очищается каждый раз, когда вы запрашиваете ввод.

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

void main(void)
{
    double num;
    string mystr;

    cin >> num;
    getline(cin, mystr);

    cout << "num=" << num << ",mystr=\'" << mystr << "\'" << endl;
}

В вышесказанном вы думаете: "Сначала получите номер". Таким образом, вы вводите 123 нажмите enter, и ваш выход будет num=123,mystr=''. Почему это? Это потому, что в потоке вы 123\n, а 123 анализируется в переменной num, а \n все еще находится в потоке. Чтение документа для функции getline по умолчанию будет выглядеть в istream до тех пор, пока не встретится \n. В этом примере, поскольку \n находится в потоке, похоже, что он "пропустил" его, но он работал правильно.

Для выполнения вышеописанного вы должны ввести 123Hello World, который будет правильно выводить num=123,mystr='Hello World'. Это, или вы помещаете cin.ignore между cin и getline, чтобы он разбился на логические шаги, которые вы ожидаете.

Вот почему вам нужна команда ignore. Потому что вы думаете об этом в логических шагах, а не в форме потока, чтобы вы столкнулись с состоянием гонки.

Возьмите другой пример кода, который обычно встречается в школах:

void main(void)
{
    int age;
    string firstName;
    string lastName;

    cout << "First name: ";
    cin >> firstName;

    cout << "Last name: ";
    cin >> lastName;

    cout << "Age: ";
    cin >> age;

    cout << "Hello " << firstName << " " << lastName << "! You are " << age << " years old!" << endl;
}

Вышеизложенное представляется логичным. Сначала спросите имя, фамилию, возраст. Итак, если вы сделали John введите, затем Doe введите, затем 19 введите, приложение выполняет каждый логический шаг. Если вы думаете об этом в "потоках", вы можете просто ввести John Doe 19 в вопрос "Имя:", и он тоже сработает и, похоже, пропустит оставшиеся вопросы. Чтобы вышеперечисленное работало в логических шагах, вам потребуется ignore оставшийся поток для каждого логического разрыва в вопросах.

Не забудьте вспомнить свой ввод программы, поскольку он читает "поток", а не логически. Каждый раз, когда вы вызываете cin, он считывается из потока. Это создает довольно ошибочное приложение, если пользователь вводит неверный ввод. Например, если вы ввели символ, где ожидается cin >> double, приложение будет обрабатывать довольно (казалось бы) странный вывод.

Ответ 3

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

Очень распространенный случай использования - это безопасное игнорирование символов новой строки, поскольку cin иногда оставляет символы новой строки, которые вам придется переходить, чтобы перейти к следующей строке ввода.

Короче говоря, это дает вам гибкость при обработке потока ввода.

Ответ 4

Короткий ответ

Зачем? Потому что во входном потоке остаются пробелы (возврат каретки, табуляция, пробелы, перевод строки).

Когда? Когда вы используете какую-то функцию, которая сама по себе не игнорирует начальные пробелы. Cin по умолчанию игнорирует и удаляет начальные пробелы, но getline не игнорирует ведущие пробелы самостоятельно.

Теперь подробный ответ.

Все, что вы вводите в консоль, читается из стандартного потока stdin. Когда вы вводите что-то, скажем 256 в вашем случае и нажимаете ввод, содержимое потока становится 256\n. Теперь cin берет 256 и удаляет его из потока, а \n все еще остается в потоке. Теперь, когда вы введете свое имя, скажем, Raddicus, новое содержимое потока будет \nRaddicus.

Теперь здесь идет улов. Когда вы пытаетесь прочитать строку с использованием getline, если в качестве третьего аргумента не указан какой-либо разделитель, getline по умолчанию считывает символ новой строки и удаляет символ новой строки из потока. Поэтому при вызове новой строки getline читает и отбрасывает \n из потока, в результате чего в mystr читается пустая строка, которая выглядит как пропущенная getline (но это не так), поскольку в потоке уже была новая строка, getline не запрашивает вход, как он уже прочитал, что он должен был прочитать.

Теперь, как cin.ignore помогает здесь?

В соответствии с документацией игнорирования выписка из cplusplus.com -

istream & ignore (размер потока n = 1, int delim = EOF);

Извлекает символы из входной последовательности и отбрасывает их до тех пор, пока не будет извлечено n символов или один из них не будет равен delim.

Функция также прекращает извлечение символов, если достигнут конец файла. Если это достигается преждевременно (перед извлечением n символов или поиском разделителя), функция устанавливает флаг eofbit.

Итак, cin.ignore(256, '\n'); , игнорирует первые 256 символов или все символы, пока не встретит разделитель (здесь\n в вашем случае), в зависимости от того, что произойдет первым (здесь\n - первый символ, поэтому он игнорирует, пока не встретится \n).

Для справки: если вы точно не знаете, сколько символов пропустить, и ваша единственная цель - очистить поток, чтобы подготовиться к чтению строки, используя getline или cin, вы должны использовать cin.ignore(numeric_limits<streamsize>::max(),'\n').

Краткое объяснение: он игнорирует символы, равные максимальному размеру потока или до тех пор, пока не встретится '\n', в зависимости от того, что произойдет раньше.

Ответ 5

Функция игнорирования используется для пропуска (отбрасывания/выброса) символов во входном потоке. Игнорировать файл связан с файлом istream. Рассмотрим функцию, приведенную ниже ex: cin.ignore(120, '/n'); конкретная функция пропускает следующий 120 входных символов или пропускает символы до тех пор, пока не будет прочитан символ новой строки.

Ответ 6

Это не ответ.

Я тоже пробовал что-то подобное, но мой код не работает должным образом. Он рекурсивно зацикливается. Я использовал функцию игнорирования, но не могу ее избежать. Прикрепили фрагмент кода и снимок проблемы.

cout<<"\n\n\t\tEnter the details : \n";
    for( ;ch=='y' ; )
    {
        cout<<"\n\t\tEnter the ID : ";
        cin>>eid;
        cout<<"\n\t\tEnter the Name : ";
        getline(cin, ename);
        cin.ignore();
        cout<<"\n\t\tEnter the Gross Revenue : ";
        cin>>esal;
        obj.insert(eid, esal, ename);
        cout<<"\n\t\t\tNew Entries ? Y/N ";
        cin>>ch;
    }
    cout<<"\n\n\t\t\t\tPress Any Key to Continue......";
    getch();

Снимок, показывающий проблему

Ответ 7

Лучше использовать scanf ("% [^\n]", str) в c++, чем cin.ignore() после cin >> statement.Чтобы сделать это сначала, вы должны включить заголовок <cstdio>.