The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  ВХОД  слежка  RSS
"scanf & fflush"
Вариант для распечатки Архивированная нить - только для чтения! 
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [Проследить за развитием треда]

"scanf & fflush"
Сообщение от Fatal emailИскать по авторуВ закладки(??) on 17-Июл-04, 00:59  (MSK)
Подскажите, пожалуйста.
Почему в FreeBSD функция fflush не чистит поток stdin. Если я к примеру ввожу букву вместо цифры при запросе функции scanf, то fflush не сбрасывает поток. Почему?
  Рекомендовать в FAQ | Cообщить модератору | Наверх

 Оглавление

Индекс форумов | Темы | Пред. тема | След. тема
Сообщения по теме

1. "scanf & fflush"
Сообщение от sas emailИскать по авторуВ закладки(ok) on 17-Июл-04, 06:13  (MSK)
>Подскажите, пожалуйста.
>Почему в FreeBSD функция fflush не чистит поток stdin. Если я к
>примеру ввожу букву вместо цифры при запросе функции scanf, то fflush
>не сбрасывает поток. Почему?

Вам же уже объясняли на nixp.ru, что согласно стандарту языка С fflush работает только на  output  потоках. Поведение на input НЕ ОПРЕДЕЛЕНО, что означает, что может случится ВСЕ что угодно начиная с ничего до core или атомного взрыва.

Удачи
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

2. "scanf & fflush"
Сообщение от Fatal emailИскать по авторуВ закладки(??) on 17-Июл-04, 09:55  (MSK)
Доброго времени суток, sas!
Это курто!
Просто хотел узнать менение других умных людей, а на том форуме отвечаете только вы один. Ну, даладно ... В любом случае спасибо большое за ответ.
  Рекомендовать в FAQ | Cообщить модератору | Наверх

3. "scanf & fflush"
Сообщение от dimus Искать по авторуВ закладки(ok) on 20-Июл-04, 08:31  (MSK)
Интересно, а я этого не знал, хотя с давних пор общаюсь с С/С++. А как же всетаки очистить stdin, если fflush( stdin ) тут не работает (хотя под виндой я видел, и не раз, примеры обратного)
  Рекомендовать в FAQ | Cообщить модератору | Наверх

4. "scanf & fflush"
Сообщение от sas emailИскать по авторуВ закладки(ok) on 20-Июл-04, 08:38  (MSK)
>Интересно, а я этого не знал, хотя с давних пор общаюсь с
>С/С++. А как же всетаки очистить stdin, если fflush( stdin )
>тут не работает (хотя под виндой я видел, и не раз,
>примеры обратного)

Сходите на
http://www.nixp.ru/cgi-bin/forum/YaBB.pl?board=coding;action=display;num=1089829436

Успехов
--- sas

  Рекомендовать в FAQ | Cообщить модератору | Наверх

5. "scanf & fflush"
Сообщение от dimus Искать по авторуВ закладки(ok) on 23-Июл-04, 14:10  (MSK)
Сходил. Да, круто вы там все разложили. Вот уж никогда не думал, что очистить поток ввода - это такая проблема. А виндовая функция fflush мне все же нравится. По моему, возможно сделать и так:

void fflush_stdin( void )
{
  while( не_конец_файла_стдин )
  {
    fgetc( stdin );
  }
}
Я опробую этот код при первой же возможности, но хотелось бы
услышать ваше мнение

  Рекомендовать в FAQ | Cообщить модератору | Наверх

6. "scanf & fflush"
Сообщение от Fatal emailИскать по авторуВ закладки(??) on 23-Июл-04, 20:10  (MSK)
>Сходил. Да, круто вы там все разложили. Вот уж никогда не думал,
>что очистить поток ввода - это такая проблема. А виндовая функция
>fflush мне все же нравится. По моему, возможно сделать и так:
>
>
>void fflush_stdin( void )
>{
>  while( не_конец_файла_стдин )
>  {
>    fgetc( stdin );
>  }
>}
>Я опробую этот код при первой же возможности, но хотелось бы
>услышать ваше мнение


