c++ - 选择、std::cin 和 std::getline 不能一起玩

标签 c++ stdin

问题:

我的程序试图将“std::cin << ...”和 std::getline 与一些“select”混合。它有奇怪的行为,但不是典型的“你需要 std::cin.ignore”的情况。

所需操作:

目的是从 std::cin(如果有的话)读取标记,直到遇到标记“stop”。 std::cin 中剩余的内容稍后将作为对问题的回答进行读取。例如:

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

'one' 和 'two' 标记被读取,然后遇到 'stop' 阻止 'y' 被读取。只有在提出问题时,才应该读“y”。

实际操作:

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

程序首先调用'select',检查是否有 token 在等待,然后它使用std::cin,然后是std::getline。通常这是您可能认为我需要读取 std::getline 未读取的未决 '\n' 的地方。但是选择并不表示有任何输入在等待,所以 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;
}

最佳答案

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

我观察到的另一个问题是,对于 tv.tv_usec 和 tv.tv_sec = 0,您只检查一次以查看是否有数据可供处理。如果到达选择时未设置输入 FD,它将直接落空(结果为零),然后退出程序。我怀疑在电视上设置一些时间,让您有机会输入可以设置描述符的内容。我会将选择放在循环中以等待输入发生。目前程序的写法,select只会检查一次,看是否有输入。我有一个下面的循环示例。

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

}

我也会花一些时间等待,否则您将很快在循环中旋转。当有输入时,select 将返回,tv 将包含剩余时间。

关于c++ - 选择、std::cin 和 std::getline 不能一起玩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9732710/

相关文章:

c++ - C++ STL 的系统级依赖

c++ - 比较两个包含字符串的 vector 的快速方法

c++ - 交换运算符+重载导致无限递归

c++ - 在 std::pair 中使用 `std::make_pair`:C++ STL

c++ - Arcsynthesis OpenGL 3.3 教程的问题 - MAKE 错误

c++ - 带数字的优化算法

swift - 允许程序从 Swift 中的标准输入或参数读取

java - 从 STDIN 读取命令并在输入时执行每个命令

c - 加载标准输入缓冲区

java - 标准输入上的 Java 和 C++ 应用程序之间的通信问题