C语言中的非阻塞式“按键按下”测试

4

我需要的是一个非常简单的功能:

我想测试是否按下了某个键,任何键。如果没有按下,则程序应继续运行。因此它必须是一个“非阻塞调用”。

我猜这个问题可能等价于检查键盘缓冲区中是否有任何内容。

我猜这样的函数必须存在于C语言中,但我还没有找到它。我找到的所有标准函数都是“阻塞型”,等待按键被按下后才会回答。

注意 - 我计划将其用于Windows控制台程序。

2个回答

3
在Windows中,您可以使用conio.h中的'_kbhit()'函数。该函数是非标准函数,可能在其他平台上不可用。

1

我知道这可能有点老,但是这里有一些可以运行的Linux代码。

kbhit.h:
#ifndef KBHIT_H__
  #define KBHIT_H__

  void  init_keyboard(void);
  void  close_keyboard(void);
  int   kbhit(void);
  int   readch(void); 

#endif 
  
kbhit.c:
#include "kbhit.h"
#include <termios.h>
#include <unistd.h>   // for read()

static struct termios initial_settings, new_settings;
static int peek_character = -1;

void init_keyboard(void)
{
    tcgetattr(0,&initial_settings);
    new_settings = initial_settings;
    new_settings.c_lflag &= ~ICANON;
    new_settings.c_lflag &= ~ECHO;
    new_settings.c_lflag &= ~ISIG;
    new_settings.c_cc[VMIN] = 1;
    new_settings.c_cc[VTIME] = 0;
    tcsetattr(0, TCSANOW, &new_settings);
}

void close_keyboard(void)
{
    tcsetattr(0, TCSANOW, &initial_settings);
}

int kbhit(void)
{
unsigned char ch;
int nread;

    if (peek_character != -1) return 1;
    new_settings.c_cc[VMIN]=0;
    tcsetattr(0, TCSANOW, &new_settings);
    nread = read(0,&ch,1);
    new_settings.c_cc[VMIN]=1;
    tcsetattr(0, TCSANOW, &new_settings);
    if(nread == 1) 
    {
        peek_character = ch;
        return 1;
    }
    return 0;
}

int readch(void)
{
char ch;

    if(peek_character != -1) 
    {
        ch = peek_character;
        peek_character = -1;
        return ch;
    }
    read(0,&ch,1);
    return ch;
}
main.c:
#include "kbhit.h"
#define Esc 27
int main(void)
{
 init_keyboard(); // for kbhit usage
 do {
   if(kbhit())
     {
      ch = tolower(readch());
      if(ch == Esc || ch == 'q') break;
      if(ch=='s') GetNewTimerValue(TIMER_1);
      if(ch=='f') GetNewTimerValue(TIMER_2);
      if(ch=='l') {rotateFields();}

     }
   usleep(330000);
  } while(1);

 close_keyboard();
return 0;     
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接