【问题标题】:How to make reading from `std::cin` timeout after a particular amount of time如何在特定时间后从`std::cin`读取超时
【发布时间】:2013-09-04 07:29:16
【问题描述】:

我写了一个小程序,

int main(int argc, char *argv[])
{
    int n;
    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 读取是阻塞的,因此程序会等待,直到程序有外部中断(也像信号一样)或用户提供一些输入。

我应该如何让语句std::cin &gt;&gt; n 等待一段时间(可能使用sleep() 系统调用)以供用户输入? 如果用户没有提供输入并且在规定的时间(比如 10 秒)完成后,程序应该继续执行下一条指令(即 if (b==1) 语句开始)。

【问题讨论】:

标签: c++ linux


【解决方案1】:

一个基于 c++ 标准的干净解决方案,它是跨平台、紧凑且可重用于 c++11 标准和更新的标准

#include <iostream>
#include<thread>
#include<string>


class Timee_Limited_Input_Reader{ 
public:
   std::string Input;
   void operator()(){
    Timee_Limited_Input_Reader Input_Reader; 
    std::cout<<"enter inp"<<std::endl;
    std::thread Read_Input(&Timee_Limited_Input_Reader::Read,this);
    Read_Input.detach();
    std::this_thread::sleep_for(std::chrono::seconds(5));
    Read_Input.~thread();
   }
private:
   
   void Read(){
       Input = "nothing entered";
       
       std::cin>>Input;
       
   }
};
int main(){
   
   Timee_Limited_Input_Reader Input_Reader;
   Input_Reader();
   std::cout<<"Input Data : "<<Input_Reader.Input<<std::endl;
}

【讨论】:

    【解决方案2】:

    可能有用:

      auto read_input = [&]() {
        std::string input;
        std::cin >> input;
        return input;
      };
    
      std::future<std::string> future_input;
      while (1) {
        if (!future_input.valid())
          future_input = std::async(read_input);
    
        if (future_input.wait_for(std::chrono::milliseconds(1000)) == std::future_status::ready) {
          std::string s = future_input.get();
          if (s == "q") {
            break;
          }
        }
      }
      
    

    【讨论】:

      【解决方案3】:

      这对我有用(请注意,这在 Windows 下不起作用):

      #include <iostream>
      #include <sys/select.h>
      
      using namespace std;
      
      int main(int argc, char *argv[])
      {
          int n;
          cout<<"Before performing cin operation"<<endl;
      
          //Below cin operation should be executed within stipulated period of time
          fd_set readSet;
          FD_ZERO(&readSet);
          FD_SET(STDIN_FILENO, &readSet);
          struct timeval tv = {10, 0};  // 10 seconds, 0 microseconds;
          if (select(STDIN_FILENO+1, &readSet, NULL, NULL, &tv) < 0) perror("select");
      
          bool b = (FD_ISSET(STDIN_FILENO, &readSet)) ? (cin>>n) : false;
      
          if(b==1)
                cout<<"input is integer for n and it's correct"<<endl;
          else
                cout<<"Either n is not integer or no input for n"<<endl;
      
          return 0;
      }
      

      【讨论】:

      • Windows 等效项为 WaitForSingleObject。请注意,在 Windows 上,标准输入的 HANDLE 不固定,您必须使用 GetStdHandle 检索它。
      • 我建议使用poll(2) 而不是select
      【解决方案4】:

      我有一个坏消息要告诉你:cin 不是一个声明。它是一个 std::istream 类型的对象,它将您的操作系统默认映射到程序控制台的标准输入文件重新映射。

      阻塞的不是cin,而是当标准输入被一个空缓冲区读取时,控制台本身调用的控制台行编辑器。

      您要问的是标准输入模型 cin 应该包装的内容,并且不能作为 istream 功能实现。

      唯一干净的方法是使用控制台的本机 I/O 功能,获取用户事件,并且 - 最终 - 仅在需要解析一些字符后才依赖 C++ 流。

      【讨论】:

        【解决方案5】:

        使用标准 C 或 C++ 函数无法做到这一点。

        有很多方法可以使用非标准代码,但您很可能不得不将输入作为字符串或单独的按键来处理,而不是能够读取像 cin &gt;&gt; x &gt;&gt; y; 这样的输入,其中 x 和 @ 987654323@ 是任何 C++ 类型的任意变量。

        实现这一目标的最简单方法是使用 ncurses 库——尤其是在 Linux 上。

        timeout 函数将允许您设置超时(以毫秒为单位),您可以使用 getstr() 读取字符串,或使用 scanw() 读取 C scanf 样式输入。

        【讨论】:

          猜你喜欢
          • 2019-03-07
          • 2021-02-28
          • 2016-12-03
          • 2010-11-27
          • 1970-01-01
          • 2015-04-03
          • 2013-07-31
          • 1970-01-01
          相关资源
          最近更新 更多