为什么 getch() 在以非常短的延迟调用 halfdelay() 之后读取 EOF?

Why does getch() read EOF after calling halfdelay() with a very short delay?

我正在使用 ncurses 进行实验,在使用 halfdelay 时,我偶然发现了一些有小延迟的反直觉行为。

以下内容需要用户的键盘输入。我不只是按下并释放一个键,而是在按下该键的情况下对其进行测试,以便它应该继续打印相应的字符(更准确地说,是相应的 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 字符完全消失。我很想了解造成这种情况的机制。

tl;博士 如果你打字太慢,你不会得到 getch 的键,而是 EOF

长版:

根据 ncurses 手册,halfdelay 模式意味着输入功能会等待,直到按下某个键或给定的超时间隔到期。 使用 halfdelay(1),您不仅可以将输入模式设置为半延迟,还可以将此间隔设置为 1/10 秒。 这意味着如果您没有在 1/10 秒内获得密钥,函数 returns 仍然有效。

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

因此,如果您将间隔增加到超过按键间隔,则可以避免得到 EOF 是很直接的。

要验证数字,您可以尝试弄清楚按住某个键的键重复率是多少。大概每秒不到7个。