如果cin >> num
失败,则需要从流中删除无效输入。我建议使用ignore
而不是sync
来完成此操作。原因是sync
不能保证在标准库的所有实现中删除剩余的输入。
#include <iostream>
#include <limits>
int main()
{
int num;
while (cout << "Enter a number" && !(cin >> num))
{
cin.clear(); // clear the error
// Remove input up to a new line
cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
cout << "Invalid input; please re-enter.\n";
}
}
上面的示例std::numeric_limits<std::streamsize>::max()
用于检索输入缓冲区可以容纳的最大字符数。这允许ignore()
删除尽可能多的字符,直到新行。它是惯用的 C++,并且比使用可能只是隐藏您当前遇到的问题的幻数更可取。
这很好用,但不能处理输入在数字后包含额外字符的情况。为了处理这些情况,需要对循环进行一些更改以处理额外的验证。一种选择是从 读取整行cin
,将其放入 a std::stringstream
,从中读取数字,然后进行额外验证。但是,可能需要考虑一种特殊情况 - 数字后面唯一的字符是空格的行。幸运的是,标准库提供了流修饰符std::skipws
,可以轻松处理这种情况。下面的示例显示了如何轻松做到这一点
#include <iostream>
#include <sstream>
int main()
{
int num;
for(;;)
{
std::cout << "Enter a number: " << std::flush;
std::string line;
std::getline(std::cin, line); // Read a line from console
std::stringstream text(line); // store in a string stream
char ch = 0;
if(!(text >> num).fail() && (text >> std::skipws >> ch).fail())
{
break;
}
std::cout << "Invalid input; please re-enter.\n";
}
return 0;
}
该表达式(text >> std::skipws >> ch).fail()
将跳过出现在数字之后的所有空格,然后尝试读取单个字符。如果没有可用的字符,则读取将失败,表明用户只输入了一个数字而没有输入其他内容。如果我们尝试这样做,cin
即使输入有效,它也会等待用户输入更多文本。