Как очистить буфер ввода c
Перейти к содержимому

Как очистить буфер ввода c

  • автор:

Как очистить буфер ввода c

использую в тестовом примере ввод с клавиатуры с помощью scanf

 printf("введите нужное:\n"); while (GoGo != 'q') < switch (GoGo): < case 's': . case '1': . > printf("введите нужное:\n"); >

читаю чары как %c, строку как %s, целое как %i, double как %lf

в общем, во внутреннем switch строка

 printf("введите нужное:\n");

выводится ДВАЖДЫ .

т.е. видимо что-то остается в буфере!! сделал

 fflush(stdin);

перед строкой printf — никакой разницы.

как победить сие безобразие . btw, под VC++6 и mingw все отлично.

P.S. компилятор g++/Linux.

—————
c уважением, мохнато-полосатый kot—
Re: про scanf и очистку буфера

От: kot—
Дата: 15.05.07 10:54
Оценка:

Здравствуйте, kot—, Вы писали:

 printf("введите нужное:\n"); while (GoGo != 'q') < switch (GoGo): < case 's': . case '1': . > printf("введите нужное:\n"); scanf("%c",&Gogo); >

да, забыл дописать — scanf после printf, но думаю и так ясен вопрос.

—————
c уважением, мохнато-полосатый kot—
Re: про scanf и очистку буфера

От: Dair https://dair.spb.ru
Дата: 15.05.07 11:17
Оценка:

K>вроде такого

K>

K> printf("введите нужное:\n"); K> while (GoGo != 'q') K> < K>switch (GoGo): K> < K>case 's': . K> case '1': . K> > K> printf("введите нужное:\n"); K> scanf("%c",&Gogo); K> > K>

K> как победить сие безобразие . btw, под VC++6 и mingw все отлично.

Я их вижу два (выделил в коде)
Удивлён

Может, как-нибудь так:

do < printf( "введите нужное:\n" ); scanf( "%c", &GoGo ); switch( GoGo ) < case 's': . case '1': . > > while( GoGo != 'q' );

Re[2]: про scanf и очистку буфера

От: Cruser
Дата: 15.05.07 11:21
Оценка:

K> да, забыл дописать — scanf после printf, но думаю и так ясен вопрос.

scanf() считывает только символ ‘\r’, а вот символ ‘\n’ он на следующей итерации заглатывает

Re[3]: про scanf и очистку буфера

От: kot—
Дата: 15.05.07 11:28
Оценка:

Здравствуйте, Cruser, Вы писали:

K>> да, забыл дописать — scanf после printf, но думаю и так ясен вопрос.

C> scanf() считывает только символ ‘\r’, а вот символ ‘\n’ он на следующей итерации заглатывает

хм. но разве fflush(stdin) буфер от него не чистит ?

—————
c уважением, мохнато-полосатый kot—
Re[4]: про scanf и очистку буфера

От: Cruser
Дата: 15.05.07 13:07
Оценка:

Здравствуйте, kot—, Вы писали:

K>Здравствуйте, Cruser, Вы писали:

K>>> да, забыл дописать — scanf после printf, но думаю и так ясен вопрос.

C>> scanf() считывает только символ ‘\r’, а вот символ ‘\n’ он на следующей итерации заглатывает

K> хм. но разве fflush(stdin) буфер от него не чистит ?

Чистит, с ним у меня scanf() нормально работает.

Re[4]: про scanf и очистку буфера

От: night beast
Дата: 16.05.07 05:37
Оценка:

Здравствуйте, kot—, Вы писали:

K>>> да, забыл дописать — scanf после printf, но думаю и так ясен вопрос.

C>> scanf() считывает только символ ‘\r’, а вот символ ‘\n’ он на следующей итерации заглатывает

K> хм. но разве fflush(stdin) буфер от него не чистит ?

если не ошибаюсь, fflush применим только для потоков вывода.

Сброс буфера ввода

Собственно, вопрос в том, как сделать так, чтобы при вводе символов, коих больше, чем считывает fgets , они не оставались в, мм, буфере? Иначе я ввожу ~100 символов при первом приглашении ввода, он читает 65 штук, остальное отправляет сразу во второй fgets , и, естественно, так быть не должно. Вот тут fflush(stdin) , но эффекта нет: всё равно отправляет «остаток» во второй fgets . С _flushall(); немного иначе: он срабатывает, но выборочно, раз через два, почему — не могу понять. Компилятор: «Оптимизирующий компилятор Майкрософт С/С++ версии 19.00.23506«

/GS /analyze- /W3 /Zc:wchar_t /ZI /Gm /Od /sdl /Fd"Debug\vc140.pdb" /Zc:inline /fp:precise /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /RTC1 /Gd /Oy- /MDd /Fa"Debug\" /EHsc /nologo /Fo"Debug\" /Fp"Debug\ConsoleApplication2.pch" 

Отслеживать

6,651 6 6 золотых знаков 30 30 серебряных знаков 52 52 бронзовых знака

