【问题标题】:Does cin.ignore with a limit continue discarding new input?带有限制的 cin.ignore 是否会继续丢弃新输入?
【发布时间】:2015-09-22 23:24:27
【问题描述】:

我正在尝试学习 C++,但由于一些我无法理解的 cin 行为而陷入了困境。这是我的代码:

#include <iostream>

using namespace std;

int main()
{
    int num;

    // Get valid input
    do
    {
        if (!cin)
        {
            // Clear error state and flush any garbage input
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max());
        }

        cout << "Please enter a number: ";
        cin >> num;
    } while (!cin);

    // Echo back what we heard
    cout << "You entered: " << num << "\n";

    cin.get();
}

这里的问题是,当我第一次输入无效输入(例如一些字母字符)时,程序会卡在 cin.ignore(numeric_limits&lt;streamsize&gt;::max()) 语句上。我可以继续输入内容(包括换行符),但程序永远不会超过该语句。

据我了解,这表明如果 cin.ignore 的第一个参数超过缓冲区的当前大小,那么任何未来的字符(直到提供的限制)都将继续被丢弃。这个对吗?如果正确的话,如何在不影响以后输入的情况下清空输入缓冲区?


注意:由于某种原因,使用cin.ignore(numeric_limits&lt;streamsize&gt;::max(), '\n'),并在cin &gt;&gt; num 之后添加cin.ignore() 会使代码正常工作。这只是为了澄清我知道这种可能性存在,但我仍然有兴趣了解上面代码中出了什么问题(未指定 \n 分隔符)。

【问题讨论】:

  • 您将无限期地丢弃字符(很多),直到达到 max() 限制或找到 EOF。
  • @MarcoA。假设我输入了sdqwd 而不是数字。缓冲区现在处于失败状态,其中有 6 个字符(我的垃圾和换行符)。一旦ignore 删除所有这些,它不会命中EOF吗?
  • 不,当你输入文件结束符时(通常是Ctrl-Z)
  • @MarcoA。啊,所以我误解了输入流何时结束。那么如何清除缓冲区中的内容呢?
  • 您使用 ignore 刷新缓冲区,但由于您输入的是数字(并且使用了换行符),因此您应该丢弃直到找到换行符。 clear() 只会重置错误标志

标签: c++ stdin


【解决方案1】:

您的代码正在清除任何错误标志,然后丢弃其他字符,直到达到numeric_limits&lt;streamsize&gt;::max()EOF 字符的硬限制(您通常可以使用 Ctrl+Z 输入一个)。因此,正如您所怀疑的,它会不断丢弃您的输入。

您的代码的固定版本可能会丢弃字符,直到找到换行符

#include <iostream>
#include <limits>

using namespace std;

int main()
{
  int num;

  // Get valid input
  do
  { 
    if (cin.fail())
    {
      // Clear error state and flush any garbage input
      cin.clear();
      cin.ignore(numeric_limits<streamsize>::max(), '\n');
    }

    cout << "Please enter a number: ";
    cin >> num;

  } while (cin.fail());

  // Echo back what we heard
  cout << "You entered: " << num << "\n";

  cin.get();
}

Live Example

并且可能是更惯用和紧凑的版本

#include <iostream>
#include <limits>
using namespace std;

int main()
{
  int num;

  // Get valid input
  while( (cout << "Please enter a number: ") && !(cin >> num) )
  {
    cout << "Invalid number entered" << endl;
    // Clear error state and flush any garbage input
    cin.clear();
    cin.ignore(cin.rdbuf()->in_avail());
  }

  // Echo back what we heard
  cout << "You entered: " << num << "\n";

  cin.get();
}

Live Example

正如您所说,cin.rdbuf()-&gt;in_avail() 可能是一个更简单的解决方案,因为它会准确丢弃流中可读取的字符数。

【讨论】:

  • 接受这一点,因为这可能是正确的做法。我刚刚发现cin.ignore(cin.rdbuf()-&gt;in_avail()); 也可以使用 :)
  • 这可能是一个更简单的解决方案:它将清除缓冲区中的字符数,而无需进行任何手动计数。为了完整起见,我将对其进行编辑
猜你喜欢
  • 1970-01-01
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 2017-04-24
  • 1970-01-01
  • 2013-05-27
  • 2011-03-09
  • 2021-03-18
相关资源
最近更新 更多