Почему getchar () не читает символы, такие как backspace?
Это очень простой вопрос C, исходящий из Страницы 18 Кернигана и Ричи.
Я собрал этот очень простой код для подсчета символов, вводимых с клавиатуры:
#include <stdio.h>
/* count characters in input; 1st version */
main()
{
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%1dn", nc);
}
это компилируется отлично, работает нормально и ведет себя почти так, как ожидалось, т. е. если я ввожу "Hello World", он возвращает значение 11 при нажатии CTRLD чтобы дать характер EOF.
что меня смущает, если я ошибаюсь, Я могу использовать backspace для удаления символов и повторного ввода их, и он возвращает только количество символов, отображаемых терминалом при вызове EOF.
Если код подсчитывает каждый символ, включая специальные символы, если я набираю четыре символа, удаляю два и набираю еще два, разве это не должно выводиться как 8 символов (4 char + 2 del + 2 char), а не 4?
Я, очевидно, не понимаю, как C обрабатывает backspace и как / когда код увеличивает переменную nc
?
3 ответов
Как правило, ваш сеанс терминала работает в" режиме линии", то есть он передает данные в вашу программу только тогда, когда строка завершена (например, вы нажали Return и т. д.). Таким образом, вы видите только строку по мере ее завершения (при любом редактировании, сделанном до того, как ваша программа что-либо увидит). Как правило, это хорошо, поэтому каждой программе не нужно иметь дело с delete/etc.
в большинстве систем (например, в Unix-системах и т. д.) можно перевести терминал в режим "raw" -- то есть каждый символ передается по мере поступления в программу. Например, это обычно делают текстовые редакторы, ориентированные на экран.
это не так getchar()
не учитывает "удаления", но он даже не видит вход, пока он не передан вашей программе драйвером терминала.
когда вы вводите что-то, оно не достигает вашей программы C, пока вы не нажмете \n
или отправить EOF (или EOL). Это то, что POSIX определяет как Канонический Режим Обработки Ввода - который обычно является режимом по умолчанию.
символы Backspace обычно используются для редактирования ввода в режиме cooked tty (см. канонический режим ввода в tty(4)
в BSD и termios(3)
в системах linux), поэтому они потребляются в драйвере tty и не попадают на вход, который получает процесс после этого. То же самое относится к Ctrl-D
в конце файла или в Ctrl-K
как символ ввода убить. Есть несколько вещей, которые водитель делает за кулисами, которые ваш процесс не получает окончательно. Они направлены на то, чтобы облегчить жизнь пользователям и программисты, как вы обычно не хотите стирать вход в свою жизнь (это причина стирания), или хотите, чтобы окончания строк были \n
, а не \r
как обычно генерирует tty, когда вы нажимаете [RETURN]
ключ. Но если Вы читаете из файла, у которого есть backspaces, вы все равно получите их как обычный ввод, просто создайте файл с backspaces и попробуйте прочитать перенаправляющий ввод из него, и вы увидите эти символы в своем вводе.
кстати, если вы хотите создайте backspaces на терминале, просто добавьте Ctrl-V
символ перед каждым (это также управляется в драйвере tty и не произойдет при чтении из файла), и вы увидите свои символы backspace как обычный ввод в файл (для отправки Ctrl-V
просто удвоить его)