atoi vs atol vs strtol vs strtoul vs sscanf
c
Solution
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
Convert text per:
Step 1: Optional whitespaces like `' '`, tab, `'\n'`, ... .
Step 2: Optional sign: `'-'` or `'+'`.
Step 3:
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: On out of range errors, undefined behavior. @chqrlie 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: On out of range errors, undefined behavior. 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. (base 2 to base 36) 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. ---: Does 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()`.
Problem
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 best — without knowing the input beforehand. The goal then is to use a single function that recognizes the different types of inputs and assign that to its integer (`int`) value which can then be used so: ``` ./a.out 23 0xC4 070 ``` could print ``` 23 196 /*hexadecimal*/ 56 /*octal*/ ``` The only issue that I can see is the parsing to find the difference between a decimal integer and an octal. Side question, is this stable for converting the string to an integer for use?