我有一个游戏,用户需要在一定范围内输入x和y坐标,一次一个。现在我的输入代码如下:
do {
printf("\n");
cout << "X: ";
cin >> x;
cout << "Y: ";
cin >> y;
} while (cin.fail());
我是c ++的新手,但阅读文档让我相信这是验证用户输入的可接受方法。当输入有效时它完美地工作,但是当输入是不同类型时(例如输入“a”),它以“X:Y:”无限循环。我需要做些什么来让它等待用户输入,就像第一次读取行一样?
答案 0 :(得分:5)
您应该检查每个输入操作:
std::cout << "X: ";
if (!(std::cin >> x)) { /* error */ }
std::cout << "Y: ";
if (!(std::cin >> y)) { /* error */ }
由您决定如何处理错误。你可以提前返回,从循环中断,抛出异常......这一切都取决于。
请注意,可以循环,直到您获得可解析的内容,但如果用户关闭输入流则这很危险。最好逐行阅读并解析:
std::cout << "Please enter an integer X: ";
int x;
bool success = false;
for (std::string line; std::getline(std::cin, line); )
{
std::istringstream iss(line);
if (iss >> x >> std::ws && iss.get() == EOF) // #1
{
success = true;
break;
}
std::cout << "Sorry, please try again: ";
}
if (!success)
{
std::cerr << "Unexpected end of input stream!\n";
std::exit(1);
}
这样,如果用户在会话中间按下[Ctrl] -D,程序会立即关闭,并且不会尝试从关闭的输入流中读取更多值。
标记为#1
的行上的条件测试成功解析整数以及到达行尾(gobbling intermediate whitespace)。
答案 1 :(得分:4)
尝试解析每个变量的最大问题是,当用户犯了错误时,他们的整个输入都会变得可疑。
考虑我是否跳过无效输入并输入:“3e4 40”。我的意思是“34 40”,但是跳过e可能会产生“3 4”并且稍后会留下“40”或者可能会留下“4 40”。
考虑使用getline来读取整行并使用istringstream解析它,就像现在一样 - 任何错误都会成为错误而不会使输入流处于奇怪的状态。