从stdin读入单个字符(不需要按Enter键,即可返回当前的按键值)Canonical(常规模式)
intsetlflag(int flags, int enable)
{
structtermiosattr;
tcgetattr(STDIN_FILENO, &attr);
if (enable) {
attr.c_lflag |= flags; // 使能标志位
} else {
attr.c_lflag &= ~flags; // 清除标志位
}
return tcsetattr(STDIN_FILENO, TCIFLUSH, &attr);
}
intmain(int argc, char* argv[])
{
...
printf("enter password: ");
fflush(stdout);
setlflag(ECHO | ICANON, 0); // 关闭回显及常规模式
for (int i = 0; i < sizeof(password) && password[i-1] != '\n'; i++) {
password[i] = getchar();
printf("*");
fflush(stdout);
}
printf("\n");
setlflag(ECHO | ICANON, 1); // 恢复回显及常规模式
printf("%s\n", strcmp(username, password) ? "✖️" : "✔️");
return0;
}
在禁用回显的同时还要实现将每个输入字符回显为*样式,我们就必须在每次keypress的时候打印一个星号,但如果直接调用getchar读输入时就会发现必须在用户敲下回车键才能读到,如何免回车读取一个字符呢——答,禁用ICANON。
Canonical(常规模式)即前文提到的ICANON标志位,它同样受控于c_lflag字段。此模式下的输入处理都是line-by-line在缓存中的,这也就是为什么我们在调用fgets时总需要回车才能读到,只要你没回车就可以在行内进行简单编辑,如删除字符、清行、复制粘贴等操作。一旦关闭后,输入的处理就会变成byte-by-byte,行内编辑也失效了,什么删除符、箭头、TAB、^Y、^U、^X、F1-F12等特殊键统统被当作输入字符处理,且立即生效。