- Функция fflush() не работает с stdin
- Использование fflush(stdin)
- 4 ответов
- стандартный C и POSIX оставить fflush(stdin) как неопределенное поведение
- §7.21.5.2 функция fflush
- Microsoft определяет поведение fflush(stdin)
- документация и практика Linux, похоже, противоречат друг другу
- demo-fflush.c
- пример вывода
- demo-fflush2.c
- пример вывода
- резюме
- POSIX способ отбросить непрочитанный ввод терминала из файлового дескриптора
- fflush не работает
- 2 ответа
- Сбрасывает ручей
- Почему fflush stdin не работает
Функция fflush() не работает с stdin
Прошу прощения за этот глупый вопрос. У меня есть программа C, чтобы побудить пользователя ввести возраст и имя, а затем напечатать возраст и имя на экране. Это мое упражнение, которое я прочитал из книги.
Когда я ввожу дополнительные символы в первый scanf() программа завершает и назначает дополнительные символы следующему scanf()
Затем я изменил код и добавлю функцию с именем clear_buff() и используя функцию fgets в clear_buff() чтобы прочитать оставшиеся символы в потоке. Код работает так, как я ожидал.
Мой вопрос в том, почему fflush(stdin) не работает в этой программе?
В книге говорится, что fflush функции сброса всех буферизованных данных на stream.And Я знаю, что fflush() функция является стандартной функцией C, если работа с I/O потока.
fflush предназначен для работы с потоками вывода или обновления, а использование его с входным потоком — неопределенное поведение, из раздела cppreference C для fflush:
Поведение не определено, если данный поток имеет тип ввода или если данный поток относится к типу обновления, но последняя операция ввода-вывода не была операцией вывода.
Неопределенное поведение — это поведение, которое стандарт не указывает, и это означает, что результат вашей программы непредсказуем, что может означать поведение, которое кажется нормальным, или сбой или другие нежелательные эффекты.
cppreference согласуется с языком в проекте стандартного раздела C99 7.19.5.2 Функция 7.19.5.2 которая гласит:
Если поток указывает на выходной поток или поток обновлений, в котором последняя операция не была введена, функция fflush приводит к тому, что любые неписанные данные для этого потока будут доставлены в среду хоста для записи в файл; в противном случае поведение не определено.
Хотя на самом деле это не ваш вопрос, и кажется, что вы разобрались в работе, вопрос C, flushing stdin охватывает некоторые правильные способы смывания stdin .
Источник
Использование fflush(stdin)
Так быстрый поиск Google для fflush(stdin) для очистки входного буфера показывает многочисленные веб-сайты предупреждение против его использования. И все же именно так мой профессор CS учил класс делать это.
Как плохо использует fflush(stdin) ? Должен ли я действительно воздерживаться от его использования, даже если мой профессор использует его и, похоже, работает безупречно?
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.
[CX] для a поток открыт для чтения, если файл еще не находится в EOF, и файл способен искать, смещение файла базового открытого описания файла должно быть установлено в положение файла потока, и любые символы, возвращаемые в поток ungetc() или ungetwc() , которые впоследствии не были считаны из потока, должны быть отброшены (без дальнейшего изменения файла смещение).
обратите внимание, что терминалы не способны искать; ни трубы, ни розетки.
Microsoft определяет поведение fflush(stdin)
Microsoft и среда выполнения Visual Studio определяет определение поведения fflush() на входном потоке.
если поток открыт для ввода, fflush очищает содержимое буфера.
Cygwin является примером довольно распространенной платформы, на которой fflush(stdin) не очищает входные данные.
вот почему эта версия ответа my комментарий Примечания «Microsoft и среда выполнения Visual Studio» -Если вы используете библиотеку времени выполнения не Microsoft C, поведение, которое вы видите, зависит от этой библиотеки.
документация и практика 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 строки выглядят так:
другими словами, есть комментарий в верхней части Mac OS X . Строки без комментариев соответствуют нормальному макету, так что root запись:
Ubuntu 14.04 LTS:
поведение Mac OS X игнорирует (или, по крайней мере, кажется, игнорирует) fflush(stdin) (таким образом, не следуя POSIX по этому вопросу). Поведение Linux соответствует задокументированному поведению POSIX, но спецификация POSIX гораздо более осторожна в том, что она говорит — она указывает файл, способный искать, но терминалы, конечно, не поддерживают поиск. Это также гораздо менее полезно, чем спецификация Microsoft.
резюме
Microsoft документирует поведение fflush(stdin) . По-видимому, он работает так, как описано на платформе Windows, используя собственный компилятор Windows и библиотеки поддержки среды выполнения C.
несмотря на документацию наоборот, он не работает в Linux, когда стандартный ввод является терминалом, но, похоже, следует спецификации POSIX, которая гораздо более тщательно сформулирована. В соответствии с стандарт C, поведение fflush(stdin) неопределено. В POSIX добавляет уточнение, если входной файл для перемещения, которые терминал не. Поведение не совпадает с поведением Microsoft.
следовательно, портативный код не использует fflush(stdin) . Код, привязанный к платформе Microsoft, может использовать его, и он будет работать, но остерегайтесь проблем с переносимостью.
POSIX способ отбросить непрочитанный ввод терминала из файлового дескриптора
стандартный способ POSIX отбросьте непрочитанную информацию из дескриптора файла терминала (в отличие от потока файлов типа stdin ) иллюстрируется на как я могу очистить непрочитанные данные из входной очереди tty в системе Unix. Однако это работает ниже стандартного уровня библиотеки ввода-вывода.
согласно стандарту, fflush может использоваться только с выходными буферами и, очевидно, stdin не один. Однако,некоторые компиляторы обеспечивают использование fflush (stdin) в качестве расширения. В этом случае вы можете использовать его, но это повлияет на переносимость, поэтому вы больше не сможете использовать любой совместимый со стандартами компилятор на земле и ожидать тех же результатов.
для потока, открытого для чтения, если файл еще не находится в EOF, и файл один способный искать, смещение файла основного открытого описания файла будет установлено в положение файла потока, и любые символы, выталкиваемые обратно в поток ungetc () или ungetwc (), которые впоследствии не считывались из потока, должны быть dis- карточку (без дальнейшего изменения файла смещение.)
обратите внимание, что терминал не способен искать.
Источник
fflush не работает
Почему fflush(..) не работает с c2 и c0 ?
Если я использую объявление c0 = 0 и c2 = 0 , оно работает, но fflush(stdin) не работает, я пытался разместить в разных местах, но это не сработало, я использую блоки кода в ubuntu 13.04 ;
2 ответа
fflush(stdin) имеет неопределенное поведение. В дальнейшем используйте это для работы с новой строкой, которая остается в буфере stdin при использовании scanf() , особенно в тех случаях, когда вам нужно прочитать символ, но новая строка остается в буфер автоматически принимается как символ:
Вот что cplusplusreference говорит о fflush() (вы можете проверить то же самое и из других источников, потому что слишком много ветеранов здесь, на SO, недовольны cplusplusreference , хотя и не осуждают его полностью)
. In some implementations, flushing a stream open for reading causes its input buffer to be cleared (but this is not portable expected behavior).
В вашей системе ubuntu 13.04 (Unix или Linux) вызов fflush (stdin); является неопределенным поведением!
ostream указывает на выходной поток или поток обновления, в котором не была введена самая последняя операция, функция fflush заставляет любые незаписанные данные для этого потока, которые будут доставлены в среду хоста, будут записаны в файл; в противном случае поведение не определено
Чтобы научиться правильно очищать входной буфер, вы можете использовать некоторые из следующих фрагментов кода, которые фактически читают и удаляют ненужные символы из входного буфера. Вы можете использовать это как fflush перед чтением фактических данных. прочтите этот раздел часто задаваемых вопросов.
Для C :
Для C ++ :
Однако, если вы вызываете их, когда во входном потоке нет данных, программа будет ждать, пока они не появятся, что даст вам нежелательные результаты.
Изменить:
Есть платформы, где fflush(stdin) полностью определен (как нестандартное расширение для этой платформы). Основным примером является хорошо известное семейство систем, вместе известных как Windows. Спецификация Microsoft:
Сбрасывает ручей
Функция int fflush(FILE *stream ) очищает поток. Если файл, связанный с поток открыт для вывода, fflush записывает в этот файл содержимое буфер, связанный с потоком. Если поток открыт для input , fflush очищает содержимое буфера. fflush отменяет эффект любого предыдущего вызова ungetc против потока. Кроме того, fflush(NULL) очищает все потоки, открытые для вывода. Поток остается открытым после звонок. fflush не влияет на небуферизованный поток.
Источник
Почему fflush stdin не работает
Подскажите, пожалуйста.
Почему в FreeBSD функция fflush не чистит поток stdin. Если я к примеру ввожу букву вместо цифры при запросе функции scanf, то fflush не сбрасывает поток. Почему?
| Оглавление |
|
| Индекс форумов | Темы | Пред. тема | След. тема |
| Сообщения по теме |
| 1. «scanf & fflush» | |
| Сообщение от sas | |
| Рекомендовать в FAQ | Cообщить модератору | Наверх | |
| 2. «scanf & fflush» | |
| Сообщение от Fatal | |
| |
| Рекомендовать в FAQ | Cообщить модератору | Наверх | |
| 3. «scanf & fflush» | |
| Сообщение от dimus | |
| |
| Рекомендовать в FAQ | Cообщить модератору | Наверх | |
| 4. «scanf & fflush» | |
| Сообщение от sas | |
| |
| Рекомендовать в FAQ | Cообщить модератору | Наверх | |
| 5. «scanf & fflush» | |
| Сообщение от dimus | |
void fflush_stdin( void ) | |
| Рекомендовать в FAQ | Cообщить модератору | Наверх | |
| 6. «scanf & fflush» | |
| Сообщение от Fatal | |
Этот цикл никогда не закончится (конечно если поток не перенаправлен в файл), т.к. в stdin нет EOF (End Of File) | |
| Рекомендовать в FAQ | Cообщить модератору | Наверх | |
| 7. «scanf & fflush» | |
| Сообщение от sas | |
Теория 2) «сырой» (noncanonical), когда например буферизация убрана, и данные передаются нам для обработки сразу (см termios). Ответ Т.е. мы могли бы перейти в «сырой» режим (termios флаги и tcsetattr), но тогда нам самим бы пришлось разбирать ввод, т.е. делать кучу работы, которую для нас (scanf) уже кто-то сделал. И зачем? | |
| Рекомендовать в FAQ | Cообщить модератору | Наверх | |
| 8 . «scanf & fflush» | |
| Сообщение от dimus | |
int get_menu_char( FILE* fp ) Не знаю, может еще добавить туда сброс флага конца файла — я еще не решил, надо ли это. Но тестовая програмка работала прекрасно. Насчет scanf: я не использую функции, которые не контролируют объем ввода, т.к. это прямой путь к дырявой программе. Может быть я несправедлив к scanf, однако: Кстати, а где можно найти ТОЛКОВУЮ информацию по переключению терминала в другие режимы. Все, что я читал по этому вопросу было очень невнятно, а вещь ведь интересная и нужная. Источник | |