C non-blocking keyboard input

前端 未结 10 814
说谎
说谎 2020-11-22 05:59

I\'m trying to write a program in C (on Linux) that loops until the user presses a key, but shouldn\'t require a keypress to continue each loop.

Is there a simple wa

相关标签:
10条回答
  • 2020-11-22 06:30

    There is no portable way to do this, but select() might be a good way. See http://c-faq.com/osdep/readavail.html for more possible solutions.

    0 讨论(0)
  • 2020-11-22 06:31

    Here's a function to do this for you. You need termios.h which comes with POSIX systems.

    #include <termios.h>
    void stdin_set(int cmd)
    {
        struct termios t;
        tcgetattr(1,&t);
        switch (cmd) {
        case 1:
                t.c_lflag &= ~ICANON;
                break;
        default:
                t.c_lflag |= ICANON;
                break;
        }
        tcsetattr(1,0,&t);
    }
    

    Breaking this down: tcgetattr gets the current terminal information and stores it in t. If cmd is 1, the local input flag in t is set to non-blocking input. Otherwise it is reset. Then tcsetattr changes standard input to t.

    If you don't reset standard input at the end of your program you will have problems in your shell.

    0 讨论(0)
  • 2020-11-22 06:35

    Another way to get non-blocking keyboard input is to open the device file and read it!

    You have to know the device file you are looking for, one of /dev/input/event*. You can run cat /proc/bus/input/devices to find the device you want.

    This code works for me (run as an administrator).

      #include <stdlib.h>
      #include <stdio.h>
      #include <unistd.h>
      #include <fcntl.h>
      #include <errno.h>
      #include <linux/input.h>
    
      int main(int argc, char** argv)
      {
          int fd, bytes;
          struct input_event data;
    
          const char *pDevice = "/dev/input/event2";
    
          // Open Keyboard
          fd = open(pDevice, O_RDONLY | O_NONBLOCK);
          if(fd == -1)
          {
              printf("ERROR Opening %s\n", pDevice);
              return -1;
          }
    
          while(1)
          {
              // Read Keyboard Data
              bytes = read(fd, &data, sizeof(data));
              if(bytes > 0)
              {
                  printf("Keypress value=%x, type=%x, code=%x\n", data.value, data.type, data.code);
              }
              else
              {
                  // Nothing read
                  sleep(1);
              }
          }
    
          return 0;
       }
    
    0 讨论(0)
  • 2020-11-22 06:42

    You can do that using select as follow:

      int nfds = 0;
      fd_set readfds;
      FD_ZERO(&readfds);
      FD_SET(0, &readfds); /* set the stdin in the set of file descriptors to be selected */
      while(1)
      {
         /* Do what you want */
         int count = select(nfds, &readfds, NULL, NULL, NULL);
         if (count > 0) {
          if (FD_ISSET(0, &readfds)) {
              /* If a character was pressed then we get it and exit */
              getchar();
              break;
          }
         }
      }
    

    Not too much work :D

    0 讨论(0)
提交回复
热议问题