【问题标题】:How to validate numeric input in C++如何在 C++ 中验证数字输入
【发布时间】:2009-02-05 03:24:42
【问题描述】:

我想知道如何使用std::cin 将输入值限制为带符号的小数。

【问题讨论】:

    标签: c++ visual-c++


    【解决方案1】:
    double i;
    
    //Reading the value
    cin >> i;
    
    //Numeric input validation
    if(!cin.eof())
    {
        peeked = cin.peek();
        if(peeked == 10 && cin.good())
        {
                 //Good!
                 count << "i is a decimal";
            }
            else
            {
                 count << "i is not a decimal";
             cin.clear();
             cin >> discard;
            }
    }
    

    这也给出了输入 -1a2.0 的错误消息,避免将 -1 分配给 i。

    【讨论】:

    • #1:discard 是什么? #2:为什么是10?麦克呢? #3:你如何形成一个循环来重试?当您编写它时,请尝试输入"ddd"。你会得到你的错误很多次。如果没有,那么我真的很好奇你的解决方案。
    • 应该是int peeked 吗? en.cppreference.com/w/cpp/io/basic_istream/peek 表示它返回一个字符或Traits:eof()
    【解决方案2】:

    如果cin的后备变量是数字,而提供的字符串不是数字,则返回值为false,所以需要循环:

    int someVal;
    
    while(!(cin >> someVal)) {
       cin.reset();
       cout << "Invalid value, try again.";
    }
    

    【讨论】:

    • play.cpp:10: 错误:“struct std::istream”没有名为“reset”的成员
    • 而且 - 如果我用 clear() 替换了 reset(),无论你是否有意 - 当给定非数字输入时,它会导致无限循环。
    【解决方案3】:

    结合来自顶级答案herethis 网站的技术,我得到了

    输入.h

    #include <ios>  // Provides ios_base::failure
    #include <iostream>  // Provides cin
    
    template <typename T>
    T getValidatedInput()
    {
        // Get input of type T
        T result;
        cin >> result;
    
        // Check if the failbit has been set, meaning the beginning of the input
        // was not type T. Also make sure the result is the only thing in the input
        // stream, otherwise things like 2b would be a valid int.
        if (cin.fail() || cin.get() != '\n')
        {
            // Set the error state flag back to goodbit. If you need to get the input
            // again (e.g. this is in a while loop), this is essential. Otherwise, the
            // failbit will stay set.
            cin.clear();
    
            // Clear the input stream using and empty while loop.
            while (cin.get() != '\n')
                ;
    
            // Throw an exception. Allows the caller to handle it any way you see fit
            // (exit, ask for input again, etc.)
            throw ios_base::failure("Invalid input.");
        }
    
        return result;
    }
    

    用法

    输入测试.cpp

    #include <cstdlib>  // Provides EXIT_SUCCESS
    #include <iostream>  // Provides cout, cerr, endl
    
    #include "input.h"  // Provides getValidatedInput<T>()
    
    int main()
    {
        using namespace std;
    
        int input;
    
        while (true)
        {
            cout << "Enter an integer: ";
    
            try
            {
                input = getValidatedInput<int>();
            }
            catch (exception e)
            {
                cerr << e.what() << endl;
                continue;
            }
    
            break;
        }
    
        cout << "You entered: " << input << endl;
    
        return EXIT_SUCCESS;
    }
    

    样品运行

    输入一个整数:a
    输入无效。
    输入一个整数:2b
    输入无效。
    输入一个整数:3
    您输入:3。

    【讨论】:

      【解决方案4】:

      cin 的 >> 运算符的工作方式是一次读取一个字符,直到遇到空格。这将吞噬整个字符串-1a2.0,这显然不是一个数字,因此操作失败。看起来您实际上有三个字段,-1、a 和 2.0。如果你用空格分隔数据,cin 将能够毫无问题地读取每一个数据。请记住为第二个字段阅读char

      【讨论】:

        【解决方案5】:

        我尝试了许多技术来使用 &gt;&gt; 运算符从用户那里读取整数输入,但在某种程度上我的所有实验都失败了。

        现在我认为 getline() 函数(不是 std::istream 上同名的方法)和 include cstdlib 中的 strtol() 函数是解决此问题的唯一可预测的一致解决方案。如果有人证明我错了,我将不胜感激。这是我使用的类似的东西:

        #include <iostream>
        #include <cstdlib>
        
        // @arg prompt The question to ask. Will be used again on failure.
        int GetInt(const char* prompt = "? ")
        {
            using namespace std; // *1
            while(true)
            {
                cout << prompt;
                string s;
                getline(cin,s);
                char *endp = 0;
                int ret = strtol(s.c_str(),&endp,10);
                if(endp!=s.c_str() && !*endp)
                    return ret;
            }
        }
        
        • *1:将using namespace whatever; 放置在全局范围内可能会导致大型项目的“统一构建”(google!)中断,因此应避免。练习不要使用这种方式,即使是在较小的项目中!
        • 从文件中读取整数是完全不同的事情。如果工作得当,Raúl Roa 的方法可能会对此有所帮助。我还建议不应该容忍错误的输入文件,但这确实取决于应用程序。
        • 请注意,在cin 的同一程序中使用&gt;&gt;getline() 会导致一些问题。只使用其中一种,或者谷歌知道如何处理这个问题(不要太难)。

        【讨论】:

          【解决方案6】:

          类似:

          double a;
          cin >> a;
          

          应该阅读您签名的“十进制”罚款。

          您需要一个循环和一些代码来确保它以合理的方式处理无效输入。

          祝你好运!

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-11-22
            • 2021-01-23
            • 2023-03-30
            • 2019-10-08
            • 1970-01-01
            相关资源
            最近更新 更多