Что такое буфер ввода/вывода?

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

  • Вопрос задан более трёх лет назад
  • 3533 просмотра

Комментировать
Решения вопроса 1

Anton3

Для ввода-вывода в консоль или файл программа делает системные вызовы чтения или записи. Не вдаваясь в подробности, скажу, что они дорогие. Если ты читаешь по одному символу из std::cin , то это будет работать жутко медленно.

Что происходит на практике: происходит один системный вызов, cin читает в свой внутренний буфер сразу, скажем, 4096 байт, и потом отдаёт тебе из буфера по одному символу, которые ты у него запрашиваешь. Нетрудно заметить, что работать это будет (в моём примере) где-то в 4096 раз быстрее.

Зачем очищать. Пока ты не сделал flush , то, что ты вывел в поток, находится в буфере. cout ждёт, пока ты докинешь ему ещё байтиков, чтобы вывести всё потом большим куском. Если же ты хочешь, чтобы вывод произошёл прямо сейчас, то нужен flush .

Как чистить поток после неправильного ввода со sca 0

Fatal написал 14 июля 2004 года в 22:23 (10435 просмотров) Ведет себя как мужчина; открыл 123 темы в форуме, оставил 484 комментария на сайте.

Как чистить стандартный поток вывода, после неправильного введенного символо с помощью функции scanf? с помощью fflush не получается — это работает только в консоли под Window/Dos. Я пробую писать программы под FreeBSD, а там ничерта не работает fflush или ведет себя по другому. Почему так? Я пробовал также с функцией clearerr(stdin), тоже не выходит.

sas 00:02, 15 июля 2004

if ( ferror( stdin ) || feof( stdin ) ) clearerr( stdin );

else rewind( stdin );

PS code was not compiled and so may have errors

Fatal 22:42, 15 июля 2004

Так почему же в FreeBSD не работает fflush? Почему он не очищает поток?

sas 00:03, 16 июля 2004

1 На сколько я знаю fflush stdin не может гарантированно работать по стадартам

2 Он не очищает аппаратных буферов

3 scanf имеет собственный буфер

Можно и по другому чистить:

что означает пропусти весь инпут до ‘\n’

Я не знаю что более портабельно — rewind или очистка буфера. Пока я испльзую rewind. На всех «моих» платформах он работает

Кстати scanf семейство я не люблю. Гораздо более гибко читать строку и парзить самому, т.к. например в Вашем коде не будет работать даже строка, где будет более одного целого.

После моего ответа посмотрел в стандарте о том что лучше использовать rewind или очистку буфера и нашел, что rewind НЕ ГОДИТСЯ для использования! По стандарту он может применятся только к файлам, которые поддерживают позционирование. stdin НЕ ПОДДЕРЖИВАЕТ его!

Правильнее использовать scanf очистку! Кстати предидущее решение НЕ будет работать если входная строка содержит более одного ‘\n’ В этом случае надо вызвать еще один scanf т.е.

scanf( «%*c» ); /* уберем оставшиеся ‘\n’ */

Вот теперь я надеюсь все

Fatal 22:55, 16 июля 2004

1. fflush — это стаднартная функция ANSI и она обязана работать по стандартам!

2. к сожалению я не понимаю, что такое аппаратный буфер …

3. scanf выводит в стандартный поток вывода — stdin

scanf( «%*[^\n]» ) — эта строка будет пропускать и оставлять их в stdin? Если да, то это не годится, т.к. это будет влиять на другие функции, которые используют stdin. К примеру:

char s[1000], b[1000];

scanf(«%s»,&s);/*ввести слова через пробелы и нажать в конце Enter: ыаыва ываыва ываыв Enter*/

/*сканф затяпает только одно слово до пробела, а остальные оставит в буфере stdin*/

fgets(b,999,stdin);/*эта функция не будет ожидать ввода, он съест все что осталось после сканфа в stdin*/

В man описана еще одна функция (не понятно почему она объявлена в stdio — это ведь не стандартная функция) int fpurge(FILE*). Так вот если ее подставить вместо fflush(stdin), т.е. fpurge(stdin), то все будет чики-пуки, что на местно жаргоне означает хорошо.

Функция fflush возвращает код ошибки 9 (Bad file descriptor), а функция fpurge возвращает 0 (OK). Не понятно почему fflush не понравился дескриптор стандартного вывода?!

И еще я заметил, что fputs(«Hello!\n»,stdin) тоже не фурычит. Т.е. если после этого вызова написать fgets он будет ожидать ввода, хотя по логике он должен взять из буфера stdin. В чем может быть проблема, может надо открыть заново stdin. Но как это сделать? Чертовщина какая-то! Конечно можно fflush заменить на fpurge(File*), но нужна стандартная функция, которая бы обеспечивала переносимость. Конечно вывернуться можно, но все же хочется по-нормальному. Это глюк BSD?!

У кого есть возможность попробовать в Linux кусок кода, который я привел ниже, попробуйте, пожалуйста. И напишите будет ли нормально работать fflush в линуксе.

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

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