2

I want a function that will interpret a string as a strictly unsigned integer, failing when the string overflows, represents a negative number, or does not represent a number.

strtoull() does set errno to ERANGE on overflow or EINVAL for a string that does not begin with a number, but accepts negative numbers as valid.

strtoumax() is the same as strtoull()

atoll() and strtonum() are ruled out because they are strictly for signed integers.

sscanf() sets errno to ERANGE on overflow and stops processing the string if it does not begin with a number (reflected in sscanf's return value), but also accepts negative numbers as valid.

Is there another option that I'm missing?

2
  • You can always manually test the presence of a starting - in the input then use some strtoull Jul 29, 2014 at 5:33
  • Of course I can, the point was to avoid rewriting the 30,000th new version of the same function. Jul 31, 2014 at 18:41

2 Answers 2

2

There are no out-of-the-box solutions that fit your requirements, but it is easy enough to write such a function yourself, using strtoull or strtoll as basis.

For negative numbers, either you can check for the minus sign beforehand, or you can convert to a signed number first and report an error for negative values.
For numbers followed by other characters, you can check that the endp pointer that you pass to strto(u)ll points to the end of the string.

4
  • Converting to a signed number and then rejecting negative values would mean also rejecting half of the possible unsigned values, and for no good reason. Jul 31, 2014 at 18:44
  • @Polyergic: That depends on the range of values you want to support. If you only need to support 32-bit integers, you can convert as 64-bit and still support the full 32-bit unsigned range. Jul 31, 2014 at 20:02
  • I want to support the values that I can store in a 64-bit unsigned integer. If 32-bits were enough I'd've used strtoul rather than strtoull. When I get back to the project I needed this for I'll post my implementation. Aug 1, 2014 at 16:20
  • @Polyergic: If you want to support the full range of the largest unsigned type, then testing for negative values after conversion is clearly not a viable option. That leaves testing the sign beforehand. Aug 1, 2014 at 18:03
1

You are describing two separate problems. One is that the string should be in a specific form, namely all digits (but you didn't specify whether to permit leading and trailing spaces). The second is that the range should not overflow. There is no readily available function that provides exactly this combination.

The first requirement is best satisfied by testing (or parsing) the string before decoding it. In most languages I would use a regular expression. In C++ you can use library functions. In C you write loops and test characters.

The second requirement is actually quite tricky. You can include overflow testing in your decode function but testing against MAXUINT or something similar needs some careful coding. A simple solution is to decode as a double and then test the range before casting to uint.

In summary, when you have requirements as specific as this you normally finish up writing your own functions, perhaps basing it on available "free" source code. Over the 30 years I've been writing C code I've probably written this function or similar about 5 or 6 times. It gets easier with practice!

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.