C очистка буфера ввода

Я одна часть моего приложения я использовал Sleep(5000) (Мне нужно подождать 5 сек)

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

Как я могу очистить буфер после сна?

Я старался cin.clear() а также setbuf(stdin, NULL) но они не могут очистить буфер, если в нем более одного символа.

Решение

Две функции, которые вы используете, не имеют ожидаемого эффекта:

  1. clear() не влияет на буфер вообще, а очищает флаги ошибок. То есть, если произошло неудачное чтение, устанавливается флаг ( std::ios_base::failbit ). Пока установлен любой флаг ошибки (есть еще несколько), поток не будет пытаться что-либо прочитать.
  2. setbuf(0, 0) влияет на то, что внутренний буфер потока не существует (вызовы с ненулевыми значениями имеют значение, определяемое реализацией, которое обычно «ничего не делает»). Как правило, это плохая идея, потому что это приводит к очень медленным потокам. Кроме того, клавиши, нажимаемые пользователем, вероятно, в любом случае сохраняются не в этом буфере, а во входном буфере операционной системы, пока они не будут отправлены в приложение (существуют платформо-зависимые способы отключения входного буфера операционной системы, например, на POSIX вы использовал tcsetattr() перевести вход в неканонический режим).

В любом случае отсутствие буфера на самом деле вам не поможет: пользователь вполне мог набрать правильный ввод. Правильный подход состоит в том, чтобы попытаться прочитать доступный ввод и, в случае неудачи, избавиться от оскорбительного символа (или символов). С этой целью вы попытаетесь прочитать входные данные, и если это не удастся, вы бы clear() поток и ignore() один или несколько символов (в этом примере игнорируется вся строка; вызов ignore() без параметров просто игнорировать один символ):

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

Другие решения

Самый простой способ очистить буфер ввода с клавиатуры

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

заголовочный файл, необходимый для этого conio.h

Кажется, это работает для Windows 10, скомпилированной с Code :: Blocks:

Затем вызывается откуда необходимо в вашем C ++ скрипте.

У меня есть следующая программа:

Как пояснил автор вышеприведенного кода: Программа не будет работать должным образом, потому что в строке 1, когда пользователь нажимает Enter, он оставит в буфере входного буфера 2 символ: Enter key (ASCII code 13) и
(ASCII code 10) . Поэтому в строке 2 он будет читать
и не будет ждать ввода пользователем символа.

Читайте также:  Принудительная установка gvlk windows 10

Хорошо, я понял. Но мой первый вопрос: почему второй getchar() ( ch2 = getchar(); ) не читает символ Enter key (13) , а не
?

Далее автор предложил два способа решения таких проблем:

напишите такую ​​функцию:

Этот код действительно работал. Но я не могу объяснить, как это работает? Потому что в выражении while мы используем getchar() != ‘
‘ , то есть читаем любой отдельный символ, кроме ‘
‘ ? если да, то во входном буфере остается символ ‘
‘ ?

Программа не будет работать должным образом, потому что в строке 1, когда пользователь нажимает Enter, он оставит в буфере входного сигнала 2 символ: введите ключ (код ASCII 13) и
(код ASCII 10). Поэтому в строке 2 он будет читать
и не будет ждать ввода пользователем символа.

Поведение, которое вы видите в строке 2, является правильным, но это не совсем правильное объяснение. В потоках текстового режима не имеет значения, какие линии вы используете для своей платформы (возврат каретки (0x0D) + linefeed (0x0A), голый CR или голый LF). Библиотека времени выполнения C позаботится об этом для вас: ваша программа увидит только ‘
‘ для новых строк.

Если вы набрали символ и нажали enter, тогда этот входной символ будет считаться строкой 1, а затем ‘
‘ будет считаться строкой 2. См., Что я использую scanf %c для чтения ответа Y/N, но более поздний ввод пропускается. из справочника comp.lang.c.

Что касается предлагаемых решений, см. (Опять же из часто задаваемых вопросов по comp.lang.c):

которые в основном утверждают, что единственный переносимый подход:

Ваш цикл getchar() != ‘
‘ работает, потому что как только вы вызываете getchar() , возвращаемый символ уже был удален из входного потока.

Кроме того, я чувствую себя обязанным препятствовать вам полностью использовать scanf : почему все говорят, что не использовать scanf ? Что я должен использовать вместо этого?

Что такое буфер?
Область временного хранения называется буфером. Все стандартные устройства ввода и вывода содержат буфер ввода и вывода. В стандартном C / C ++ потоки буферизуются, например, в случае стандартного ввода, когда мы нажимаем клавишу на клавиатуре, она не отправляется в вашу программу, а буферизируется операционной системой до тех пор, пока время не будет выделено для этого. программа.

