【发布时间】:2011-07-16 09:08:57
【问题描述】:
我需要在我的程序中为 getchar() 添加一个超时函数。
我该怎么做,当我的程序到达指令 getchar() 时,它只会等待一定的时间让用户进行击键,如果用户在给定的时间限制内没有击键,程序会“跳过”getchar()?
操作系统不支持 conio.h 库,因此 kbhit 不是一个选项。
【问题讨论】:
标签: c time input timeout getchar
我需要在我的程序中为 getchar() 添加一个超时函数。
我该怎么做,当我的程序到达指令 getchar() 时,它只会等待一定的时间让用户进行击键,如果用户在给定的时间限制内没有击键,程序会“跳过”getchar()?
操作系统不支持 conio.h 库,因此 kbhit 不是一个选项。
【问题讨论】:
标签: c time input timeout getchar
这通常通过在stdin 上使用select() 来实现。另一种解决方案是使用alarm() 和一个虚拟的 SIGALRM 处理程序来中断getchar() 调用(但仅适用于 POSIX 系统)。
【讨论】:
getchar() 之前拨打alarm(duration);。另外,使用signal(SIGALRM, your_handler_func); 安装一个虚拟 sighandler,这样警报信号就不会杀死您的程序。
How to add a timeout when reading from `stdin` 我发现这个问题很有帮助。
另一种方法是使用多线程。
如果你使用的是c++11,你可以使用condition_variable::wait_for()作为定时器线程。而原来的 getchar() 被另一个线程阻塞了。
这是一个例子:
#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;
}
当有击键时,主线程会通知工作线程。
【讨论】: