是否可以为std :: cin设置超时? 例如,std :: cin在10秒内没有收到任何数据 - 它会抛出异常或返回错误。
编辑:
那么来自Boost library
的计时器呢?据我所知,它是便携式库。是否有可能要求Boost库的计时器在预定义的时间段后抛出异常?我想它可以解决这个问题。
答案 0 :(得分:8)
无法以便携方式设置std::cin
的超时时间。即使采用非便携式技术,这样做也并非完全无关紧要:您需要替换std::cin
的流缓冲区。
在UNIX系统上,我会将std::cin
使用的默认流缓冲区替换为使用文件描述符0
来读取输入的自定义缓冲区。要实际读取输入,我将使用poll()
来检测输入的存在并在此函数上设置超时。根据{{1}}的结果,我会读取可用输入或失败。为了可能处理未转发到文件描述符的类型字符,但是在输入换行符之前也可以关闭缓冲完成。
使用多个线程时,您可以创建一个便携式过滤流缓冲区,它使用线程来读取实际数据,另一个线程使用定时条件变量,等待第一个线程发出信号表明它接收到数据或超时直到到期为止。请注意,您需要防止虚假唤醒以确保在没有输入时确实达到了超时。这样可以避免必须修改从poll()
读取数据的实际方式,尽管它仍然会替换std::cin
使用的流缓冲区,以使该功能可通过此名称访问。
答案 1 :(得分:2)
我只是弄清楚如何做到这一点,轮询std :: cin文件描述符。
如果发生超时并且没有发生任何事件,poll函数返回0,如果发生了某事,则返回1,如果发生错误,则返回-1。
#include <iostream>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
bool stop = false;
void intHandler(int dummy)
{
stop = true;
}
std::string readStdIn()
{
struct pollfd pfd = { STDIN_FILENO, POLLIN, 0 };
std::string line;
int ret = 0;
while(ret == 0)
{
ret = poll(&pfd, 1, 1000); // timeout of 1000ms
if(ret == 1) // there is something to read
{
std::getline(std::cin, line);
}
else if(ret == -1)
{
std::cout << "Error: " << strerror(errno) << std::endl;
}
}
return line;
}
int main(int argc, char * argv[])
{
signal(SIGINT, intHandler);
signal(SIGKILL, intHandler);
while(!stop)
{
std::string line = readStdIn();
std::cout << "Read: " << line << std::endl;
}
std::cout << "gracefully shutdown" << std::endl;
}
答案 2 :(得分:0)
这段代码使用线程来完成。
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
int main()
{
int number;
bool wasInput= false;
std::cout << "Enter a number in 10 seconds:\n";
std::thread t1([&]() {
std::cin >> number;
wasInput = true;
});
std::this_thread::sleep_for(std::chrono::seconds(10));
t1.detach();
if (wasInput)
std::cout << "\nENTERED IN TIME\nnumber = " << number << '\n';
else
std::cout << "\nTIME IS OUT\n";
return 0;
}
但是如果你运行它,你会看到即使用户输入它也会等待 10 秒 某物。所以你可以像这样改进它:
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
int main()
{
int number;
bool wasInput = false;
std::cout << "Enter a number in 10 seconds:\n";
time_t start = time(NULL);
time_t waitTime = 10;
while (time(NULL) < start + waitTime && !wasInput)
{
std::thread t1([&]() {
std::cin >> number;
wasInput = true;
});
std::this_thread::sleep_for(std::chrono::milliseconds(20));
t1.detach();
}
if (wasInput)
std::cout << "\nENTERED IN TIME\nnumber = " << number << '\n';
else
std::cout << "\nTIME IS OUT\n";
return 0;
}