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

时间:2011-05-03 02:44:00

标签: c++ validation infinite-loop cin

在下面的循环中,如果我们输入字符作为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;
}

4 个答案:

答案 0 :(得分:26)

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

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

对于简单验证,您可以尝试使用cin通过检查cin是否处于失败状态来验证输入。发生故障clear the fail时,将流强制为throw away the bad input。这会将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');

  }

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

答案 1 :(得分:9)

<强>注意

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

if (cin.fail())
{
     cout << "Please enter an integer";
     cin.clear();
}

完整解决方案

原因是您需要清除流的失败状态,以及丢弃未处理的字符。否则,坏角色仍然存在,你仍然会得到无限循环。 你可以简单地用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');
}

另一种解决方案

您还可以使用getlinestringstream来实现。这是一个简短的例子。

   string input;
   while (1)
   {
      getline(cin, input);
      stringstream(input) >> x;
      cout << x << endl;
   }

答案 2 :(得分:2)

也许,这是因为,

  1. cin是一种流媒体功能。当一个 输入非数字而不是 数字,它被忽略了。你是 提示重新进入。
  2. 即使您确实提供了数字输入, 由于您处于无限循环状态,系统将提示您输入更多信息。
  3. 你可以像这样解决这个问题: 1.创建一个函数来接受字符串输入。 2.转换后将其作为数字返回。使用strtod()进行转换。

    希望这会有所帮助:)

答案 3 :(得分:0)

另一种选择是operator!,它等同于成员函数fail()

//from Doug's answer
if ( !cin )
{
   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');
}