简体   繁体   中英

validate integer input C++?

I use !(cin >> input) to validate integer input, but it does not catch other datatypes such as floats. Instead it takes the first whole number. EG:

Please enter a number: 2.5.

My error message appears here, it is suppose to loop round but it takes first number instead.

Outputs "2"

How do I get it to ignore decimal input?

The input stream considers anything starting with a sign followed by at least one decimal digit to be a valid integer input. If you want to fail on a decimal input including a decimal point, you need to do something different. One way to deal with this to read an integer and see if the character following the successful read of an integer is a decimal point:

if (!(std::cin >> value)
    || std::cin.peek() == std::char_traits<char>::to_int_type('.')) {
    deal_with_invalid_input(std::cin);
}

As Thomas Matthews correctly pointed out, the problem isn't really limited to floating point numbers but anything with a prefix of digits followed by a non-space (and not EOF: the above solution would actually miss a valid integer at the very end of a file, ie, not followed by anything, not even a newline). To only read integers followed by a space or at the end of a file, something like this would be in order:

if (!(std:cin >> value)
    || (!std::isspace(std::cin.peek())
        && std::cin.peek() != std::char_traits<char>::eof())) {
    deal_with_invalid_input(std::cin);
}

There isn't really any way to return the already read characters. Since this isn't really nice to be used in many places, it may be reasonable to package this function into a suitable std::num_get<char> facet and imbue() the stream with a corresponding std::locale . This is a bit more advanced although the expression to deal with the code is actually simpler.

You will need to read the full input before validating it. You could use cin.getline() or getline() to do that, then check to see if the input is what you want.

You are trying to read different types of values using cin.

istream overload the >> operator to match the type of data you are expecting from input, and cin is a instance of the istream class.

When the expected type is an integer, it will consume character up to a string which can be converted to an integer, and leave the remaining characters in the stream for later parsing. The same happens with a float value, or with other simple types. See this reference page for more details on the operator and the types it supports out of the box. The bottom line is that if you want to have an integer value, but are expecting a float value from input, you must use the correct type of value you want to parse from input (here float), and do any needed conversion later on (here use trunc , floor , ceil or whichever rounding function that match your needs).

Here's a simple example:

#include <iostream>
#include <string>

using namespace std;

int main() {

    float f;
    string str;

    cout << "please enter a float :";
    cin >> f;

    cout << "value entered : " << f << endl;

    cout << "stream error : " 
         << (cin.fail() ? "yes" : "no") 
         << endl;

    cin >> str;

    cout << "remaining data : " << str << endl;

}

This very simple program demonstrate the use of the >> operator on istream, specifically with an expected float value. For the following input: "1.2345Z6789" (note the Z in the middle of the number), the program will parse the value "1.2345" and have "Z6789" remaining in the input buffer, available for a subsequent read.

If you replace the type of f from float to int , the program, on the same input, would read the value "1", and have ".2345Z6789" remaining in the input buffer.

Note: In your code, you are using the ! operator to test the state of the stream, which is equivalent to the fail method, which I used in my example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM