这是一个非常基本的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 D 时,它返回值11给出EOF角色。
令我困惑的是,如果我犯了错误,我可以使用退格键删除字符并重新输入它们,并且只返回终端在调用EOF时显示的字符数。
如果代码计算每个字符,包括特殊字符,如果我输入四个字符,删除两个,然后输入另外两个,不应该输出为8个字符(4个字符+2个del + 2个字符),而不是4个字符?
我显然误解了C处理退格的方式,以及代码如何/何时递增变量nc
?
答案 0 :(得分:5)
通常,您的终端会话以“线路模式”运行,也就是说,它只在线路完成时将数据传递给您的程序(例如,您按下Return等)。因此,您只能在完成后看到该行(在您的程序看到任何内容之前已完成任何编辑)。通常这是一件好事,所以每个程序都不需要处理delete / etc。
在大多数系统(例如基于Unix的系统等)上,可以将终端置于“原始”模式 - 也就是说,每个字符都按接收方式传递给程序。例如,面向屏幕的文本编辑器通常会这样做。
答案 1 :(得分:5)
并非getchar()
不计算&#34;删除&#34;但在终端驱动程序将其输入程序之前,它甚至看不到输入。
当您输入内容时,在您按\n
或发送EOF(或EOL)之前,它无法到达您的C程序。这就是POSIX定义为Canonical Mode Input Processing - 这通常是默认模式。
答案 2 :(得分:1)
退格字符通常用于编辑cooked tty模式下的输入(请参阅BSD中的tty(4)
中的规范输入模式和linux系统中的termios(3)
),因此它们会被tty驱动程序使用,并且不要在那之后得到进程得到的输入。这同样适用于作为文件结尾的Ctrl-D
或作为终止输入字符的Ctrl-K
。驱动程序在幕后做了几件事情,你的流程最终没有得到。这些旨在让用户和程序员的生活更轻松,因为您通常不希望在生活中删除输入(这是擦除它的原因),或者希望行结尾为\n
而不是{{1}当你按下\r
键时tty正常生成。但是如果您从一个恰好有退格的文件中读取,那么无论如何你都会将它们作为普通输入,只需创建一个带有退格的文件并尝试从中读取重定向输入,然后你会在输入中看到这些字符。 / p>
顺便说一下,如果你想在终端上生成退格,只需在每个前面添加一个[RETURN]
字符(这也是在tty驱动程序中管理,在从文件读取时不会发生)并且你'将你的退格字符视为文件中的正常输入(发送Ctrl-V
只需加倍)