| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > getchar() - вопрос с буфером ввода |
| Автор: russians 21.8.2012, 02:01 | ||||||||
| В книге K&R в первых главах даётся описание функций getchar и putchar, но пропущена проблема буфера. Например, если выполнить код из этой статьи http://younglinux.info/c/getchar
то он не сработает, как ожидается, т.к. второй символ будет занят \n, а третий вторым символом. Плюс - непонятно из статьи, почему на выводе мы увидим букву, а не \n + букву. Также непонятно, вот я ввёл символ ~, который в while отмечен по условию выхода. Почему тогда не производится выход из программы в тот момент, как я ввожу этот символ, если он уже добавился в буфер обмена, а в тот момент, когда я нажимаю Enter? Непонятно. Кроме того, мне непонятно, почему этот код даёт завершение ввода по нажатию ~:
а более короткая запись - уже нет:
И почему в выводе первого варианта отсутствует перевод на новую строку и присутствует L?
|
| Автор: baldina 21.8.2012, 03:19 |
| putchar() считывает один символ. три путчара считывают 3 символа. но в программу какие-либо символы попадут только после нажатия Enter, т.к. ввод буферизуется. так что в первом примере надо ввести abc<Enter> и считаются все три символа. непонятки с ~ по той же причине. putchar("\n"); выведет странные вещи, т.к. ей передан не символ, а указатель на строку. |
| Автор: russians 21.8.2012, 04:08 | ||
| baldina, стоп, а как же тогда работает getchar? Ведь каждый цикл вызывается getchar, который считывает один символ из потока ввода, который, по определению K&R, являет собой последовательность символов, разбитых на строки. А мы вбиваем не по одному символу, а всю строку целиком и нажимаем Enter. Как тогда понять конструкцию:
Т.е. запускается getchar() и запускается ввод. Мы можем ввести целиком строку и нажимаем Enter. После этого getchar берёт введённую строку и посимвольно пробегается по ней? Непонятно, что если ввод строки открывает getchar, то функция должна завершить свою работу на этапе while и уничтожить строку, которая была введена, кроме первого символа, сохранённого в a, а её несуществующие символы обрабатываются в putchar. Что же тогда принимает строку на ввод из потока, если getchar принимает только один символ? |
| Автор: feodorv 21.8.2012, 04:16 | ||
А ещё можно сбрасывать буфер ввода:
|
| Автор: russians 21.8.2012, 12:43 |
| feodorv, а разве вызов getchar() после putchar не опустошает буфер автоматически? Или буфер работает по принципу стека? |
| Автор: russians 21.8.2012, 13:33 |
| baldina, спасибо за подробное разъяснение. Но разве издательство K& покойный R (WPH) не могли добавить этот нюанс в новую редакцию, учитывая то, что с этим может возникнуть непонимание? Объяснить, что существует buffered input и unbuffered input. А потом говорят, что этой книги вполне достаточно для базового понимания C |
| Автор: baldina 21.8.2012, 14:57 |
достаточно. для базового понимания аппаратуры и ОС есть другие книги))) Добавлено через 2 минуты и 12 секунд в случае getc и getchar ввод всегда буферизирован, независимо консоль это или другой файл в случае небуферизированного ввода с консоли enter все равно придется нажимать. так что это к теме не относится)) Добавлено через 9 минут и 7 секунд Буфер IO это сугубо программная вещь. Буферы, которые в драйверах (или в самой железке) совсем другого рода и уровня, Вы этим не можете управлять (посредством программного IO). Представьте сетевой обмен. Например в Ethernet кадре данные это от 46 до 1500 байт. Можно читать/писать в сеть посимвольно, но это логически, с точки зрения программиста, а физически ходить данные все-равно будут порциями. |
| Автор: russians 21.8.2012, 15:27 |
| baldina, ок, спасибо. Просто, в любом случае, человек наткнётся на эту проблему и ему будет непонятно, почему код, который он написал по заданию книги, не работает. Т.е. getchar() работает не просто так, он работает с системным буфером, и для цельного понимания нужно вводить элементы из устройства ОС Unix. Правда, у K&R для этого есть другая книжка |
| Автор: russians 21.8.2012, 16:35 | ||||
baldina, а ещё такой вопрос: почему в варианте
текст вида aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^Z[Enter] прокатывает и вместо терминирования цикла - новая строка для ввода, а если напечатать одиночно ^Z - происходит терминирование цикла? Просто в этом варианте:
мы считаем количество '\n', и тут getchar() доходит до конца строки. Почему в первом варианте не так? |
| Автор: baldina 21.8.2012, 19:01 |
| пока enter не введен ^Z видимо просто сбрасывает буфер в программу (без enter), но не шлет конец файла. в отличие от ввода в начале строки |