有限制的 cin.ignore 是否继续丢弃新输入?

Does cin.ignore with a limit continue discarding new input?

我正在尝试学习 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<streamsize>::max()) 语句上。我可以继续输入内容(包括换行符),程序永远不会超出该语句。

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


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

您的代码正在清除所有错误标志,然后丢弃其他字符,直到达到 numeric_limits<streamsize>::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()->in_avail() 可能是一个更简单的解决方案,因为它会完全丢弃流中可供读取的字符数。