The OpenNET Project / Index page

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




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
scanf & fflush, !*! Fatal, 17-Июл-04, 00:59  [смотреть все]
Подскажите, пожалуйста.
Почему в FreeBSD функция fflush не чистит поток stdin. Если я к примеру ввожу букву вместо цифры при запросе функции scanf, то fflush не сбрасывает поток. Почему?
  • scanf & fflush, !*! sas, 06:13 , 17-Июл-04 (1)
    >Подскажите, пожалуйста.
    >Почему в FreeBSD функция fflush не чистит поток stdin. Если я к
    >примеру ввожу букву вместо цифры при запросе функции scanf, то fflush
    >не сбрасывает поток. Почему?

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

    Удачи
    --- sas

    • scanf & fflush, !*! Fatal, 09:55 , 17-Июл-04 (2)
      Доброго времени суток, sas!
      Это курто!
      Просто хотел узнать менение других умных людей, а на том форуме отвечаете только вы один. Ну, даладно ... В любом случае спасибо большое за ответ.
      • scanf & fflush, !*! dimus, 08:31 , 20-Июл-04 (3)
        Интересно, а я этого не знал, хотя с давних пор общаюсь с С/С++. А как же всетаки очистить stdin, если fflush( stdin ) тут не работает (хотя под виндой я видел, и не раз, примеры обратного)
        • scanf & fflush, !*! sas, 08:38 , 20-Июл-04 (4)
          >Интересно, а я этого не знал, хотя с давних пор общаюсь с
          >С/С++. А как же всетаки очистить stdin, если fflush( stdin )
          >тут не работает (хотя под виндой я видел, и не раз,
          >примеры обратного)

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

          Успехов
          --- sas

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

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

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


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

              • scanf & fflush, !*! sas, 15:33 , 24-Июл-04 (7)
                >>Сходил. Да, круто вы там все разложили. Вот уж никогда не думал,
                >>что очистить поток ввода - это такая проблема. А виндовая функция
                >>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


                • scanf & fflush, !*! dimus, 08:41 , 28-Июл-04 (8)
                  Да, тот код действительно не работает. Однако я нашел более простое решение для ограниченного круга задач, связанного с получением ввода в текстовом меню. Допустим, что нам нужно чтобы работало меню такого типа:
                  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




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

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