I need to add a timeout function for getchar() in my program.
What do I do so that when my program reaches the instruction getchar(), it will only wait for a certain amount of time for the user to make a keystroke and if the user does not make a keystroke within the given time limit, the program will "skip" the getchar()?
The operating system does not support the conio.h library so kbhit is not an option.
You can also use getc(stdin) instead of getchar() in the for statement to get a line of input from stdin .
In C programming, we use scanf() for formatted input, and printf() for formatted output, gets() or getchar() for unformatted input, and puts() or putchar() for unformatted output.
getchar may return any of the 256 possible characters, and it also may return EOF to indicate end-of-file, for a total of 257 different possible return values.
getchar() is a standard C function and is a safe function. you may come across non-standard function getch() or getche() if you are learning from multiple sources. Don't use them in your code.
This is usually achieved by using select()
on stdin
. Another solution would be using alarm()
and a dummy SIGALRM handler to interrupt the getchar()
call (only working on POSIX systems though).
How to add a timeout when reading from `stdin` I found this question is helpful.
Another method is using multithreading.
If you are using c++11, you can make use of condition_variable::wait_for()
as a timer thread. And the original getchar() is blocking on another thread.
Here is an example:
#include <termios.h>
#include <unistd.h>
#include <thread>
#include <chrono>
#include <iostream>
std::mutex mtx;
std::condition_variable cv;
int ch;
bool INPUT_SIGNAL = false;
void getch ( void ) {
struct termios oldt, newt;
tcgetattr ( STDIN_FILENO, &oldt );
newt = oldt;
newt.c_lflag &= ~( ICANON | ECHO );
tcsetattr ( STDIN_FILENO, TCSANOW, &newt );
ch = getchar();
tcsetattr ( STDIN_FILENO, TCSANOW, &oldt );
INPUT_SIGNAL = true;
cv.notify_one();
}
void timer ( int period ) {
for(;;) {
std::unique_lock<std::mutex> lck(mtx);
cv.wait_for(lck, std::chrono::seconds(period), []{return INPUT_SIGNAL;});
if(INPUT_SIGNAL) {
INPUT_SIGNAL = false;
std::cout << ch << "\n";
} else {
std::cout << 0 << "\n";
}
}
}
int main() {
std::thread worker(timer, 1);
for(;;) {
getch();
}
worker.join();
return 0;
}
When there is a keystroke, main thread will notify the worker thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With