Этот цикл никогда не закончится (конечно если поток не перенаправлен в файл), т.к. в stdin нет EOF (End Of File)

  Рекомендовать в FAQ | Cообщить модератору | Наверх

7. "scanf & fflush"
Сообщение от sas emailИскать по авторуВ закладки(ok) on 24-Июл-04, 15:33  (MSK)
>>Сходил. Да, круто вы там все разложили. Вот уж никогда не думал,
>>что очистить поток ввода - это такая проблема. А виндовая функция
>>fflush мне все же нравится. По моему, возможно сделать и так:
>>
>>
>>void fflush_stdin( void )
>>{
>>  while( не_конец_файла_стдин )
>>  {
>>    fgetc( stdin );
>>  }
>>}
>>Я опробую этот код при первой же возможности, но хотелось бы
>>услышать ваше мнение
>
>
>Этот цикл никогда не закончится (конечно если поток не перенаправлен в файл),
>т.к. в stdin нет EOF (End Of File)

Теория
=====
Мы должны различать 2 типа настройки терминалов:
1) "обычный", или буферизированный (canonical), когда данные передаются в пользовательскую программу в следующих случаях:
   а) В буфере появилось: новая строка (NL), EOF или конец строки (EOL). Кстати EOF в DOS - это Ctrl+Z, а в Unix - Ctrl+D (ВАЖНО что бы они были первыми в строке). Если EOF произошел и мы еще собираемся использванть stdin, то надо вызвать clearerr
   б) Буфер заполнился полностью и у нас нет больше места, а NL/EOF/EOL все нет. В этом случае поведение системы зависит от termio c_iflag. Подробнее смотри в man termios

2) "сырой" (noncanonical), когда например буферизация убрана, и данные передаются нам для обработки сразу (см  termios).

Ответ
====
Исходя из вышеизложенного, на "ОБЫЧНОМ" терминале: Нет, такая очистка буфера работать не будет.

Т.е. мы могли бы перейти в "сырой" режим (termios флаги и tcsetattr), но тогда нам самим бы пришлось разбирать ввод, т.е. делать кучу работы, которую для нас (scanf) уже кто-то сделал. И зачем?

Удачи
--- sas


  Рекомендовать в FAQ | Cообщить модератору | Наверх

8. "scanf & fflush"
Сообщение от dimus Искать по авторуВ закладки(ok) on 28-Июл-04, 08:41  (MSK)
Да, тот код действительно не работает. Однако я нашел более простое решение для ограниченного круга задач, связанного с получением ввода в текстовом меню. Допустим, что нам нужно чтобы работало меню такого типа:
1 - сделай то-то
2 - сделай что-то другое
h - поприветствуй всех собравшихся
0 - выйти
Тогда в цикле while можно использовать такую функцию:

int get_menu_char( FILE* fp )
{
   int result;
   // Получим то, что нам нужно
   result = fgetc( fp );
   // Проверим на конец файла из параноидальных соображений
   // Проглотим весь мусор
   while( !feof(fp) && ( fgetc(fp) !='\n') );
   return result;
}

Не знаю, может еще добавить туда сброс флага конца файла - я еще не решил, надо ли это. Но тестовая програмка работала прекрасно. Насчет scanf: я не использую функции, которые не контролируют объем ввода, т.к. это прямой путь к дырявой программе. Может быть я несправедлив к scanf, однако:
char msg[MAX_MSG];
scanf("%s", msg);
Это находка для любителей атак переполнением буфера. Я предпочитаю fgets.

Кстати, а где можно найти ТОЛКОВУЮ информацию по переключению терминала в другие режимы. Все, что я читал по этому вопросу было очень невнятно, а вещь ведь интересная и нужная.

С уважением, dimus

  Рекомендовать в FAQ | Cообщить модератору | Наверх


Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Пожалуйста, прежде чем написать сообщение, ознакомьтесь с данными рекомендациями.




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру