我正在try 实现一个非阻塞键盘输入,支持INKEY$/my BASIC interpreter.在阅读这里的(许多!)帖子时,我发现了似乎是canonical solution under POSIX的东西:

static int getkey(void)
{
  int c;
  static struct termios oldState, newState;
  if (tcgetattr(STDIN_FILENO, &oldState) == -1)
    return 0;
  newState = oldState;
  newState.c_lflag &= ~ICANON;  // use noncanonical input
  newState.c_lflag &= ~ECHO;    // disable echo
  newState.c_cc[VMIN]  = 1;     // minimum chars to wait for
  newState.c_cc[VTIME] = CTIME; // minimum wait time
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &newState) == -1)
    return 0;
  c = getchar();
  if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &oldState) == -1)
    return 0;
  return c;
}

当newState.c_cc[VMIN] = 1时,它会停止并等待,但会按预期工作.将其更改为0可以阻止它等待,但也会导致c永远不为非零.我判断了tcsetattr是否失败,返回0 - nope,一切正常.

有没有人真的能在现代风格的MacOS上使用这个软件?我用的是12.7.1和Xcode 14.2,但我怀疑这个代码有没有变化,因为按钮仍然是蓝色的和脉动的.

附注:需要注意的是,ECHO标志在Xcode控制台中似乎没有效果,但在终端中确实如预期的那样工作.我想这并不完全令人惊讶.

推荐答案

一些问题...

  1. 您只想在初始化期间呼叫tcsetattr once(使用TCSANOW).
  2. VMIN设置为0,并将VTIME设置为0.
  3. 别用getchar.不要将原始的tty输入与stdio混为一谈.请改用read.
  4. 您可以使用cfmakeraw,可能需要进行一些额外的调整.
  5. 根据所使用的选项(例如,ECHOOPOST等),您可能必须对输入字符进行自己的 echo 才能输出.

以下是一些示例代码(未编译或测试):

struct termios tio_save;

void
ttyinit(int fd)
{
    struct termios tio;

    tcgetattr(fd,&tio);
    tio_save = tio;

    cfmakeraw(&tio);
    tio.c_cc[VMIN] = 0;
    tio.c_cc[VTIME] = 0;

    tcsetattr(fd,TCSANOW,&tio);
}

void
ttyrestore(int fd)
{

    tcsetattr(fd,TCSAFLUSH,&tio_save);
}

int
getkey(int fd)
{
    unsigned char buf[1];
    int len;

    len = read(fd,buf,1);

    if (len > 0)
        len = buf[0];

    return len;
}

C++相关问答推荐

如何在C中通过转换为char * 来访问float的字节表示?

为指针 struct 创建宏

GCC不警告隐式指针到整数转换'

将数据移动到寄存器时出现分段故障

如何在C中只对字符串(包含数字、单词等)中的数字进行重复操作?

GTK函数调用将完全不相关的char* 值搞乱

==284==错误:AddressSaniizer:堆栈缓冲区下溢

等同于铁 rust 的纯C语言S未实现!()宏

For循环中的变量行为不符合预期.[C17]

#定义SSL_CONNECTION_NO_CONST

将字符串数组传递给C中的函数:`str[dim1][str_size]`vs`*str[dim1]`

在C++中允许使用字符作为宏参数

C中的回文数字

*S=0;正在优化中.可能是GCC 13号虫?或者是一些不明确的行为?

如何使用WRITE()以指针地址的十六进制形式写入标准输出

区分MySQL C界面中的文本和BLOB字段

在我的函数中实现va_arg的问题

无法理解 fgets 输出

std::malloc/calloc/realloc/free 与纯 C 的 malloc/calloc/realloc/free 有什么不同

快速准确计算double的小数指数