Abruzzo Forte e Gentile
Abruzzo Forte e Gentile

Reputation: 14869

stop reading from stdin

I am writing a simple console application in LInux/C++ that accepts user input from command line. I am using std::getline( std::cin ) / std::cin >> text in a thread.

After 10 seconds I would like to stop accepting console input and write a text message then do other things. I am using a separate thread for the timer.

This approach doesn't work since I cannot check that 10 seconds have elapsed until the user has not inserted any text.

Is there any better way to stop the application accepting text and go to another piece of line? I was thinking to use settimer and signals programming but I would like something to call from a different thread for simplicity.

Regards

AFG

Upvotes: 3

Views: 1800

Answers (3)

Abruzzo Forte e Gentile
Abruzzo Forte e Gentile

Reputation: 14869

It works nice but a small piece of code is needed that 'consumes' the byte.

Below the usage of your kbhit():

 int main(int argc, const char** argv ){
     while( !kbhit() ){
        // do whatever you want here while
        // entering the text
        std::cout << "..while you write!" << std::endl;
     } // stops when you hit 'ENTER'
     std::string line;
     std::getline( std::cin, line ); // consume/stores into line
     // what was written until hitting 'ENTER'
 }

Upvotes: 0

Jay
Jay

Reputation: 14461

A thread is overkill for this. In your input loop use select() to determine if stdin is ready for reading. You can check the time via a call to time() and exit the loop if 10 seconds have elapsed.

Upvotes: 2

user195488
user195488

Reputation:

You can use ncurses or if you don't want to, you can use select as described in this blog post. Basically, you can use select and specify the timeout. If the stdin FD is set, then you can read from it safely and won't block. If you want more info on select, check this out and of course Wikipedia. It's a handy call to know about. For example,

// if != 0, then there is data to be read on stdin

int kbhit()
{
    // timeout structure passed into select
    struct timeval tv;
    // fd_set passed into select
    fd_set fds;
    // Set up the timeout.  here we can wait for 1 second
    tv.tv_sec = 1;
    tv.tv_usec = 0;

    // Zero out the fd_set - make sure it's pristine
    FD_ZERO(&fds);
    // Set the FD that we want to read
    FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
    // select takes the last file descriptor value + 1 in the fdset to check,
    // the fdset for reads, writes, and errors.  We are only passing in reads.
    // the last parameter is the timeout.  select will return if an FD is ready or 
    // the timeout has occurred
    select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
    // return 0 if STDIN is not ready to be read.
    return FD_ISSET(STDIN_FILENO, &fds);
}

See also this SO question on Peek stdin using pthreads

Upvotes: 6

Related Questions