Linux下无需按下回车(无阻塞)读取输入键值
linux常用输入函数scanf和fgets通常都是阻塞式的:
1、如果用户没有输入,则程序会阻塞等待用户输入输入内容后,且需要用户点回车键才能完成读取键盘输入。
2、用户输入的信息,会在屏幕上显示出来。
一、以下代码实现了:
1、用户没有输入,则在设定时间过后,程序会继续运行下去
2、用户输入信息不会在屏幕上显示出来
3、程序能够不等待回车,直接响应键盘输入
4、用到了system函数,会启动子进程(缺点)。
5、此种方法是使用stty命令,设置终端输入为禁止回显并忽略回车符来实现的。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 5 #define TTY_PATH "/dev/tty" 6 #define STTY_US "stty raw -echo -F " 7 #define STTY_DEF "stty -raw echo -F " 8 9 #define UNUSED_PARAMTER(X) (void)(X) 10 11 static char get_char( void ) 12 { 13 fd_set rfds; 14 struct timeval tv; 15 char input_char = 0; 16 17 FD_ZERO(&rfds); 18 FD_SET(0, &rfds); 19 20 /** 21 * Set wait time 22 */ 23 //tv.tv_sec = 0; //seconds 24 //tv.tv_usec = 500; //microseconds 25 26 /*Check for keyboard input.*/ 27 if (select(1, &rfds, NULL, NULL, &tv) > 0) 28 input_char = getchar(); 29 30 return input_char; 31 } 32 33 char nonblocking_input( void ) 34 { 35 char input_char; 36 37 system(STTY_US TTY_PATH); //Prohibit echoing,ignoring carriage returns 38 39 usleep(100); 40 input_char = get_char(); 41 42 system(STTY_DEF TTY_PATH); //Turn on echo and don't ignore carriage return 43 44 return input_char; 45 } 46 47 int main(int argc, char **argv) 48 { 49 UNUSED_PARAMTER(argc); 50 UNUSED_PARAMTER(argv); 51 52 char input_char; 53 54 input_char = nonblocking_input(); 55 56 printf("\n\tYour input is %c!\n", input_char); 57 printf("\nApplication finish.\n\n"); 58 59 return 0; 60 }
二、另外一种方法,相对于第一种方法,改进点主要有:
1、使用tcgetattr函数和tcsetattr函数代替system函数,减少子进程启动数量。
2、此种实现是通过termios来实现的,termios的实现中,有大量的参数设置,还有伪终端的说法。
代码如下:
1 #include <stdio.h> 2 #include <fcntl.h> 3 #include <termios.h> 4 #include <unistd.h> 5 6 #define UNUSED_PARAMTER(X) (void)(X) 7 8 char nonblocking_input(void) 9 { 10 char input_ch; 11 struct termios newt, oldt; 12 13 int tty = open("/dev/tty", O_RDONLY); //Open control terminal 14 15 tcgetattr(tty, &oldt); //Get terminal properties 16 newt = oldt; 17 18 //Set characters are not buffered(~ICANON) and do not echo(~ECHO). 19 //You can also choose only one of them. 20 newt.c_lflag &= ~( ICANON | ECHO ); 21 tcsetattr(tty, TCSANOW, &newt); 22 23 read(tty, &input_ch, 1); 24 tcsetattr(tty, TCSANOW, &oldt); //Restore terminal properties 25 26 return input_ch; 27 } 28 29 int main(int argc, char **argv) 30 { 31 UNUSED_PARAMTER(argc); 32 UNUSED_PARAMTER(argv); 33 34 char input_char; 35 36 input_char = nonblocking_input(); 37 38 printf("\n\tYour input is %c!\n", input_char); 39 printf("\nApplication finish.\n\n"); 40 41 return 0; 42 }