且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

非阻塞键盘读取 - C / C ++

更新时间:2022-10-27 09:04:20

(由OP在一个问题回答的编辑,改造成社区维基回答,见Question没有答案,但问题的评论解决)

在OP写道:


  

我想我解决我的问题。请,任何人,核实并让我知道这是做正确的方式,或者是完整的方式做到这一点(我错过任何其他附加步骤如再回来 - 如果,即使是有道理的重置它)。


  
  

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


块引用>
 标志=的fcntl(0,F_GETFL,0); / *获取当前文件状态标志* /
标志| = O_NONBLOCK; / *关闭阻塞标志* /
的fcntl(0,F_SETFL,旗); / *设置了非阻塞读* /

I got this following function with me working now. But what I need to improve is that it would read input from the keyboard (on the terminal) EVEN THOUGH IT IS NOT BEING PRESSED. I need to know when it is NOT pressed (idle) so that the switch case block will fall into the default section. At this point, the read() function waits until there's an input from the user. Can anyone give a suggestion just based on modifying this following code? NOTE: I'm a Java programmer, and still learning C/C++ so it might be hard to get in my head a little bit. Thanks guys..

EDIT: I found this link, and seems to have something related to what i'm looking for at the line of fcntl(STDIN_FILENO,F_SETFL,flags | O_NONBLOCK); . But since I barely know anything in C, I completely have no Idea what it's saying, yet.
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;
}

(Answered by the OP in a question edit. Transformed into a Community Wiki Answer. See Question with no answers, but issue solved in the comments )

The OP wrote:

I think I solved my problem. Please, anyone, verify and let me know if this is the right way to do it, or is it the complete way to do it (am I missing any other addition step e.g. resetting it back again -if that even makes sense) .

So what i found is to add this 3 lines before entering the while loop:

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 */