How to validate numeric input C++

后端 未结 7 1973
忘了有多久
忘了有多久 2020-11-29 11:26

I\'d like to know how to limit an input value to signed decimals using std::cin.

相关标签:
7条回答
  • 2020-11-29 12:06

    I'm not trying to be rude. I just wanted to share a solution I provided which I believe is more robust and allows for better input validation.

    Please refer to: My Solution to Input Validation

    0 讨论(0)
  • 2020-11-29 12:17
    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;
            }
    }
    

    This also gives an error message with the input -1a2.0 avoiding the assignation of just -1 to i.

    0 讨论(0)
  • 2020-11-29 12:19

    Combining the techniques from the top answer here and this website, I get

    input.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;
    }
    

    Usage

    inputtest.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;
    }
    

    Sample run

    Enter an integer: a
    Invalid input.
    Enter an integer: 2b
    Invalid input.
    Enter an integer: 3
    You entered: 3.

    0 讨论(0)
  • 2020-11-29 12:20

    I tried many techniques for reading integer input from the user using the >> operator, but in a way or another all my experiments have failed.

    Now I think that getline() function (not the method with the same name on std::istream) and the strtol() function from the include cstdlib is the only predictable consistent solution for this problem. I would appreciate if someone proved me wrong. Here is something like the one I use:

    #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: Placing using namespace whatever; to the global scope may lead to broken "unity builds" (google!) on larger projects, so should be avoided. Practice to not use that way, even on smaller projects!
    • Reading integers from files is a very different matter. Raúl Roa's approach can be good for that if properly worked out. I also suggest that wrong input files should not be tolerated, but it really depends on the application.
    • Be warned that using >> and getline() in the same program on cin will lead to some problems. Use one of them only, or google to know how to handle the issue (not too hard).
    0 讨论(0)
  • 2020-11-29 12:22

    Something like:

    double a;
    cin >> a;
    

    Should read your signed "decimal" fine.

    You'll need a loop and some code to make sure it handles invalid input in a sensible way.

    Good luck!

    0 讨论(0)
  • 2020-11-29 12:25

    If the backing variable of the cin is a number, and the string provided is not a number, the return value is false, so you need a loop:

    int someVal;
    
    while(!(cin >> someVal)) {
       cin.reset();
       cout << "Invalid value, try again.";
    }
    
    0 讨论(0)
提交回复
热议问题