【问题标题】:Menu input: Once invalid input is detected, all inputs are deemed invalid菜单输入:一旦检测到无效输入,则认为所有输入无效
【发布时间】:2019-09-26 19:35:58
【问题描述】:

我有一个菜单创建系统,其中包含用户可以从中选择的字符串向量,因此只有菜单选项中的整数才允许作为有效输入。

如果数字输入正确,一切正常。如果输入不正确(字符串、浮点数、负数等),则当它应该显示错误消息时,什么都不会发生。

如果尝试输入其他任何内容(有效或无效),则随后的每个输入都会出现错误消息,并且用户会被卡住。

这是我用来验证代码的循环 -

bool check = false;
string line;
std::stringstream temp;
int input;

while(!check)
{
    getline(cin, line);
    temp << line;
    temp >> std::noskipws >> input; //this is supposed to reject spaces and floats

    if(!temp.fail() && temp.eof() && input > 0 && input <= static_cast<int>(options.size()))
    {
        check = true; //returns valid value and stops loop
    }
    else //if all conditions aren't met
    {
        cin.clear();
        cin.ignore();
        cout << wrongInput << endl; //prints error
    }
}
return input; //correctly returns when valid on first try

在此之前,我只是使用 cin >> input 和 cin.fail() 进行检查,但这允许浮点数通过并且会多次显示字符串条目的错误消息。

如果有任何缺失的信息,请告诉我,但我认为这里的一切都是相关的。


编辑:只是用正确的输入测试我的程序,它开始看似任意失败。

错误输入示例:

(menu with numbered options)
intput: "abba" || "3.2" || "4 3" || "-4" || etc.
(no response)
input: "valid number"
(please enter a number from above) - repeats indefinitely

正确输入示例:

(menu with numbered options)
input: "1"
(correctly executes "1" selection, shows menu again)
input: "1"
(again correctly executes "1" selection, shows menu again)
input: "1"
(no response)
input: "1"
(please enter a number from above) - repeats indefinitely

【问题讨论】:

  • 给我们一个输入的例子。
  • 如果该行包含有效的整数值,则不会设置 eof 标志。在您尝试从“文件”末尾以外的地方读取之前,它不会设置。
  • 我还建议您考虑the &gt;&gt; operator 返回 的内容,以及如何在boolean expression 中使用流。
  • 你为什么要检查temp.eof()
  • 你也永远不会在任何时候重置temp上的错误条件

标签: c++ while-loop getline


【解决方案1】:

您显示的代码存在一些问题。让我们从不检查从std::cin 读取的状态开始。如果出现故障或用户按下文件结束序列,您将不会检测到它。

其次,std::cin 的标志不需要重置,ignore 也绝对不需要来自std::cin 的任何输入。

第三,正如我所提到的,eof 标志将不会temp 字符串流中设置。还有更好的方法来检查错误标志或eof

第四,如果不想要负数,使用unsigned整数类型,如果是负数,流提取会失败。

最后,这更多是个人意见,为什么不允许前导空间?确实没什么问题。

说了这么多,我会这样做:

unsigned input;

std::string line;
while (std::getline(std::cin, line))
{
    // Define stream inside the loop, no need to reset it when the loop iterates
    std::istringstream istr(line);

    // Attempt to extract the value, checking range
    if (istr >> input && input > 0 && input <= options.size())
    {
        // All went okay, the input is valid
        break;
    }

    // If we reach here, there was an error parsing the input
    // Or the input was out of bounds
    std::cout << wrongInput << '\n';
}

if (!std::cin)
{
    // Could not even read from standard input, consider this a fatal error
    return EXIT_FAILURE;
}

// Here the variable input contains a value that is larger than zero and smaller or equal to options.size()

如果您需要多次这样做,那么我当然建议您将上述代码放入您可以调用的自己的函数中。然后,如果出现故障,您可以返回 0 而不是 EXIT_FAILURE,以指示任何类型的错误。

【讨论】:

  • (编辑:这是其自身功能的一部分)感谢您解释一切,但我仍然遇到奇怪的失败。 i.imgur.com/KDvWPQF.png 即使在正确输入后,在显示菜单后它也会显示错误消息(以前没有这样做)。它仍然会接受浮点数和空格,然后似乎只忽略部分后续输入。在某一时刻,它只是没有响应,直到再次输入相同的条目。除了使用“endl”而不是“\n”之外,我根本没有更改您发布的内容
  • @ZJN Works fine for me。首先调用读取无效值-1,然后循环并读取它返回的有效值1。第二次调用读取无效值0,循环并返回有效值2。第三次调用读取并返回有效值3(同一输入行上的5 被静默忽略)。第四个调用读取无效值4,循环并到达EOF,并返回0 指示错误。第五个调用也未能从std::cin 读取并返回0 指示错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-30
  • 1970-01-01
  • 1970-01-01
  • 2019-04-03
  • 1970-01-01
  • 2015-12-07
相关资源
最近更新 更多