【问题标题】:Filtering out invalid user inputs过滤掉无效的用户输入
【发布时间】:2010-10-07 04:39:25
【问题描述】:

我正在尝试使用以下代码块在一个小型 C++ 程序中过滤掉无效的用户输入:

    int selection = -1;
    while (!(selection >= 1 && selection <=4))
    {   
        cin >> selection;

        if (!(selection >= 1 && selection <=4))
        {
            cout << "invalid selection!" << endl;
            cout << "selection: ";
        }
    }

当我输入任何在我想要过滤的范围之内或之外的数值时,它似乎工作正常。但是,当我输入无效值(例如大于最大可存储 int 或字符的值)时,会发生奇怪的事情。代码循环并跳过“cin”命令。

我该如何解决这个问题?

谢谢

【问题讨论】:

    标签: c++ stl validation


    【解决方案1】:

    您需要使用fail() 检测不可转换的输入,然后忽略其余的错误数据并使用clear() 重置cin 错误标志,然后再读取新的输入尝试。

    int selection = -1;
    while (!(selection >= 1 && selection <=4))
    {   
        cin >> selection;
    
        if (cin.fail() || !(selection >= 1 && selection <=4))
        {
            cout << "invalid selection!" << endl;
            cout << "selection: ";
    
            cin.clear();
    
            cin.ignore(std::numeric_limits<int>::max(), '\n');
        }
    }
    

    【讨论】:

      【解决方案2】:

      以下是解决问题的两条建议:

      1. 将错误处理添加到cin
      2. 读取为字符串并解析

      常见的解决方案是 Read As String And Parse,但我将两者都提供给您选择。

      将错误处理添加到cin

      当流提取函数接收到一个不适合数字的字符时,它会设置一个fail 位。您需要检查流的状态 (cin) 是否失败。如果要继续,则需要清除错误状态。

      可以使用fail 方法检查状态:cin.fail()。要清除状态,请使用:cin.clear()

      C++ Online Reference -- istream

      读取为字符串并解析

      另一种方法是将输入作为字符串读取,然后解析字符串以获取数据。 string 容器有一些有用的解析方法。

      使用getlinecin 中读取string 变量。

      同样,您必须编写代码来检查错误并进行处理。

      【讨论】:

        【解决方案3】:

        您需要检查cin的条件,如果是任何错误状态,您应该清除错误标志和ignore()

        int main()
        {
            int selection = -1;
            while (!(selection >= 1 && selection <=4))
            {
                if (cin >> selection)
                {
                    if (!(selection >= 1 && selection <=4))
                    {
                        cout << "invalid selection!" << endl;
                        cout << "selection: ";
                    }
                }
                else
                {
                    cin.clear();
                    cin.ignore();
                }
            }
        
            cout << selection << " selected\n";
        
            return 0;
        }
        

        另一种方法是将所有内容读取为string,然后让stringstream 进行错误检查:

        int main()
        {
            int selection = -1;
            while (!(selection >= 1 && selection <=4))
            {
                string line;
                getline(cin, line);
        
                stringstream sstr(line);
                if (sstr >> selection)
                {
                    if (!(selection >= 1 && selection <=4))
                    {
                        cout << "invalid selection!" << endl;
                        cout << "selection: ";
                    }
                }
                else
                {
                    cout << "invalid input!" << endl;
                    cout << "selection: ";
                }
            }
        
            cout << selection << " selected\n";
        
            return 0;
        }
        

        注意:您可能需要在getline() 调用之后立即输入cin.ignore(); - 取决于您是否正在读取所有未格式化的输入。

        【讨论】:

          【解决方案4】:

          您应该将 cin 读入 std::string 并从那里开始验证。首先检查该值是否为数字。

          【讨论】:

            【解决方案5】:

            例如,当您输入字母时,它会将cin 置于错误状态并留下这些字符。您需要 ignore 他们 (cin.ignore(1024, '\n')) 以便它知道继续输入下一行。

            【讨论】:

            • 我将如何使用这个忽略? cin.ignore(1024) 是什么意思?特别是 1024 部分。
            • 这告诉忽略接下来的 1024 个字符,这是错误的,因为接下来的 1024 个字符将被忽略。
            • 也许您想使用 cin.ignore(1024, '\n') 来忽略所有字符,直到找到换行符或忽略 1024 个字符
            • 呃,确实,只忽略一个换行符。
            猜你喜欢
            • 1970-01-01
            • 2020-10-11
            • 2015-09-10
            • 2011-08-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-11-05
            • 1970-01-01
            相关资源
            最近更新 更多