title: select, std::cin and std::getline not playing well together
body: <p><strong>Problem:</strong></p>
  
  <p>My program is trying to mix 'std::cin &lt;&lt; ...' and std::getline, with a dash of 'select'.  It has odd behavior, but is not the typical "you need std::cin.ignore" situation.</p>
  
  <p><strong>Desired Operation:</strong></p>
  
  <p>The intention is to read tokens from std::cin (if any) until the token 'stop' is encountered.  Whatever remains in std::cin is read later as a response to a question.  For example:</p>
  
  <pre><code>$ echo 'one two stop y' | ./a.out
  read 'one'
  read 'two'
  Question? y
  read 'y'
  $
  </code></pre>
  
  <p>The 'one' and 'two' tokens are read, then 'stop' is encountered which prevents the 'y' being read.  Only when the question is asked, the 'y' should be read.</p>
  
  <p><strong>Actual Operation:</strong></p>
  
  <pre><code>read 'one two stop y'
  Question? read ''
  Question? read ''
  Question? read ''
  ...
  </code></pre>
  
  <p>The program calls 'select' first, to check whether there are tokens waiting, then it uses std::cin, then std::getline.  Ordinarily this is where you might think I need to read that pending '\n' that std::getline doesn't read.  But the select does not indicate that there is any input waiting, so std::cin misses it, and std::getline gets all of it.</p>
  
  <p>However, if a timeout is added, it works perfectly:</p>
  
  <pre><code>  tv.tv_usec = 1000;
  </code></pre>
  
  <p><strong>Finally, a Question:</strong></p>
  
  <p>What is going on?  And what silly mistakes have I made?</p>
  
  <p><strong>Code:</strong></p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;sys/select.h&gt;
  
  int main (int argc, char* argv[])
  {
    // Step 1, read until 'stop'.
    struct timeval tv;
    tv.tv_sec = 0;
    tv.tv_usec = 0;
  
    fd_set fds;
    FD_ZERO (&amp;fds);
    FD_SET (STDIN_FILENO, &amp;fds);
  
    int result = select (STDIN_FILENO + 1, &amp;fds, NULL, NULL, &amp;tv);
    if (result &amp;&amp; result != -1)
    {
      if (FD_ISSET (0, &amp;fds))
      {
        std::string token;
        while (std::cin &gt;&gt; token)
        {
          if (token == "stop")
            break;
  
          std::cout &lt;&lt; "read '" &lt;&lt; token &lt;&lt; "'\n";
        }
      }
    }
  
    // Step 2, ask a question.
    std::string answer;
    do
    {
      std::cout &lt;&lt; "Question? ";
      std::getline (std::cin, answer);
      std::cout &lt;&lt; "read '" &lt;&lt; answer &lt;&lt; "'\n";
    }
    while (answer != "y");
  
    return 0;
  }
  </code></pre>