【问题标题】:Non-blocking keyboard read - C/C++非阻塞键盘读取 - C/C++
【发布时间】:2012-03-14 19:23:32
【问题描述】:

我现在正在使用以下功能。但我需要改进的是它会从键盘(在终端上)读取输入,即使它没有被按下。我需要知道它何时未被按下(空闲),以便switch case 块将落入default 部分。此时,read() 函数会一直等待,直到有用户输入。任何人都可以根据修改以下代码给出建议吗? 注意:我是一名 Java 程序员,还在学习 C/C++,所以可能很难进入我的脑海。谢谢各位。。

编辑:我找到了这个链接,并且似乎与我在 fcntl(STDIN_FILENO,F_SETFL,flags | O_NONBLOCK); 的行中寻找的内容有关。但由于我对 C 语言几乎一无所知,所以我完全不知道它在说什么。
http://www.codeguru.com/forum/showthread.php?t=367082

int kfd = 0;
struct termios cooked, raw;
char c;
bool dirty = false;

//get the console in raw mode
tcgetattr(kfd, &cooked);
memcpy(&raw, &cooked, sizeof(struct termios));
raw.c_lflag &=~ (ICANON | ECHO);
// Setting a new line, then end of file
raw.c_cc[VEOL] = 1;
raw.c_cc[VEOF] = 2;
tcsetattr(kfd, TCSANOW, &raw);

puts("Reading from keyboard");
puts("=====================");
puts("Use arrow keys to navigate");

while(true){
//get the next event from the keyboard
if(read(kfd, &c, 1) < 0)
{
  perror("read():");
  exit(-1);
}

linear_ = angular_ = 0;
ROS_DEBUG("value: 0x%02X\n", c);

switch(c)
{
  case KEYCODE_L:
    ROS_DEBUG("LEFT");
    angular_ = -1.0;
    dirty = true;
    break;
  case KEYCODE_R:
    ROS_DEBUG("RIGHT");
    angular_ = 1.0;
    dirty = true;
    break;
  case KEYCODE_U:
    ROS_DEBUG("UP");
    linear_ = 1.0;
    dirty = true;
    break;
  case KEYCODE_D:
    ROS_DEBUG("DOWN");
    linear_ = -1.0;
    dirty = true;
    break;
  default:
    ROS_DEBUG("RELEASE");
    linear_ = 0;
    angular_ = 0;
    dirty = true;
    break;
}

【问题讨论】:

  • 我建议不要直接使用 termios,而是使用 ncurses 之类的东西。 Here 是一个教程,展示了如何以非阻塞方式获取密钥。
  • 没有办法只修改上面的代码是吗?我只是想从终端读取键盘输入(忘了提)。当然,我最后的手段是学习 ncurses,但我已经很难学习 C/C++。
  • @JoachimPileborg 我用(我认为是)相关链接编辑了我的问题。你认为你知道它在说什么吗?
  • @pst 我已经用(我认为是)相关链接编辑了我的问题。你认为你知道它在说什么吗?
  • 您可以像这样使STDIN_FILENO 非阻塞,但请记住read 在没有内容可读取时会返回错误。检查errno 看看它是否是一个真正的错误或者它是否会阻塞 (errno == EWOULDBLOCK)。

标签: c++ c nonblocking keyboard-events


【解决方案1】:

OP 似乎已经回答了他们的问题:

我想我解决了我的问题。请任何人验证并让我知道这是否是正确的方法,或者它是否是完整的方法(我是否错过了任何其他添加步骤,例如再次重置它 - 如果这甚至有意义的话)。

所以我发现在进入while循环之前添加这3行:

flags = fcntl(0, F_GETFL, 0); /* get current file status flags */
flags |= O_NONBLOCK;          /* turn off blocking flag */
fcntl(0, F_SETFL, flags);         /* set up non-blocking read */

【讨论】:

    猜你喜欢
    • 2010-10-01
    • 1970-01-01
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多