为什么 getchar() 不读取退格等字符?

Why doesn't getchar() read characters such as backspace?

这是一道非常基础的 C 题,来自 Kernighan 和 Ritchie 的第 18 页。

我编写了这段非常简单的代码来计算从键盘输入的字符数:

#include <stdio.h>

/* count characters in input; 1st version */
main()
{
  long nc;

  nc = 0;
  while (getchar() != EOF)
    ++nc;
  printf("%1d\n", nc);
}

这可以正常编译,运行正常,并且表现非常符合预期,即如果我输入 "Hello World",当我按下 CTRL[=26] 时,它 returns 的值为 11 =]D 给出EOF字符。

令我困惑的是,如果我输入错误,我可以使用退格键删除字符并重新输入,而且它 returns 只是我调用 EOF 时终端显示的字符数.

如果代码计算每个字符,包括特殊字符,如果我输入四个字符,删除两个,然后再输入两个,不应该输出为 8 个字符 (4 char + 2 del + 2 char),不是 4?

我显然误解了 C 是如何处理退格键的,how/when 代码正在递增变量 nc?

通常,您的终端会话是 "line mode" 中的 运行,也就是说,它仅在一行完成时将数据传递给您的程序(例如,您按下 Return,等等).所以你只能看到完整的行(在你的程序看到任何东西之前已经完成了任何编辑)。通常这是一件好事,所以每个程序都不需要处理 delete/etc.

在大多数系统(例如Unix-based 系统等)上,可以将终端置于"raw" 模式——也就是说,每个字符都按接收到的方式传递给程序。例如,screen-oriented 文本编辑器通常这样做。

并不是说 getchar() 不计算 "deletions" 而是在终端驱动程序将其传递给您的程序之前它甚至看不到输入。

当您输入某些内容时,在您按下 \n 或发送 EOF(或 EOL)之前,它不会到达您的 C 程序。这就是 POSIX 定义为 Canonical Mode Input Processing - 通常是默认模式。

退格字符通常用于在 cooked tty 模式下编辑输入(请参阅 BSD 中的 tty(4) 和 linux 系统中的 termios(3) 中的规范输入模式),因此它们在tty 驱动程序,并且不要获取该进程之后获得的输入。这同样适用于 Ctrl-D 作为文件结尾或 Ctrl-K 作为 kill 输入字符。驱动程序在幕后做的几件事是您的进程最终没有得到的。这些旨在让用户和程序员的生活更轻松,因为您通常不希望在生活中删除输入(这就是删除它的原因),或者希望行尾是 \n 而不是 \r 因为 tty 通常在您按下 [RETURN] 键时生成。但是,如果您从一个碰巧有退格键的文件中读取,无论如何您都会将它们作为正常输入获取,只需创建一个带有退格键的文件并尝试从中读取重定向输入,您就会在输入中看到这些字符。

顺便说一句,如果你想在终端生成退格,只需在每个退格前加上一个 Ctrl-V 字符(这也是在 tty 驱动程序中管理的,从文件读取时不会发生)和你会在你的文件中看到你的退格字符作为正常输入(发送 Ctrl-V 只需加倍)