在C中防止键盘输入中的ANSI转义字符
我有一个C程序,要求用户输入他们的名字,并在while循环中读取stdin的代码(直到按下enter)。 我确保用户只能输入32到126之间的ASCII值 问题是当我按下我的箭头(光标)键,或类似于PAGE_DOWN或其他。。。 我最终将ANSI转义序列打印到终端([A、[6~,等等) 下面是代码部分在C中防止键盘输入中的ANSI转义字符,c,string,user-input,stdin,ansi,C,String,User Input,Stdin,Ansi,我有一个C程序,要求用户输入他们的名字,并在while循环中读取stdin的代码(直到按下enter)。 我确保用户只能输入32到126之间的ASCII值 问题是当我按下我的箭头(光标)键,或类似于PAGE_DOWN或其他。。。 我最终将ANSI转义序列打印到终端([A、[6~,等等) 下面是代码部分 char name[6]; char c; uint8_t i = 0; while ((c = getchar()) != '\n') { if (c == 127 || c == 8)
char name[6];
char c;
uint8_t i = 0;
while ((c = getchar()) != '\n') {
if (c == 127 || c == 8) { // Checks if backspace or del is pressed
i--;
name[i] = ' ';
} else if (c >= 32 && c <= 126) { // Only legal key presses please!
name[i] = c;
i++;
} else {
}
if ((c >= 32 && c <= 126) || c == 127 || c == 8) {
printf_P(PSTR("%c"), c);
}
}
name[5] = '\0';
move_cursor(15, 18);
printf_P(PSTR("%s"), name);
字符名[6];
字符c;
uint8_t i=0;
而((c=getchar())!='\n'){
如果(c==127 | | c==8){//检查是否按下了backspace或del
我--;
名称[i]='';
}否则,如果(c>=32&&c=32&&c,这将按预期工作。对于VT100系列的终端模拟,例如,按下向上光标键将向应用程序发送以下序列:
<ESC>[A
[A]
现在,ESC(0x1b)被剥离,因为它超出了您的有效范围。但是其他字符完全有效
因此,要去除这些字符,程序必须识别终端转义码;一个简单的规则是将转义码中的所有字符删除到下一个字母。这不会捕获所有的终端转义序列,但对于最常见的情况,它可以
在这里,您可以查看发布的代码不包含某些关键信息
要使此功能正常工作,代码需要修改与终端通信的“模式”
正常的“模式”是“煮熟”模式,其中按键回显到终端,像“退格”这样的按键由终端驱动程序处理
要启用所需的功能,“模式”必须是“原始”且“回声”必须关闭。请提供MCVE@CIsForCookies谢谢!我已添加了相应的剪接,但我正在为侦听串行com端口的终端编写代码,因此对于常规标准输出,代码有点不同。如果是分配,请不要使用用户终端。如果需要更好的UX对于生产程序来说,使用GNU readline或类似的库而不是stdio。在其他新闻中,不要使用像126、8或32这样的神奇数字。C有字符文字,请使用它们。别担心,分配不会标记代码质量。只看实现的功能。看,我们正在AVR微控制器上制作snake游戏,并且LED矩阵。在用户终端之间来回发送信息对于显示其他信息很有用。我来试一试!当你说“这不会捕获所有终端转义序列”时,这是因为一些长度不同吗?例如,大多数是“[X”形式,但向下翻页是“[6~”?@TristanBatchler不同的长度是没有问题的,因为你把所有的东西都去掉,直到下一个字母(不是数字!),但是如果在序列的结尾之前有字母,它将不会被充分剥离。但是你很少会遇到这些字母中的任何一个。太棒了!我刚刚开始尝试你的建议,它看起来已经很好了。谢谢你的回答!@ctx:Make that“删除(忽略)从转义到下一个大写字母A
-Z
、小写字母A
-Z
或~
”的所有字符,基本上涵盖POSIXy系统中的键盘输入。