C non-blocking keyboard input
As already stated, you can use sigaction
to trap ctrl-c, or select
to trap any standard input.
Note however that with the latter method you also need to set the TTY so that it's in character-at-a-time rather than line-at-a-time mode. The latter is the default - if you type in a line of text it doesn't get sent to the running program's stdin until you press enter.
You'd need to use the tcsetattr()
function to turn off ICANON mode, and probably also disable ECHO too. From memory, you also have to set the terminal back into ICANON mode when the program exits!
Just for completeness, here's some code I've just knocked up (nb: no error checking!) which sets up a Unix TTY and emulates the DOS <conio.h>
functions kbhit()
and getch()
:
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <termios.h>
struct termios orig_termios;
void reset_terminal_mode()
{
tcsetattr(0, TCSANOW, &orig_termios);
}
void set_conio_terminal_mode()
{
struct termios new_termios;
/* take two copies - one for now, one for later */
tcgetattr(0, &orig_termios);
memcpy(&new_termios, &orig_termios, sizeof(new_termios));
/* register cleanup handler, and set the new terminal mode */
atexit(reset_terminal_mode);
cfmakeraw(&new_termios);
tcsetattr(0, TCSANOW, &new_termios);
}
int kbhit()
{
struct timeval tv = { 0L, 0L };
fd_set fds;
FD_ZERO(&fds);
FD_SET(0, &fds);
return select(1, &fds, NULL, NULL, &tv) > 0;
}
int getch()
{
int r;
unsigned char c;
if ((r = read(0, &c, sizeof(c))) < 0) {
return r;
} else {
return c;
}
}
int main(int argc, char *argv[])
{
set_conio_terminal_mode();
while (!kbhit()) {
/* do some work */
}
(void)getch(); /* consume the character */
}
How do you do non-blocking console I/O on Linux in C?
You don't, really. The TTY (console) is a pretty limited device, and you pretty much don't do non-blocking I/O. What you do when you see something that looks like non-blocking I/O, say in a curses/ncurses application, is called raw I/O. In raw I/O, there's no interpretation of the characters, no erase processing etc. Instead, you need to write your own code that checks for data while doing other things.
In modern C programs, you can simplify this another way, by putting the console I/O into a thread or lightweight process. Then the I/O can go on in the usual blocking fashion, but the data can be inserted into a queue to be processed on another thread.
Update
Here's a curses tutorial that covers it more.
Non-blocking console input C++
I would do this by creating separate a thread which calls normal blocking IO functions and pass it a callback function which it would call when it got input. Are you sure you need to do what you said you want to do?
As for outputting information at the same time, what would happen if the user was in the middle of typing some input and you printed something?
Non blocking input C
When time ran out have timeleft()
set a global flag, which is tested by questions()
, and if set makes the code leave the while (1)
loop.
Make sure access to the flag is protected using a mutex.
Talking about "protected access": key
is accessed concurrently without protection. Not good.
Non-Blocking i/o in c? (windows)
From the documentation for _kbhit()
:
The
_kbhit
function checks the console for a recent keystroke. If the function returns a nonzero value, a keystroke is waiting in the buffer. The program can then call_getch
or_getche
to get the keystroke.
So, in your loop:
while (true) {
// ...
if (_kbhit()) {
char c = _getch();
// act on character c in whatever way you want
}
}
So, you can still use _getch()
, but limit its use to only after _kbhit()
says there is something waiting. That way it won't block.
Non-blocking ReadConsoleInput
This is all documented in ReadConsoleInput. You can determine if there is a console input with GetNumberOfConsoleInputEvents. And you are able to to determine the type of console input events with PeekConsoleInput.
So GetNumberOfConsoleInputEvents is all you need.
You can also use WaitForSingleObject with the console handle to wait for a next available input. This is also documented in ReadConsoleInput
Cin without waiting for input?
It's sad that there is no simple portable way to checking asynchronously if a key was hit. But I guess that the standard committee has carefully evaluated the pros and cons.
If you don't want to rely on third party event management libraries, and if multithreading would be overkill, one alternative could be to have your own version of kbhit()
, with conditional compiling for the environments you want to support:
- if your conio.h supports kbhit() just use it.
- for windows, you can refer to _kbhit()
- for linux and posix, you can use Matthieu's answer, or look here for Morgan Mattews's code
It's not the most academic answer, but it's pragmatic.
Related Topics
How to Read Until Eof from Cin in C++
Is It Legal to Recurse into Main() in C++
A Free Tool to Check C/C++ Source Code Against a Set of Coding Standards
Initializing Fields in Constructor - Initializer List VS Constructor Body
Why Is C++11'S Pod "Standard Layout" Definition the Way It Is
C++ "Cin" Only Reads the First Word
Why Do Std::Shared_Ptr≪Void≫ Work
Do Jagged Arrays Exist in C/C++
Is There Any Reason to Use This-≫
Can Standard Container Templates Be Instantiated With Incomplete Types
Mixing Cout and Printf For Faster Output
Why Doesn't C++ Use Std::Nested_Exception to Allow Throwing from Destructor
Why Is ++I Considered an L-Value, But I++ Is Not
Is Sizeof in C++ Evaluated At Compilation Time or Run Time