Santosh Sahu
Santosh Sahu

Reputation: 2244

How to make reading from `std::cin` timeout after a particular amount of time

I have written a small program,

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;
 }

Reading from std::cin is blocking hence the program waits until there is a external interrupt (like signals also) to the program or user provides some input.

How should I make statement std::cin >> n wait for some time (maybe using sleep() system call) for the user input? If user does not provide input and after the completion of stipulated time (let's say 10 seconds) the program should resume for the next instruction (i.e if (b==1) statement onwards).

Upvotes: 13

Views: 12001

Answers (5)

Amir Rasti
Amir Rasti

Reputation: 768

a clean solution based on c++ standard which is cross platform ,compact and reusable for c++11 standard and newer

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


class Time_Limited_Input_Reader{ 
public:
   std::string Input;
   void operator()(){
    Time_Limited_Input_Reader Input_Reader; 
    std::cout<<"enter inp"<<std::endl;
    std::thread Read_Input(&Time_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(){
   
   Time_Limited_Input_Reader Input_Reader;
   Input_Reader();
   std::cout<<"Input Data : "<<Input_Reader.Input<<std::endl;
}

Upvotes: 2

Shimon Doodkin
Shimon Doodkin

Reputation: 4569

might be useful:

  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;
      }
    }
  }
  

Upvotes: 0

Jeremy Friesner
Jeremy Friesner

Reputation: 73081

This works for me (note that this wouldn't work under Windows though):

#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;
}

Upvotes: 10

Emilio Garavaglia
Emilio Garavaglia

Reputation: 20730

I have a bad news for you: cin is NOT A STATEMENT. It is an object of type std::istream that remaps the standard input file that your OS maps by default to your program's console.

What blocks is not cin, but the console line editor that the console itself invokes when the standard input is read with an empty buffer.

What you are asking goes ahead of the standard input model cin is supposed to wrap, and cannot be implemented as a istream functionality.

The only clean way to do it is using the native I/O functionality of the console, to get user events, and -eventually- rely on C++ streams only after you've got some characters to be parsed.

Upvotes: 4

Mats Petersson
Mats Petersson

Reputation: 129374

There is no way to do this using standard C or C++ functions.

There are a number of ways using non-standard code, but you will most likely have to deal with input either as a string or individual keypresses, rather than being able to read input like cin >> x >> y; where x and y are arbitrary variables of any C++ type.

The easiest way to achieve this would be to use the ncurses library - in particular as you are on Linux.

The timeout function will allow you to set a timeout (in milliseconds) and you can use getstr() to read a string, or scanw() to read C scanf style input.

Upvotes: 4

Related Questions