首页 > 解决方案 > 为什么 getch() 在以很短的延迟调用 halfdelay() 后读取 EOF?

问题描述

我正在使用ncurseshalfdelay进行实验,并且在使用小延迟时偶然发现了一些违反直觉的行为。

以下期望来自用户的键盘输入。我不只是按下和释放一个键,而是在按下键的情况下对其进行测试,以便它应该继续打印相应的字符(更准确地说,是相应的int值)。这是我所拥有的剥离版本:

#include <ncurses.h>

int main() {
  int c = 0, d = 0, e = 0;

  initscr();
  cbreak();
  noecho();
  keypad(stdscr, TRUE);

  while ('q' != (c = getch())) {
    printw("c: %d\n", c);

    // Make sure that halfdelay returned OK. It should as the input is in the expected range ([1, 255])
    if ((d = halfdelay(1)) != OK) {
      printw("d: %d\n", d);
      return 0;
    }

    e = getch();

    printw("e: %d\n", e);
    cbreak();
  }

  endwin();
  return 0;
}

这是我构建和运行它的方式:

$ gcc -Wall -Wpedantic -lncurses file.c
$ a.out

以及运行时的输出(按住a键盘约 1 秒后):

c: 97
e: -1
c: 97
e: 97
c: 97
e: 97
c: 97
e: 97
c: 97
e: 97
c: 97
e: 97
c: 97
e: -1

问题 -1/EOF在这个输出中来自哪里?我确实注意到通过增加延迟(在我的机器上从 1 到 7)会使EOF角色完全消失。我很想了解造成这种情况的机制是什么。

标签: cncurses

解决方案


tl;dr 如果你打字太慢,你不会得到一个钥匙,getch但你会得到EOF

长版:

根据 ncurses 手册,半延迟模式意味着输入函数等到按键被按下或给定的超时间隔到期。halfdelay(1)您不仅可以将输入模式设置为半延迟,还可以将此间隔设置为 1/10 秒。这意味着如果您在 1/10 秒内没有获得密钥,该函数无论如何都会返回。

另一方面,按住一个键会创建多个按键。如果这些按键的速度太慢而无法适应您的半延迟间隔,那么您有时会用完按键并看到EOF.

EOF因此,如果您将间隔增加超过按键间隔,您可以避免得到。

要验证数字,您可以尝试找出按住某个键的键重复率是多少。它可能低于每秒 7 次。


推荐阅读