Since C99 the C library has a set of safe conversion functions that interpret a string as a number. Their names are of the form strtoX
, where X
is one of l
, ul
, d
, etc to determine the target type of the conversion
double strtod(char const* p, char** endptr);
long double strtold(char const* p, char** endptr);
They provide checking that a conversion had an over- or underflow:
double ret = strtod(argv[1], 0); /* attempt conversion */
/* check the conversion result. */
if ((ret == HUGE_VAL || ret == -HUGE_VAL) && errno == ERANGE)
return; /* numeric overflow in in string */
else if (ret == HUGE_VAL && errno == ERANGE)
return; /* numeric underflow in in string */
/* At this point we know that everything went fine so ret may be used */
If the string in fact contains no number at all, this usage of strtod
returns 0.0
.
If this is not satisfactory, the additional parameter endptr
can be used. It is a pointer to pointer that will be pointed to the end of the detected number in the string. If it is set to 0
, as above, or NULL
, it is simply ignored.
This endptr
parameter provides indicates if there has been a successful conversion and if so, where the number ended:
char *check = 0;
double ret = strtod(argv[1], &check); /* attempt conversion */
/* check the conversion result. */
if (argv[1] == check)
return; /* No number was detected in string */
else if ((ret == HUGE_VAL || ret == -HUGE_VAL) && errno == ERANGE)
return; /* numeric overflow in in string */
else if (ret == HUGE_VAL && errno == ERANGE)
return; /* numeric underflow in in string */
/* At this point we know that everything went fine so ret may be used */
There are analogous functions to convert to the wider integer types:
long strtol(char const* p, char** endptr, int nbase);
long long strtoll(char const* p, char** endptr, int nbase);
unsigned long strtoul(char const* p, char** endptr, int nbase);
unsigned long long strtoull(char const* p, char** endptr, int nbase);
These functions have a third parameter nbase
that holds the number
base in which the number is written.
long a = strtol("101", 0, 2 ); /* a = 5L */
long b = strtol("101", 0, 8 ); /* b = 65L */
long c = strtol("101", 0, 10); /* c = 101L */
long d = strtol("101", 0, 16); /* d = 257L */
long e = strtol("101", 0, 0 ); /* e = 101L */
long f = strtol("0101", 0, 0 ); /* f = 65L */
long g = strtol("0x101", 0, 0 ); /* g = 257L */
The special value 0
for nbase
means the string is interpreted in the same way as number literals are interpreted in a C program: a prefix of 0x
corresponds to a hexadecimal representation, otherwise a leading 0
is octal and all other numbers are seen as decimal.
Thus the most practical way to interpret a command-line argument as a number would be
int main(int argc, char* argv[] {
if (argc < 1)
return EXIT_FAILURE; /* No number given. */
/* use strtoull because size_t may be wide */
size_t mySize = strtoull(argv[1], 0, 0);
/* then check conversion results. */
...
return EXIT_SUCCESS;
}
This means that the program can be called with a parameter in octal, decimal or hexadecimal.