Why is there no strtoi in stdlib.h?

I have grown accustomed to strtod and variants. I am wondering why there is no strtoi shipped with <stdlib.h>. Why is it that the integer type is left out of this party?

Specifically I am asking why there is not a version of atoi with the safety features of strtod?


Solution 1:

strtol() converts a string to an integer, a long integer but an integer nevertheless. There is atoi() but it should be avoided in most cases due to the fact that it lacks a mechanism for error reporting from invalid input.

Solution 2:

Why is there no strtoi in stdlib.h?

No critical need.

In early C, there was not a standard signed integer type wider than long and all narrower conversions, like int, could be made from strtol() - as done below.

IMO, these and their unsigned counterparts are now missing C functions and a design shortcoming in the current standard C library (C17/18).


On many systems, long and int have the same range and so there is a reduced need for a separate strtoi(). atoi() fills the need for quick and dirty code to convert to an int, but can lack error detection or cause undefined behavior (UB). There also is no strto_short() nor strto_signchar(), etc.

It is fairly easy to create a substitute strtoi(). Simplifications exist.

#include <errno.h>
#include <limits.h>
#include <stdlib.h>

static long str2subrange(const char *s, char **endptr, int base, 
    long min, long max) {
  long y = strtol(s, endptr, base);
  if (y > max) {
    errno = ERANGE;
    return max;
  }
  if (y < min) {
    errno = ERANGE;
    return min;
  }
  return y;
}

// OP's goal
int str2i(const char *s, char **endptr, int base) {
  #if INT_MAX == LONG_MAX && INT_MIN == LONG_MIN
    return (int) strtol(s, endptr, base);
  #else
    return (int) str2subrange(s, endptr, base, INT_MIN, INT_MAX);
  #endif
}

short str2short(const char *s, char **endptr, int base) {
  return (short) str2subrange(s, endptr, base, SHRT_MIN, SHRT_MAX);
}

signed char str2schar(const char *s, char **endptr, int base) {
  return (signed char) str2subrange(s, endptr, base, SCHAR_MIN, SCHAR_MAX);
}

#include <stdint.h>
int16_t str2int16(const char *s, char **endptr, int base) {
  return (int16_t) str2subrange(s, endptr, base, INT16_MIN, INT16_MAX);
}

[Edit 2021]

To avoid conflicts with Future library directions, names changed from strto...() to str2...().
2 implying to.

Function names that begin with str, mem, or wcs and a lowercase letter may be added to the declarations in the <string.h> header. C17dr § 7.31.13 1

Solution 3:

The integer isn't left out of the party: there is strtol, which converts a string to a long, which is an integer type.