【问题标题】:Ignoring EOF on std::cin in C++在 C++ 中忽略 std::cin 上的 EOF
【发布时间】:2009-03-23 17:32:43
【问题描述】:

我有一个实现交互式 shell 的应用程序,类似于 Python 控制台/irb 的工作方式。现在的问题是,如果用户不小心点击了^D EOF 并且我的getline() 调用返回一个空字符串,我将其视为“无输入”并再次显示提示。

这会导致打印提示的无限循环。

现在在 Python 中,我将通过捕获 EOFError 来解决该问题,但在 C++ 中,我无法捕获任何异常,而且在 cin 上似乎没有设置来忽略 EOF。

有什么提示吗?

【问题讨论】:

    标签: c++ console stdin


    【解决方案1】:

    如果它无法读取任何内容,则设置failbit。只需在 if 条件下测试流,然后清除该位:

    if(!getline(std::cin, myline)) {
        std::cin.clear();
        std::cout << "you should enter something" << std::endl;
    }
    

    在内部,您的情况是这样的:

    • 在终端上等待字符串。终端将阻塞,直到用户发出换行符。两种可能的错误情况
      1. 用户立即按下 EOF。这将使getline 什么也不读,它会设置failbiteofbit
      2. 用户输入内容,然后按 EOF。这将使getline 消耗一些东西,然后在尝试获取下一个字符时遇到 EOF。这会导致设置 eofbit
    • 您将尝试再次阅读某些内容。提取函数将创建一个istream::sentry 类型的对象,它检查流的状态。如果设置了任何错误位,它将导致提取函数立即返回。这导致了之前的死循环。

    调用clear() 会清除所有错误位,您可以继续阅读您的资料。

    【讨论】:

      【解决方案2】:

      感谢 litb 的正确解决方案:

      if (!getline(std::cin, str)) {
          std::cin.clear();
          std::cout << std::endl;
      }
      

      【讨论】:

      • 还不能这样做。由于我不知道的原因,尽管我使用现有帐户登录,但我刚刚获得了一个新帐户:-/
      • @mitsuhiko 可能您使用不同的 openid 帐户登录。
      • 取回我的帐户。似乎 stackoverflows OpenID 委托支持有点错误
      【解决方案3】:

      getline() 函数使用以下位发出错误信号:

      • eofbit
      • 故障位
      • 坏比特

      在继续之前尝试检查这些。

      【讨论】:

      • 我可以检查它们,但我不能那样忽略 EOF。所以我不能继续使用输入流。我只能退出不是我想要的应用程序。
      • darnit,你比我快 1 分钟 :) +1
      • 不巧的是,链接链接到 istream::getline。他使用 std::getline (cplusplus.com/reference/string/getline.html) 的机会很高。
      • mitsuhiko,只要做 if(!getline(std::cin, myline)) { std::cin.clear(); std::cout
      • @litb:可能。我得到了怀疑的好处;-)
      【解决方案4】:

      http://www.horstmann.com/cpp/pitfalls.html

      您可以使用如下代码:

      while (cin)
      {  int x;
         cin >> x;
         if (cin) a.push_back(x);
      }
      

      【讨论】:

      • @ypnos 该代码旨在作为示例,而不是解决方案。无论如何,我们现在有了一个解决方案,感谢 Litb
      【解决方案5】:

      好的,在其他答案中,使用 cin.clear() 被描述为一种可能的解决方案。

      另一个技巧是,您可以使用其他方式来处理来自控制台的输入,而不是典型标准,方法是将终端设置为另一种模式,以便您可以直接处理 Ctrl+D。在 RAW 模式或其他模式下,您可以更直接地访问来自用户端的输入和控制序列(如 Ctrl+D 或 Ctrl+C),其他地方不再处理。

      一些库你可能会尝试收集更多信息(甚至节省编码时间):

      ½ 您可以在文档here 中找到有关您的问题的一些信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-12
        • 1970-01-01
        • 2016-03-07
        相关资源
        最近更新 更多