- 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)
- 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
|