简体   繁体   中英

How to make an integer validation function that does not accept floating point values?

getRegionTotal() is the function I'm using for validation right now. It works pretty well in that if the user enters something like "twenty" or -7, it will not accept that and it will keep asking for new values until it gets one that is valid. However if the user enters 60.7 for the number of accidents in the north region, it will accept 60 and drop the .7 part. Then it will give both the regular instructions and the more specific instructions when it asks for the number of accidents in the south region.

//These will hold the number of accidents in each region last year
int northTotal = 0;
int southTotal = 0;
int eastTotal = 0;
int westTotal = 0;
int centralTotal = 0;

//passing 0 for northTotal, southTotal etc. because main doesn't know
//values of them until the function returns a value. When it returns a value
//it will go into the variables on the left. getRegionTotal will get the number
//of accidents for a region from the user and prompt the user using the string that
//is in the first argument.
northTotal = getRegionTotal("North", northTotal);
southTotal = getRegionTotal("South", southTotal);
eastTotal = getRegionTotal("East", eastTotal);
westTotal = getRegionTotal("West", westTotal);
centralTotal = getRegionTotal("Central", centralTotal);


int getRegionTotal(string regionName, int regionTotal)
{
    //instructs user to enter number of accidents reported in a particular region
    cout << "\nNumber of automobile accidents reported in " << regionName << " " << cityName << ": ";
    //while regionTotal is not an integer or regionTotal is negative
    while (!(cin >> regionTotal) || (regionTotal < 0) )
    {
        //give user more specific instructions
        cout << "\nPlease enter a positive whole number for the number of\n";
        cout << "automobile accidents in " << regionName << " " << cityName << ": ";
        cin.clear(); //clear out cin object
        cin.ignore(100, '\n'); //ignore whatever is in the cin object
                                //up to 100 characters or until
                                // a new line character
    }
    //returns a valid value for the number of accidents for the region
    return regionTotal;
}

Parse the whole line and make sure you've consumed the whole line.

With iostreams:

#include <iostream>
#include <sstream>
#include <string>

for (std::string line; std::getline(std::cin, line); )
{
    std::istringstream iss(line);
    int result;

    if (!(iss >> result >> std::ws && iss.get() == EOF))
    {
        // error, die. For example:

        std::cout << "Unparsable input: '" << line << "'\n";
        continue;
    }

    // else use "result"
}

With stdlib:

#include <errno>
#include <cstdlib>

char const * input = line.c_str();   // from above, say
char * e;
errno = 0;

long int result = std::strtol(input, &e, 10);

if (e == input || *e != '\0' || errno != 0)
{
    // error
}

The two approaches are fundamentally identical, but the former may be more "idiomatic C++". That said, if you already have an existing string, the strtol -approach is a neat alternative, since it gives you precise error handling: did you consume the whole string (if not, e points to the next character); did you consume any of the string (if not, e points to the beginning); was there an overflow or underflow (check errno ). On the other hand, the iostreams approach lets you consume trailing whitespace (thanks to >> std::ws ), which the strtol -solution doesn't.

There's also std::stol which wraps strtol (and similarly for strtoull / strtod etc.), but it throws an exception on error, and I believe that exceptions are not the right tool for structuring control flow of normal behaviour like reading user input. Also, you cannot control how those wrappers operates; for example, the succeed even if they don't consume the entire string (but don't tell you how far they got), and you cannot specify the number base.

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