![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| russians |
|
||||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 297 Регистрация: 6.11.2006 Репутация: нет Всего: нет |
В книге K&R в первых главах даётся описание функций getchar и putchar, но пропущена проблема буфера.
Например, если выполнить код из этой статьи http://younglinux.info/c/getchar
то он не сработает, как ожидается, т.к. второй символ будет занят \n, а третий вторым символом. Плюс - непонятно из статьи, почему на выводе мы увидим букву, а не \n + букву. Также непонятно, вот я ввёл символ ~, который в while отмечен по условию выхода. Почему тогда не производится выход из программы в тот момент, как я ввожу этот символ, если он уже добавился в буфер обмена, а в тот момент, когда я нажимаю Enter? Непонятно. Кроме того, мне непонятно, почему этот код даёт завершение ввода по нажатию ~:
а более короткая запись - уже нет:
И почему в выводе первого варианта отсутствует перевод на новую строку и присутствует L?
Это сообщение отредактировал(а) russians - 21.8.2012, 02:17 |
||||||||
|
|||||||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
putchar() считывает один символ. три путчара считывают 3 символа. но в программу какие-либо символы попадут только после нажатия Enter, т.к. ввод буферизуется.
так что в первом примере надо ввести abc<Enter> и считаются все три символа. непонятки с ~ по той же причине. putchar("\n"); выведет странные вещи, т.к. ей передан не символ, а указатель на строку. |
|||
|
||||
| russians |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 297 Регистрация: 6.11.2006 Репутация: нет Всего: нет |
baldina, стоп, а как же тогда работает getchar?
Ведь каждый цикл вызывается getchar, который считывает один символ из потока ввода, который, по определению K&R, являет собой последовательность символов, разбитых на строки. А мы вбиваем не по одному символу, а всю строку целиком и нажимаем Enter. Как тогда понять конструкцию:
Т.е. запускается getchar() и запускается ввод. Мы можем ввести целиком строку и нажимаем Enter. После этого getchar берёт введённую строку и посимвольно пробегается по ней? Непонятно, что если ввод строки открывает getchar, то функция должна завершить свою работу на этапе while и уничтожить строку, которая была введена, кроме первого символа, сохранённого в a, а её несуществующие символы обрабатываются в putchar. Что же тогда принимает строку на ввод из потока, если getchar принимает только один символ? Это сообщение отредактировал(а) russians - 21.8.2012, 04:15 |
|||
|
||||
| feodorv |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2214 Регистрация: 30.7.2011 Репутация: 11 Всего: 45 |
А ещё можно сбрасывать буфер ввода:
-------------------- Напильник, велосипед, грабли и костыли - основные инструменты программиста... |
|||
|
||||
| russians |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 297 Регистрация: 6.11.2006 Репутация: нет Всего: нет |
feodorv, а разве вызов getchar() после putchar не опустошает буфер автоматически? Или буфер работает по принципу стека?
|
|||
|
||||
| baldina |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
Вы не совсем правильно поняли. Это не по их определению, так консоль устроена. буфер работает по принципу очереди нет. getchar() извлекает один единственный символ из буфера (начала очереди). что и как попадает в буфер от программиста скрыто, известно только, что попадает со стандартного ввода. программисту достаточно знать, что: 1. getchar() получает очередной символ из потока ввода (будет ждать, если доступных символов нет) 2. символы, вводимые с клавиатуры, станут доступны программе после нажатия клавиши enter. необходимость нажатия enter связана только с механизмом работы консоли (по историческим ныне несущественным причинам). если на стандартный ввод перенаправить из файла, будет как раз последовательная посимвольная обработка. Добавлено @ 13:08
нет. они вообще с разными потоками связаны, stdin и stdout. Добавлено @ 13:11 попробуйте заменить В вашем примере getchar и putchar на getc и putc, может быть сразу станет понятнее. Это суть одно и то же, только в getc и putc поток ввода/вывода указывается явно, а getchar и putchar однозначно работают с stdin и stdout соответственно. Это сообщение отредактировал(а) baldina - 21.8.2012, 13:18 |
||||
|
|||||
| russians |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 297 Регистрация: 6.11.2006 Репутация: нет Всего: нет |
baldina, спасибо за подробное разъяснение.
Но разве издательство K& покойный R (WPH) не могли добавить этот нюанс в новую редакцию, учитывая то, что с этим может возникнуть непонимание? Объяснить, что существует buffered input и unbuffered input. А потом говорят, что этой книги вполне достаточно для базового понимания C Это сообщение отредактировал(а) russians - 21.8.2012, 13:42 |
|||
|
||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
достаточно. для базового понимания аппаратуры и ОС есть другие книги))) Добавлено через 2 минуты и 12 секунд в случае getc и getchar ввод всегда буферизирован, независимо консоль это или другой файл в случае небуферизированного ввода с консоли enter все равно придется нажимать. так что это к теме не относится)) Добавлено через 9 минут и 7 секунд Буфер IO это сугубо программная вещь. Буферы, которые в драйверах (или в самой железке) совсем другого рода и уровня, Вы этим не можете управлять (посредством программного IO). Представьте сетевой обмен. Например в Ethernet кадре данные это от 46 до 1500 байт. Можно читать/писать в сеть посимвольно, но это логически, с точки зрения программиста, а физически ходить данные все-равно будут порциями. |
|||
|
||||
| russians |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 297 Регистрация: 6.11.2006 Репутация: нет Всего: нет |
baldina, ок, спасибо. Просто, в любом случае, человек наткнётся на эту проблему и ему будет непонятно, почему код, который он написал по заданию книги, не работает. Т.е. getchar() работает не просто так, он работает с системным буфером, и для цельного понимания нужно вводить элементы из устройства ОС Unix. Правда, у K&R для этого есть другая книжка
Это сообщение отредактировал(а) russians - 21.8.2012, 15:31 |
|||
|
||||
| russians |
|
||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 297 Регистрация: 6.11.2006 Репутация: нет Всего: нет |
baldina, а ещё такой вопрос: почему в варианте
текст вида aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^Z[Enter] прокатывает и вместо терминирования цикла - новая строка для ввода, а если напечатать одиночно ^Z - происходит терминирование цикла? Просто в этом варианте:
мы считаем количество '\n', и тут getchar() доходит до конца строки. Почему в первом варианте не так? Это сообщение отредактировал(а) russians - 21.8.2012, 16:37 |
||||
|
|||||
| baldina |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 3433 Регистрация: 5.12.2007 Где: Москва Репутация: 32 Всего: 101 |
пока enter не введен ^Z видимо просто сбрасывает буфер в программу (без enter), но не шлет конец файла. в отличие от ввода в начале строки
|
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |