cstrtoull

Check if a string representing float/unsigned int is too big


I have a file containing strings representing float and uint64_t values.

I know exactly which string contains float values and which contains uint64_t values - that is not the problem I'm facing.

Here is how I convert them to their respective data-type:

char* t, v; 
uint64_t cn; 


cn = strtoull(t, &v, 10);

char* tt, vv; 
float cn2; 

cn2 = strtof(tt, vv); 

But the problem arises at the following edge-case I want to catch:

Let's say the string for the uint64_t is "99999999999999999999999999999999999999999999999999"

This can't be represented within 8 bytes and therefore causes an overflow resulting in cn = 18446744073709551615.

Same problem with the float cn2.

How can catch this behavior?


Solution

  • strtoull provides an indication that the value is out of range. Consider this code:

    #include <errno.h>
    …
    errno = 0; // Set error code to zero before call.
    unsigned long long x = strtoull(t, &v, 10);
    if (errno == ERANGE)
    {
        // Handle out-of-range error.
    }
    

    This will reach the error case if the numeral in t is too large.

    Note that if t contains a minus sign (but is not too large in magnitude), strtoull will return a value that is “negated” in the unsigned long long type (that is, a value wrapped around ULLONG_MAX+1) even though a negative value is out of range of the type; no error indication will be provided. So, if you want to detect all out-of-range cases, you must check t for a minus sign (possibly after leading white space) with a non-zero return value.

    strtof provides sufficient information to distinguish cases, per C 2018 7.22.1.3 10: