2

我有一个游戏,用户需要输入一定范围内的 x 和 y 坐标,一次一个。现在我的输入代码如下:

do {
    printf("\n");
    cout << "X: ";
    cin >> x;
    cout << "Y: ";
    cin >> y;
} while (cin.fail());

我是 C++ 新手,但阅读文档让我相信这是验证用户输入的可接受方法。当输入有效时它可以完美地工作,但是当输入是不同的类型(例如输入“a”)时,它会无限循环“X:Y:”。我需要做些什么不同的事情才能让它等待用户输入,就像第一次读取这些行一样?

4

2 回答 2

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测试是否成功解析整数以及是否已到达行尾(吞噬中间空白)。

于 2012-09-12T22:36:58.543 回答
4

尝试解析每个变量的最大问题是,当用户犯错时,他们的整个输入都会变得可疑。

考虑我是否跳过无效输入并输入:“3e4 40”。我的意思是“34 40”,但跳过 e 可能会变成“3 4”,然后留下“40”,或者可能会留下“4 40”。

考虑使用getline读取整行并解析它,例如使用istringstream,就像现在一样 - 任何错误都会变成错误,而不会使输入流处于奇怪的状态。

于 2012-09-12T22:41:06.047 回答