【问题标题】:Preventing ANSI Escape Characters in Keyboard Input in C防止 C 中键盘输入中的 ANSI 转义字符
【发布时间】:2017-11-02 01:58:36
【问题描述】:

我有一个 C 程序,它通过在 while 循环上从标准输入读取的一些代码询问用户他们的姓名(直到按下回车键)。 我确保用户只能输入从 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) {   // 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);

我当然选择忽略 32 到 126 范围之外的 ASCII 值,那么这是什么原因呢?有任何想法吗?干杯!

【问题讨论】:

  • 提供一个MCVE stackoverflow.com/help/mcve
  • @CIsForCookies 谢谢!我添加了适当的片段,但我正在为一个在串行 com 端口上侦听的终端进行编码,因此对于常规标准输出,代码有点不同。
  • 如果是作业,不要管用户终端。如果你想为生产程序提供更好的用户体验,请使用 GNU readline 或类似的库而不是 stdio。
  • 在其他新闻中,不要使用像 126、8 或 32 这样的幻数。C 有字符文字,请改用这些。
  • 别担心,作业不会标记代码质量。只查看实现的功能。看,我们正在 AVR 微控制器和 LED 矩阵上制作蛇游戏。在用户终端之间来回发送信息对于显示其他信息很有用。

标签: c string user-input stdin ansi


【解决方案1】:

这按预期工作。对于 VT100 系列的终端仿真,例如,按下光标向上键会将以下序列发送到您的应用程序:

<ESC>[A

现在,ESC (0x1b) 被剥离,因为它超出了您的有效范围。但其他字符完全有效。

因此,要去除这些,您的程序必须识别终端转义码;一个简单的规则是删除从转义到下一个字母的所有字符。这不会捕获所有终端转义序列,但对于最常见的情况,它会捕获。

您可以在这里查看list of common terminal control escape sequences

【讨论】:

  • 我试试看!当您说“这不会捕获所有终端转义序列”时,这是因为有些长度不同吗?例如大多数是“[X”的形式,但向下翻页是“[6~”?
  • @TristanBatchler 不同的长度是没有问题的,因为您将所有字母都剥离到下一个字母(不是数字!),但如果在序列结束之前有字母,它将不够剥离。但你很少会遇到其中之一
  • 太棒了!我刚刚开始尝试您的建议,并且看起来不错。感谢您的回答!
  • @ctx: Make that "删除(忽略)从转义到下一个大写字母A-Z、小写字母a-z的所有字符,或~",基本涵盖了POSIXy系统中的键盘输入。
【解决方案2】:

发布的代码不包含某些关键信息。

为了使这个功能起作用,代码需要修改与终端通信的“模式”。

正常的“模式”是“熟”,其中击键回显到终端,而像“退格”这样的击键由终端驱动程序处理。

要启用所需的功能,'mode' 必须是 'raw' 并且 'echo' 必须关闭。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-22
    • 2014-11-19
    • 1970-01-01
    • 1970-01-01
    • 2015-01-01
    • 1970-01-01
    相关资源
    最近更新 更多