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等特殊键统统被当作输入字符处理,且立即生效。

标签: none

添加新评论