2012-03-16 42 views
3

问题:选择,给std :: cin和std ::函数getline打得不好在一起

我的程序试图混 '的std :: CIN < < ...' 和std ::函数getline,与一小撮'选择'。它有奇怪的行为,但不是典型的“你需要std :: cin.ignore”的情况。

所需的操作:

的意图是读给std :: cin(如果有的话),直到令牌“一站式”令牌遇到。无论在std :: cin中保留什么,稍后会作为对问题的回应来阅读。例如:

$ echo 'one two stop y' | ./a.out 
read 'one' 
read 'two' 
Question? y 
read 'y' 
$ 

的“一”和“二”的令牌被读,则“停”遇到这防止了“Y”被读取。只有在提出问题时,才应该阅读'y'。

实际操作:

read 'one two stop y' 
Question? read '' 
Question? read '' 
Question? read '' 
... 

程序调用 '选择' 第一,要检查是否有等待令牌,然后它使用的std :: CIN,然后的std ::函数getline。通常这就是你可能认为我需要读取待处理的'\ n'std :: getline没有读取的地方。但是select并不表示有任何等待输入,所以std :: cin忽略了它,而std :: getline获取了所有的输入。

但是,如果加了超时,它完美的作品:

tv.tv_usec = 1000; 

最后一个问题:

这是怎么回事?我犯了什么愚蠢的错误?

代码:

#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; 
} 
+0

您能否为一组输入添加预测的预期输出和实际输出? – 2012-03-16 06:26:31

回答

3

如果你有tv.tv_usec = 0,那么它只是轮询看看有没有东西。文件语句必须存在一些返回0以外的内容(表示没有可用输入的时间)。

我观察到的另一个问题是,对于tv.tv_usec和tv.tv_sec = 0,您只是检查一次以查看是否有可用的数据进行处理。如果到达选择时没有设置输入FD,则只会落入(结果为零),然后退出程序。我怀疑在电视上设置一些时间,给你一个输入设置描述符的机会。我会把选择放在一个循环中等待输入发生。程序当前写入的方式,选择只会检查一次,看看是否有输入。我有一个下面的循环的例子。

while (1) 
{ 
    FD_ZERO (&fds); 
    FD_SET (STDIN_FILENO, &fds); 
    tv.tv_sec = 0; 
    tv.tv_usec = 100; 
    result = select (STDIN_FILENO + 1, &fds, NULL, NULL, &tv); 
    // Code here to read in line if result is not zero 

} 

我会花些时间等待,或者你只是在通过循环快速旋转。有输入时选择将返回,电视将包含剩余时间。

+1

while(1)将不起作用,因为stdin上的输入是可选的。那些'一'和'两'代币可能不在那里。选择是检查。 – 2012-03-16 12:03:43

1

混合CIN和cin.getline的大多数问题都导致或法拉盛问题副作用。我不认为在这种情况下它也会有所不同。

编辑:是的,你必须使用peek来检查一个字符没有从流中提取它。

+0

是的,但没有必要冲洗。我可以等待模拟。 – 2012-03-16 12:02:32