Fflush stdin что это
fflush
Записывает содержимое потока на диск.
Синтаксис
Параметры
вышестоящий
Указатель на структуру FILE.
Возвращаемое значение
fflush возвращает 0, если буфер был успешно сброшен. Кроме того, значение 0 также возвращается в случаях, когда указанный поток не имеет буфера или открыт только для чтения. Возвращаемое значение EOF обозначает ошибку.
Если fflush возвращает EOF, данные могут быть потеряны из-за ошибки записи. При настройке критического обработчика ошибок можно безопасным образом отключить буферизацию с помощью функции setvbuf или использовать подпрограммы ввода-вывода низкого уровня, такие как _open, _closeи _Write вместо функций потокового ввода-вывода.
Комментарии
Функция fflush очищает потокпотока. Если поток был открыт в режиме записи, а также если он был открыт в режиме обновления и последней была выполнена операция записи, содержимое буфера потока записывается в базовый файл или на базовое устройство, после чего буфер очищается. Если поток был открыт в режиме чтения или поток не содержит буфер, вызов fflush не оказывает никакого влияния и сохраняется любой буфер. Вызов fflush инвертирует результат любого ранее вызова метода ungetc для потока. После вызова поток остается открытым.
Если Stream имеет значение NULL, поведение аналогично вызову fflush для каждого открытого потока. Выполняется запись на диск всех потоков, открытых в режиме записи, а также всех потоков в режиме обновления, для которых последней была выполнена операция записи. Вызов не влияет на другие потоки.
Дополнительные сведения об управлении возможностью фиксации на диск см. в разделах Потоковый ввод-вывод, fopen и _fdopen.
Функция блокирует вызывающий поток, поэтому она потокобезопасна. Сведения о версии без блокировки см. в разделе _fflush_nolock.
По умолчанию глобальное состояние этой функции ограничивается приложением. Чтобы изменить это, см. раздел глобальное состояние в CRT.
Требования
Дополнительные сведения о совместимости см. в статье Compatibility.
Использование fflush(stdin)
Так быстрый поиск Google для fflush(stdin) для очистки входного буфера показывает многочисленные веб-сайты предупреждение против его использования. И все же именно так мой профессор CS учил класс делать это.
4 ответов
Simple: это неопределенное поведение, так как fflush предназначен для вызова в выходном потоке. Это выдержка из стандарта C:
ostream указывает на выходной поток или поток обновлений, в котором больше всего недавняя операция не была входной, функция fflush вызывает любые неписаные данные для этого потока, который будет доставлен к среде должно быть написано в файл; в противном случае поведение есть не определено.
Так что это не вопрос» насколько плохо » это. fflush(stdin) is явно неправильно и нельзя им пользоваться, никогда!—12—>.
стандартный C и POSIX оставить fflush(stdin) как неопределенное поведение
на POSIX C и C++ стандарты fflush() явно указать, что поведение не определено, но ни один из них не мешает системе определить его.
ISO / IEC 9899: 2011-стандарт C11-говорит:
§7.21.5.2 функция fflush
¶2 If stream указывает на выходной поток или поток обновления, в котором последняя операция не была введена, fflush функция заставляет любые неписаные данные для этого потока доставляться в среду хоста, чтобы быть записанными в файл; в противном случае поведение не определено.
POSIX в основном ссылается на стандарт C, но он отмечает этот текст как расширение C.
обратите внимание, что терминалы не способны искать; ни трубы, ни розетки.
Microsoft определяет поведение fflush(stdin)
Microsoft и среда выполнения Visual Studio определяет определение поведения fflush() на входном потоке.
если поток открыт для ввода, fflush очищает содержимое буфера.
Cygwin является примером довольно распространенной платформы, на которой fflush(stdin) не очищает входные данные.
документация и практика Linux, похоже, противоречат друг другу
удивительно, Linux номинально документирует поведение fflush(stdin) тоже, и даже определяет его таким же образом (Чудо творивший чудеса.)
для потоков ввода, fflush() отбрасывает все буферизованные данные, которые были извлечены из базового файла, но не были использованы приложением.
я по-прежнему немного озадачен и удивлен документацией Linux, говорящей, что fflush(stdin) будет работать. Несмотря на это предложение, он, как правило, не работает на Linux. Я только что проверил документацию на Ubuntu 14.04 LTS; он говорит, что цитируется выше, но эмпирически это не так работа-по крайней мере, когда входной поток не является искомым устройством, таким как терминал.
demo-fflush.c
пример вывода
этот вывод был получен как на Ubuntu 14.04 LTS, так и на Mac OS X 10.11.2. Насколько я понимаю, это противоречит тому, что говорится в руководстве Linux. Если fflush(stdin) операция работала, мне пришлось бы ввести новую строку текста, чтобы получить информацию для второго getchar() читать.
учитывая, что стандарт POSIX говорит, Может быть, нужна лучшая демонстрация, и документация Linux должна быть уточнена.
demo-fflush2.c
пример вывода
обратите внимание, что /etc/passwd файл для перемещения. На Ubuntu, первая строка выглядит так:
на Mac OS X первые 4 строки выглядят так:
резюме
несмотря на документацию наоборот, он не работает в Linux, когда стандартный ввод является терминалом, но, похоже, следует спецификации POSIX, которая гораздо более тщательно сформулирована. В соответствии с стандарт C, поведение fflush(stdin) неопределено. В POSIX добавляет уточнение, если входной файл для перемещения, которые терминал не. Поведение не совпадает с поведением Microsoft.
POSIX способ отбросить непрочитанный ввод терминала из файлового дескриптора
стандартный способ POSIX отбросьте непрочитанную информацию из дескриптора файла терминала (в отличие от потока файлов типа stdin ) иллюстрируется на как я могу очистить непрочитанные данные из входной очереди tty в системе Unix. Однако это работает ниже стандартного уровня библиотеки ввода-вывода.
согласно стандарту, fflush может использоваться только с выходными буферами и, очевидно, stdin не один. Однако,некоторые компиляторы обеспечивают использование fflush (stdin) в качестве расширения. В этом случае вы можете использовать его, но это повлияет на переносимость, поэтому вы больше не сможете использовать любой совместимый со стандартами компилятор на земле и ожидать тех же результатов.
для потока, открытого для чтения, если файл еще не находится в EOF, и файл один способный искать, смещение файла основного открытого описания файла будет установлено в положение файла потока, и любые символы, выталкиваемые обратно в поток ungetc () или ungetwc (), которые впоследствии не считывались из потока, должны быть dis- карточку (без дальнейшего изменения файла смещение.)
обратите внимание, что терминал не способен искать.
Понимание необходимости fflush() и связанных с ним проблем
Ниже приведен пример кода для вызов fflush():
все, что я знаю о fflush (), это то, что это библиотечная функция, используемая для очистки выходного буфера. Я хочу знать, какова основная цель использования fflush () и где я могу ее использовать. И главным образом мне интересно знать какие проблемы могут быть с вызов fflush().
3 ответов
первое, что нужно учитывать, это fflush определяется только в выходных потоках. Выходной поток собирает «вещи для записи в файл» в большой (ish) буфер, а затем записывает этот буфер в файл. Смысл этого сбора-и-написания-позже заключается в повышении скорости / эффективности двумя способами:
Итак, люди, которые предоставляют вашу библиотеку C и ее реализацию потока stdio, делают все возможное в вашей ОС, чтобы найти «разумно оптимальный» размер блока и собрать все выход в кусок такого размера. (Числа 4096, 8192, 16384 и 65536 часто, сегодня, как правило, хорошие, но это действительно зависит от ОС, а иногда и от базовой файловой системы. Обратите внимание, что» больше «не всегда» лучше»: потоковая передача данных в кусках по четыре гигабайта за раз, вероятно, будет работать хуже, чем делать это в кусках 64 Кбайт, например.)
но это создает проблему. Предположим, вы записываете в файл, например файл журнала со штампами даты и времени и сообщения, и ваш код будет продолжать писать в этот файл позже, но прямо сейчас, он хочет приостановить на некоторое время и давайте лог-анализатор прочитать текущее содержимое файла журнала. Один из вариантов-использовать fclose закрыть файл журнала, а затем fopen открыть его снова, чтобы добавить больше данных. Более эффективно, однако, толкать любые ожидающие сообщения журнала в базовый файл ОС, но держать файл открытым. Вот что!—0—> делает.
буферизация также создает другой проблема. Предположим, ваш код имеет какую-то ошибку, и он иногда падает, но вы не уверены, что он вот-вот рухнет. И предположим, вы что-то написали, и это очень важно!—20—>этой данные выходят в базовую файловую систему. Вы можете позвонить fflush чтобы протолкнуть данные в ОС, прежде чем вызывать потенциально плохой код, который может произойти сбой. (Иногда это хорошо для отладки.)
Ввод и вывод символьных строк в Си
Пожалуйста, приостановите работу AdBlock на этом сайте.
Создание и инициализация строки
Так как строка – это массив символов, то объявление и инициализация строки аналогичны подобным операциям с одномерными массивами.
Следующий код иллюстрирует различные способы инициализации строк.
Рис.1 Объявление и инициализация строк
Как вывести строку
Дополним код выше до полноценной программы, которая будет выводить созданные строки на экран.
Рис.2 Различные способы вывода строки на экран
Как видите, есть несколько основных способов вывести строку на экран.
Как видите, с выводом всё достаточно просто.
Ввод строк
С вводом строк всё немного сложнее, чем с выводом. Простейшим способом будет являться следующее:
Функция gets приостанавливает работу программы, читает строку символов, введенных с клавиатуры, и помещает в символьный массив, имя которого передаётся функции в качестве параметра.
Завершением работы функции gets будет являться символ, соответствующий клавише ввод и записываемый в строку как нулевой символ.
Заметили опасность? Если нет, то о ней вас любезно предупредит компилятор. Дело в том, что функция gets завершает работу только тогда, когда пользователь нажимает клавишу ввод. Это чревато тем, что мы можем выйти за рамки массива, в нашем случае — если введено более 20 символов.
К слову, ранее ошибки переполнения буфера считались самым распространенным типом уязвимости. Они встречаются и сейчас, но использовать их для взлома программ стало гораздо сложнее.
Итак, что мы имеем. У нас есть задача: записать строку в массив ограниченного размера. То есть, мы должны как-то контролировать количество символов, вводимых пользователем. И тут нам на помощь приходит функция fgets :
Если в ходе выполнения этой программы мы введем строку длиннее, чем 10 символов, в массив все равно будут записаны только 9 символов с начала и символ переноса строки, fgets «обрежет» строку под необходимую длину.
Рис.3 Пример работы функции fgets
Возникает вопрос. А куда делся десятый символ? А я отвечу. Он никуда не делся, он остался в потоке ввода. Выполните следующую программу.
Вот результат её работы.
Рис.4 Непустой буфер stdin
Исправим последний пример так, чтобы его работа была предсказуемой.
Теперь программа будет работать так, как надо.
Рис.4 Сброс буфера stdin функцией fflush
На этом разговор о вводе строк закончен. Идём дальше.
Практика
Решите предложенные задачи:
Для удобства работы сразу переходите в полноэкранный режим
Исследовательские задачи для хакеров
Use of fflush(stdin) in C
fflush() is typically used for output stream only. Its purpose is to clear (or flush) the output buffer and move the buffered data to console (in case of stdout) or disk (in case of file output stream). Below is its syntax.
Can we use it for input stream like stdin?
As per C standard, it is undefined behavior to use fflush(stdin). However some compilers like Microsoft visual studio allows it. How is it used in these compilers? While taking an input string with spaces, the buffer does not get cleared for the next input and considers the previous input for the same. To solve this problem fflush(stdin) is. used to clear the stream/buffer.
Input:
Output:
The code above takes only single input and gives the same result for the second input. Reason is because as the string is already stored in the buffer i.e. stream is not cleared yet as it was expecting string with spaces or new line. So, to handle this situation fflush(stdin) is used.
Input:
Output:
Is it good to use fflush(stdin)?
Although using “fflush(stdin)” after “scanf()” statement also clears the input buffer in certain compilers, it is not recommended to use it as it is undefined behavior by the language standards. In C and C++, we have different methods to clear the buffer discussed in this post.





