1

Is it possible to use getline(cin,buffer); at the top of my program, then have a "animated menu" still running below it? For example (very basic):

#include <iostream> 
#include <string> 

using namespace std; 
int stringLen=0;
string buffer; 

getline(cin, buffer);

for (int i = 0; i < kMaxWait;i++)
{
     printf("counter waiting for user input %d",i);
     if (1 >= buffer.length())
     break; 
}

Would I have to fork that loop somehow so it would keep counting and display the counter until the user enters something??

4
  • 1
    Input blocks execution. You need threads/tasks. Commented Mar 15, 2016 at 17:06
  • Why did you tag this with fork? You seem to know it's possible using e.g. fork(). In general you would use a std::thread waiting for changes in the buffer. Commented Mar 15, 2016 at 17:28
  • I don't understand fully how fork works, so I wasn't sure if this is a scenario where I would use it Commented Mar 15, 2016 at 17:30
  • @Robolisk If you definitely want/need anoother process, you can use fork() to achieve such behavior, access to buffer.length() needs to be synchronized in any case. Commented Mar 15, 2016 at 17:33

3 Answers 3

3

One possible answer, given in the comments, is to use threads. But it's not necessary, there's a way to do this without threads.

  • Make stdin a non-blocking file descriptor.

  • Wait for stdin to become readable, via poll()/select(), in the meantime do your animation, etc...

  • Make stdin a blocking file descriptor, again.

  • Use std::getline().

There are also some ancillary issues to consider, such as the buffering that comes from std::streambuf, so before doing all that, check if there's already something to read from std::cin, first.

Sign up to request clarification or add additional context in comments.

6 Comments

So that basically proposes to use the stdin fd in a select()/poll() loop, right? That's another way.
I see what you mean, sorta. In a way, the animation block example I gave is very basic. This would actually be a fairly large file doing ascii art type animation in the command window until the user enter data ( Logs in)
Doesn't matter how extensive. The principle's the same.
This is a pretty elegant solution actually. Took me a couple of reads before I got there but finally a +1 from me.
Is this route, or using fork() more efficient?
|
1

This is something I used sometime ago. It's quite rudimentary, but you can get the gist of the process - using poll. It returns true if there is input, and puts it in str, false otherwise. So, you can put this in your loop somewhere, and take action when there is input.

bool polled_input(std::string& str)
{
    struct pollfd fd_user_in;
    fd_user_in.fd = STDIN_FILENO;
    fd_user_in.events = POLLIN;
    fd_user_in.revents = 0;

    int rv = poll(&fd_user_in, 1, 0);

    if (rv == -1) {/* error */}
    else if (rv == 0) return false;
    else if (fd_user_in.revents & POLLIN)
    {         
        char buffer[MAX_BUFF_SIZE];
        int rc = read(STDIN_FILENO, buffer, MAX_BUFF_SIZE-1);
        if (rc >= 0) 
        {
            buffer[rc]='\0';
            str = std::string(buffer);
            return true;       
        }
        else {/* error */}
    }        
    else {/* error */}
}

Comments

0

select is meant for this, multiplexed, blocking I/O. It can be done without a poll I think:

#include <iostream>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int main(int argc, char **arg)
{
   const int time_in_secs = 10;
   const int buffer_size = 1024;
   fd_set readfds;

   FD_ZERO(&readfds);
   FD_SET(STDIN_FILENO, &readfds);

   struct timeval tv;
   tv.tv_sec = time_in_secs;
   tv.tv_usec = 0;

   int ret = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);

   if (!ret)
   {
       std::cout << "Timeout\n";
       exit(1);
   }

   char buf[buffer_size];

   if (FD_ISSET(STDIN_FILENO, &readfds))
   {
        int len = read(STDIN_FILENO, buf, buffer_size);
        buf[len] = '\0';
   }

    std::cout << "You typed: " << buf << "\n";

    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.