I\'m trying to figure out from a command line being parsed, which function would be best to convert either a decimal, hexadecimal, or octal number to an int
the
which function would be best to convert either a decimal, hexadecimal, or octal number to an
int
the best (?)
To convert such text to int
, recommend long strtol(const char *nptr, char **endptr, int base);
with additional tests when converting to int
, if needed.
Use 0
as the base
to assess early characters in steering conversion as base 10, 16 or 8. @Mike Holt
0x or 0X followed by hex digits--> hexadecimal
0 --> octal
else --> decimal
Sample code
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
int mystrtoi(const char *str) {
char *endptr;
errno = 0;
// v--- determine conversion base
long long_var = strtol(str, &endptr, 0);
// out of range , extra junk at end, no conversion at all
if (errno == ERANGE || *endptr != '\0' || str == endptr) {
Handle_Error();
}
// Needed when `int` and `long` have different ranges
#if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX
if (long_var < INT_MIN || long_var > INT_MAX) {
errno = ERANGE;
Handle_Error();
}
#endif
return (int) long_var;
}
atoi vs atol vs strtol vs strtoul vs sscanf ... to int
atoi()
Pro: Very simple.
Pro: Convert to an int
.
Pro: In the C standard library.
Pro: Fast.
Con: No error handling.
Con: Handle neither hexadecimal nor octal.
atol()
Pro: Simple.
Pro: In the C standard library.
Pro: Fast.
Con: Converts to an long
, not int
which may differ in size.
Con: No error handling.
Con: Handle neither hexadecimal nor octal.
strtol()
Pro: Simple.
Pro: In the C standard library.
Pro: Good error handling.
Pro: Fast.
Pro: Can handle binary.
Con: Convert to an long
, not int
which may differ in size.
strtoul()
Pro: Simple.
Pro: In the C standard library.
Pro: Good error handling.
Pro: Fast.
Pro: Can handle binary.
---: Appears to not complain about negative numbers.
Con: Converts to an unsigned long
, not int
which may differ in size.
sscanf(..., "%i", ...)
Pro: In the C standard library.
Pro: Converts to int
.
---: Middle-of-the-road complexity.
Con: Potentially slow.
Con: OK error handling (overflow is not defined).
All suffer/benefit from locale
settings. §7.22.1.4 6 “In other than the "C" locale, additional locale-specific subject sequence forms may be accepted.”
Additional credits:
@Jonathan Leffler: errno
test against ERANGE
, atoi()
decimal-only, discussion about errno
multi-thread concern.
@Marian Speed issue.
@Kevin Library inclusiveness.
For converting short
, signed char
, etc., consider strto_subrange().
It is only sensible to consider strtol()
and strtoul()
(or strtoll()
or strtoull()
from <stdlib.h>
, or perhaps strtoimax()
or strtoumax()
from <inttypes.h>
) if you care about error conditions. If you don't care about error conditions on overflow, any of them could be used. Neither atoi()
nor atol()
nor sscanf()
gives you control if the values overflow. Additionally, neither atoi()
nor atol()
provides support for hex or octal inputs (so in fact you can't use those to meet your requirements).
Note that calling the strtoX()
functions is not entirely trivial. You have to set errno
to 0 before calling them, and pass a pointer to get the end location, and analyze carefully to know what happened. Remember, all possible return values from these functions are valid outputs, but some of them may also indicate invalid inputs — and errno
and the end pointer help you distinguish between them all.
If you need to convert to int
after reading the value using, say, strtoll()
, you can check the range of the returned value (stored in a long long
) against the range defined in <limits.h>
for int
: INT_MIN
and INT_MAX
.
For full details, see my answer at: Correct usage of strtol().
Note that none of these functions tells you which conversion was used. You'll need to analyze the string yourself. Quirky note: did you know that there is no decimal 0 in C source; when you write 0
, you are writing an octal constant (because its first digit is a 0
). There are no practical consequences to this piece of trivia.