Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

linux

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).

like image 663
Santosh Sahu Avatar asked Aug 31 '13 19:08

Santosh Sahu


2 Answers

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.

like image 161
Emilio Garavaglia Avatar answered Sep 23 '22 09:09

Emilio Garavaglia


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;
}
like image 35
Jeremy Friesner Avatar answered Sep 24 '22 09:09

Jeremy Friesner