По какой-то причине в моей программе, когда я достигаю определенного места, я должен нажать Войти дважды, чтобы получить его для отправки. Я добавил clear, чтобы он не пропускал ввод, и ignore (), чтобы он не содержал лишних символов в буфере. Я ввожу свой ввод, а затем он падает на новую строку, я нажимаю Войти снова, и он вводит ввод и продолжает программу без проблем, но мне интересно, почему. Вот фрагмент кода:
cin.ignore();
cout << "Enter Student Major (ex. COSC): ";
cin.getline(student.major, 6);
for(int i = 0; i < sizeof(student.major); i++)
student.major[i] = toupper(student.major[i]);
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
Какие-либо предложения?
Мне кажется, что вы бросаете слишком много cin.ignore()
вокруг, не зная точно, зачем они нужны и когда их туда ставить.
Есть два общих обстоятельства, когда cin.ignore()
необходим для «правильной работы ввода»:
В обоих случаях вы хотите избавиться от ложных символов из входного буфера; если такого символа нет (что, вероятно, происходит в вашей программе), cin.ignore()
приостановит выполнение и дождется пользовательского ввода — в конце концов, вы попросили его игнорировать некоторые символы, и, черт побери, он будет подчиняться его приказам.
(хотя ignore()
по умолчанию «съедает» только один символ, каким бы он ни был, выполнение приостанавливается, пока не будет найден символ новой строки, потому что по умолчанию cin
буферизована строка — новый ввод не проверяется до получения новой строки)
cin.ignore()
звонки часто необходимы, если вы выполняете неформатированный ввод операция (как getline
) после выполнения форматированный ввод операция (т.е. с использованием >>
оператор).
Это происходит потому, что >>
оператор оставляет новую строку во входном буфере; это не проблема, если вы выполняете только отформатированные операции ввода (по умолчанию они пропускают все пробелы перед попыткой интерпретировать ввод), но это проблема, если впоследствии вы делаете неформатированный ввод: getline
по умолчанию читает до тех пор, пока не найдет новую строку, поэтому оставленная «ложная новая строка» немедленно прекратит чтение.
Итак, здесь вы обычно будете звонить cin.ignore(...)
вызовите, чтобы избавиться от новой строки сразу после последней отформатированной операции ввода, которую вы выполняете подряд, гарантируя, что буфер ввода пуст. После этого вы можете позвонить getline
прямо без страха, зная, что вы оставили буфер пустым.
Вместо этого это плохая идея до любой getline
, как вы, кажется, делаете в своем коде, так как могут быть пути кода, которые приводят к этому getline
с чистым входным буфером, поэтому ignore
звонок будет заблокирован.
когда istream
сталкивается с ошибкой в отформатированных операциях ввода, оставляет «плохие» символы в буфере, поэтому, если вы повторите попытку, вы застрянете бесконечно, поскольку нарушители все еще там. Обычный clear()/ignore()
на помощь приходит идиома, удаляющая всю ошибочную строку из буфера ввода.
Опять же, вы не ставите clear()/ignore()
последовательность в произвольном порядке, но только после того, как вы получите ошибку ввода от форматированной операции ввода (которая устанавливает бит бит потока).
Теперь, кроме этих случаев, редко cin.ignore()
(если вы на самом деле не хотите пропустить символы); не распространяйте его случайным образом «просто для безопасности», иначе вы столкнетесь с проблемой, которую вы описали.
Ответ можно найти Вот.
Извлечение заканчивается, когда n символов были извлечены и отброшены, или когда найден разделитель символов, в зависимости от того, что произойдет раньше. В последнем случае сам символ-разделитель также извлекается.
Так что в вашем случае программа не будет продолжаться до '\n'
персонаж получен.
Я думаю cin.ignore(numeric_limits<streamsize>::max(), '\n');
ожидает \n
на входе, и он не находит его, поэтому вы должны нажать Войти еще раз, чтобы найти его.