【问题标题】:Setting up a loop waiting for user input (C++)设置循环等待用户输入(C++)
【发布时间】:2020-04-16 23:13:52
【问题描述】:

我正在尝试让一个简单的井字游戏程序在控制台中运行,以确保我理解循环和数组。

它可以按预期编译和运行,但如果用户输入的不是数字,则程序会无限循环第一个 if 语句,而没有机会添加新的输入。我真的不知道如何解决这个问题。

我认为问题在于 chosenSquare 是一个整数,因为它需要与值进行比较,但 cin 可以接受任何内容。预期的行为是检查输入是否为 0 到 8 之间的整数(板上的 9 个空格),如果没有返回消息并重复,等待新的输入。

有一个简单的解决方法吗?在我了解基础知识的同时,我现在正在尝试避免使用专业包和命名空间。我看过类似的问题,但没有关注。

谢谢。

代码sn-p:

 // Input loop
    bool valid = false;
    while (valid != true)
    {
        int chosenSquare = 0;
        cout << "Player " << currentPlayer << ", enter a number between 1 and 9:" << endl;
        cin >> chosenSquare;
        chosenSquare--; // For array indexing

        if ((chosenSquare < 0) || (chosenSquare > 8)) // <--- PROBLEM IS THIS LOOP
        {
            cout << "Invalid input. Try again." << endl;
            continue;
        }
        else if ((board[chosenSquare] == currentPlayer) || (board[chosenSquare] == lastPlayer))
        {
            cout << "Square not availible. Try again." << endl;
            continue;
        }
        else
        {
            board[chosenSquare] = currentPlayer;
            valid = true;
            break;
        }
    }

【问题讨论】:

    标签: c++


    【解决方案1】:

    有几件事最终导致了这种情况。

    首先是当一个字母字符被放入控制台时,错误位被设置,0 is written to the variable you're writing to:

    您想要观察的行为在 2011 年发生了变化。在那之前:

    如果提取失败(例如,如果在需要数字的地方输入了字母),则值保持不变并设置失败位。

    但是从 C++11 开始:

    如果提取失败,则将零写入 value 并设置 failbit。 [...]

    (来自cppr。)

    这意味着chosenSquare 在读取之后是0,所以chosenSquare-- 变为-1。如您所知,-1 小于 0,因此第一个 if 语句为真。

    至于为什么会一直这样,你需要clear the fail-bit

    【讨论】:

    • 谢谢你,这解释了行为。我仍在努力了解溪流。我设法修复了代码(答案如下),但我实际上并不了解 what 修复了它。据我所知,cin.fail() 是对流中故障位的测试,即使当时它是 -1 而不是 0,它似乎也会触发。看来我需要clear()ignore(),但目前还不清楚为什么。编辑:所以 failbit 独立于流的内容(或它的变量?),这更有意义。
    • “所以 failbit 独立于流的内容”我相信这是正确的。 “这更有意义。”是的,流可能需要一段时间才能掌握。我仍在努力了解它们的所有细节。
    【解决方案2】:

    所以我在阅读和实验后改变了第一个循环:

    if (cin.fail()) // <--- PROBLEM IS THIS LOOP
            {
                cout << "Invalid input. Try again." << endl;
                cin.clear();
                cin.ignore();
                continue;
            }
    

    这可行,但我无法弄清楚它实际上在做什么。

    谁能详细说明?

    【讨论】:

    • 您希望能够读取用户提供的任何输入,无论是不是数字,然后对其进行处理以查看它是否有效。但这不是您的代码所做的。它只是读取一个整数。如果您想读取一行然后分析它以查看它是否是有效数字,请编写执行此操作的代码。它更简单,更清晰。
    • @DavidSchwartz 这就是我想要做的?还是在这里学习。据我所知fail() == true 表示输入不是整数,所以我可以发出警告。 clear() 删除了故障位(不要像我想的那样清空流),ignore() 删除仍在流中的任何内容,因此它不会陷入无限循环。是这样吗?这真的很难让我明白。我知道它不优雅,但它确实是我尝试制作的第二个程序。
    • ignore() 去除流中仍然存在的内容 不太正确。 ignore() 只删除一个字符。您可能想要的是删除用户按下回车的所有内容。在this documentation page for ignore 中有一个如何做到这一点的示例。 C++ 是一种通过反复试验来学习的粗略语言。在使用函数之前阅读文档,你会更容易使用它。也就是说,请按照 David 的建议将输入读取为更宽容的类型,例如 std::string、验证和转换。
    • @Willow 是的,但是您正在尝试解决编写的代码无法执行您想要执行的操作。编写代码来做你真正想做的事情要容易得多。如果您想读取一行输入并对其进行解析以查看它是否有效,那么编写专门执行此操作的代码将变得更加容易和清晰。当复杂函数完全按照您的要求执行时,它们会很棒,但如果它们不是您真正想要的,您应该从稍微简单的函数中推出您自己的函数。
    猜你喜欢
    • 2021-12-08
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多