Problem:
My program is trying to mix 'std::cin << ...' and std::getline, with a dash of 'select'. It has odd behavior, but is not the typical "you need std::cin.ignore" situation.
Desired Operation:
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:
$ echo 'one two stop y' | ./a.out
read 'one'
read 'two'
Question? y
read 'y'
$
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.
Actual Operation:
read 'one two stop y'
Question? read ''
Question? read ''
Question? read ''
...
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.
However, if a timeout is added, it works perfectly:
tv.tv_usec = 1000;
Finally, a Question:
What is going on? And what silly mistakes have I made?
Code:
#include <iostream>
#include <sys/select.h>
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 (&fds);
FD_SET (STDIN_FILENO, &fds);
int result = select (STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
if (result && result != -1)
{
if (FD_ISSET (0, &fds))
{
std::string token;
while (std::cin >> token)
{
if (token == "stop")
break;
std::cout << "read '" << token << "'\n";
}
}
}
// Step 2, ask a question.
std::string answer;
do
{
std::cout << "Question? ";
std::getline (std::cin, answer);
std::cout << "read '" << answer << "'\n";
}
while (answer != "y");
return 0;
}