键入字符串时带有cin的无限循环,而数字是预期的

cha*_*com 21 c++ validation cin infinite-loop

在下面的循环中,如果我们输入字符作为cin输入而不是预期的数字,那么它将进入无限循环.有人可以向我解释为什么会这样吗?

当我们使用时cin,如果输入不是数字,那么有没有办法检测到这一点以避免上述问题?

unsigned long ul_x1, ul_x2;

while (1)
{
  cin >> ul_x1 >> ul_x2;
  cout << "ux_x1 is " << ul_x1 << endl << "ul_x2 is " << ul_x2 << endl;
}
Run Code Online (Sandbox Code Playgroud)

Dou*_* T. 29

好吧,你总是会有一个无限循环,但我知道你真正想知道的是为什么cin不会在每次循环迭代时继续提示输入,导致你的无限循环自由运行.

原因是因为cin在您描述的情况下失败,并且不会再读取这些变量的输入.通过给出错误输入,cin进入失败状态并停止提示输入命令行导致循环自由运行.

对于简单验证,您可以尝试使用cin通过检查cin是否处于失败状态来验证输入.发生故障时,清除故障状态并强制流丢弃错误输入.这会将cin返回到正常操作,因此您可以提示输入更多内容.

  if (cin.fail())
  {
     cout << "ERROR -- You did not enter an integer";

     // get rid of failure state
     cin.clear(); 

     // From Eric's answer (thanks Eric)
     // discard 'bad' character(s) 
     cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

  }
Run Code Online (Sandbox Code Playgroud)

对于更复杂的验证,您可能希望首先读取字符串并对字符串执行更复杂的检查,以确保它符合您的预期.


Eri*_*c Z 9

注意

请注意以下解决方案.尚未完成清除您案例中的错误.你仍然会得到无限循环!

if (cin.fail())
{
     cout << "Please enter an integer";
     cin.clear();
}
Run Code Online (Sandbox Code Playgroud)

完整解决方案

原因是您需要清除流的失败状态,以及丢弃未处理的字符.否则,坏角色仍然存在,你仍然会得到无限循环.你可以简单地用std :: cin.ignore()来实现这一点.例如,

if (cin.fail())
{
         cout << "Please enter an integer";
         // clear error state
         cin.clear();
         // discard 'bad' character(s)
         cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Run Code Online (Sandbox Code Playgroud)

另一种方案

你也可以使用getlinestringstream实现.这是一个简短的例子.

   string input;
   while (1)
   {
      getline(cin, input);
      stringstream(input) >> x;
      cout << x << endl;
   }
Run Code Online (Sandbox Code Playgroud)