Читайте также:  Iphone в режиме восстановления что делать


Как это влияет на программирование?

В некоторых случаях вам может потребоваться очистить ненужный буфер, чтобы получить следующий ввод в желаемом контейнере, а не в буфере предыдущей переменной. Например, в случае C после встречи с «scanf ()», если нам нужно ввести массив символов или символ, и в случае C ++, после встречи с оператором «cin», мы требуем ввести массив символов или строку, нам нужно очистить буфер ввода, иначе желаемый ввод будет занят буфером предыдущей переменной, а не нужным контейнером. При нажатии «Enter» (возврат каретки) на экране вывода после первого ввода, поскольку буфер предыдущей переменной был пространство для нового контейнера (как мы его не очищали), программа пропускает следующий ввод контейнера.

В случае программирования C

// C код, чтобы объяснить, почему нет
// очищаем входной буфер
// вызывает нежелательные выходы
#include

// Сканирование ввода от пользователя –

// Сканирование символа от пользователя

// Печать массива символов,

printf ( "%s
" , str);

// Это не печатает

В случае C ++

// C ++ код, объясняющий почему
// не очищаем ввод
// буфер вызывает нежелательное
// выводы
#include
#include

using namespace std;

// Введите ввод от пользователя

// Получить ввод от пользователя –

// Печать строки: это делает

// не печатать строку

В обоих приведенных выше кодах вывод не распечатывается должным образом. Причиной этому является занятый буфер. Символ «/ n» остается там в буфере и читается как следующий ввод.

Как это можно решить?

В случае C:

    Использование «while ((getchar ())! = ‘/ N’); ” : Ввод« while ((getchar ())! = ‘/ N’); »читает символы буфера до конца и отбрасывает их (включая символ новой строки) и использует их после того, как инструкция« scanf () »очищает входной буфер и позволяет вводить в нужный контейнер.

// C код, объясняющий, почему добавление
// "while ((getchar ())! = ‘/ n’);"
// после оператора "scanf ()"
// очищает входной буфер
#include

// сканировать ввод от пользователя –

// сбрасывает стандартный ввод

// (очищает входной буфер)

while (( getchar ()) != ‘
‘ );

// сканируем символ от пользователя –

// Печать массива символов,

printf ( "%s
" , str);

// Печать символа a: It

// на этот раз напечатаем ‘a’

  1. Использование «fflush (stdin)» : ввод «fflush (stdin)» после оператора «scanf ()» также очищает входной буфер, но его использование исключается и называется «неопределенным» для входного потока согласно C ++ 11 стандартов.
Читайте также:  Как изменить название в инстаграме

В случае C ++:

    Использование «cin.ignore (numeric_limits :: max (), ‘/ n’); » : — Ввод« cin.ignore (numeric_limits :: max (), ‘/ n’); »после оператора« cin »отбрасывает все во входном потоке, включая символ новой строки.

// C ++ код, чтобы объяснить, как
// "cin.ignore (numeric_limits
// :: max (), ‘/ n’); "
// отбрасывает входной буфер
#include

// для numeric_limits
#include

using namespace std;

// Введите ввод от пользователя

// отбрасывает входной буфер

cin.ignore(numeric_limits ::max(), ‘
‘ );

// Получить ввод от пользователя –

// Печать строки: это

// сейчас напечатает строку

    Использование «cin.sync ()»: ввод «cin.sync ()» после оператора «cin» отбрасывает все, что осталось в буфере. Хотя «cin.sync ()» работает не во всех реализациях (в соответствии со стандартами C ++ 11 и выше).

// C ++ код, объясняющий, как "cin.sync ();"
// отбрасывает входной буфер
#include
#include
#include

using namespace std;

// Введите ввод от пользователя

// Сбрасывает входной буфер

// Получить ввод от пользователя –

// Печать строки – это

// сейчас напечатает строку

    Использование «cin >> ws»: ввод «cin >> ws» после оператора «cin» указывает компилятору игнорировать буфер, а также отбрасывать все пробелы перед фактическим содержимым строки или символьного массива.

// C ++ код, объясняющий, как "cin >> ws"
// сбрасывает входной буфер вместе с
// начальные пробелы строки

using namespace std;

// Введите ввод от пользователя –

// Сбрасывает входной буфер и

// начальные пробелы строки

// Получить ввод от пользователя –

// печатает 4 и GeeksforGeeks:

// выполнит print a и s

Эта статья предоставлена Манджитом Сингхом . Если вам нравится GeeksforGeeks и вы хотите внести свой вклад, вы также можете написать статью и отправить ее по почте на contrib@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock detector