使std :: cin语句自动超时

我写了这个程序

#include<iostream> using namespace std; int n; int main(int argc, char *argv[]) { std::cout << "Before reading from cin" << std::endl; // Below reading from cin should be executed within stipulated time bool b=std::cin >> n; if (b) std::cout << "input is integer for n and it's correct" << std::endl; else std::cout << "Either n is not integer or no input for n" << std::endl; return 0; } 

这里std :: cin语句将等待input的控制台,并将进入睡眠模式,直到我们提供一些input,然后按Enter键。

我希望std :: cin语句在10秒后超时(如果用户在10秒之间没有input任何数据,那么编译器会开始执行std :: cin语句下方的下一个语句。

我能够使用multithreading机制来解决它。 以下是我的代码:

 #include<unistd.h> #include<stdlib.h> #include<pthread.h> #include<iostream> using namespace std; void *thread_function(void *arg); int input_value; int main(int argc, char *argv[]) { int res; pthread_t a_thread; void *thread_result; res=pthread_create(&a_thread,NULL,thread_function,NULL); if(res!=0){ perror("Thread creation error"); exit(EXIT_FAILURE); } //sleep(10); cout<<"cancelling thread"<<endl; res=pthread_cancel(a_thread); cout<<"input value="<<input_value<<endl; exit(EXIT_SUCCESS); } void *thread_function(void *arg) { int res; res=pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); if(res!=0){ perror("Unable to set pthread to cancel enbable state"); exit(EXIT_FAILURE); } cin>>input_value; pthread_exit(&input_value); } 

但在这里我面临一个问题。 由于睡眠function,用户input数值或不使用睡眠function默认睡眠10秒。 这是我落后的地方。

我如何解决这个问题,如使用(信号,二进制信号等)。 请将您的答案与我的解决scheme(即multithreading)联系起来。

任何信息是最受欢迎的…

Solutions Collecting From Web of "使std :: cin语句自动超时"

既然你在POSIX机器上,你可以使用select来检查标准输入是否有任何内容:

 fd_set fds; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds) timeval timeout; timeout.tv_sec = 5; // A five-second timeout timeout.tv_usec = 0; int rc = select(STDIN_FILENO + 1, &fds, nullptr, nullptr, &timeout); if (rc < 0) perror("select"); else if (rc == 0) { // Timeout } else { // There is input to be read on standard input } 

使用poll (按照Basile Starynkevitch的建议),可以这样做:

 struct pollfd poller; poller.fd = STDIN_FILENO; poller.events = POLLIN; poller.revents = 0; int rc = poll(&poller, 1, 5); // Poll one descriptor with a five second timeout if (rc < 0) perror("select"); else if (rc == 0) { // Timeout } else { // There is input to be read on standard input } 

我已经尝试了一些解决方案来使这个工作,我目前的解决方案是相当hacky,但是,它适用于我在这里使用select和poll的其他解决方案失败的地方。

我的代码有时会给我一个积极的结果数据可用,但然后永远封锁std::cin.get(); 或者std::getline(std::cin, STRINGVARIABLE);

我的解决方案

 // Reset flag, initially true so that if cin blocks it will be reset bool Reset = true; // Create a c++11 thread to reset cin after a timeout of 100ms std::thread ResetThread([&Reset](void){ // This thread will wait 100ms std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Then if the reset flag is still true it will reset cin by closing and opening it if (Reset) { close(STDIN_FILENO); // TODO: Really the output of this open call should be checked for errors open("/dev/null", O_RDONLY); } }); // Now for the standard reading of cin: std::string Line; std::getline(std::cin, Line);. // If cin was read correctly the getline command will return immediately // This means that the reset flag will be set to false long before the thread tests it. Reset = false; // Finally join with the thread. ResetThread.join(); 

这段代码可以与选择或轮询方法(它在我的代码中)联合,以防止每100ms创建一个新的线程。

很明显,这段代码的合适性取决于你的项目的其他部分,但是对我来说很合适,所以我想分享一下。

– 编辑 –

在个人电脑之间移动后,似乎这个代码不像我所希望的那样健壮。 我现在只接受一个单独的阻塞的线程输入,看到我的答案在这里:

与非阻塞cin长时间战斗后,似乎唯一可靠的方法是在自己的线程内。

在这里看到我的答案实施:

https://stackoverflow.com/a/39499548/1427932