user105033
user105033

Reputation: 19648

atoi() — string to int

I read that atoi() is deprecated and that it is equivalent to:

(int)strtol(token_start, (char **)NULL, 10);

Does that mean I should use the above instead of atoi(chr) or is it just saying they are equivalent?

Upvotes: 12

Views: 30088

Answers (6)

chux
chux

Reputation: 154572

  • atoi() is not deprecated by the prior or the current C standard.

  • atoi(nptr) is like (int)strtol(nptr, (char **)NULL, 10); except on errors.


Now, how to detect and resolve errors?

Consider using a helper function: int atoi_alt(const char *nptr, int *errorptr);

Possible errors and candidate resolutions:

  • Out-of-range: conversion leads to a value outside the [INT_MIN ... INT_MAX] range like atoi_alt("1234567890123456789012345678901234567890", ...);. Return either INT_MIN or INT_MAX (matching the sign of the original conversion) and a non-zero error.

  • No conversion: conversion fails as the string begins with non-numeric, non-white-space text like atoi_alt("!@#$1234", ...);. Return 0 and a non-zero error.

  • No conversion: conversion fails as the string is empty like atoi_alt("", ...);. Return 0 and a non-zero error.

  • Non-numeric trailing text: Initial conversion works, yet extra, non-white-space, text exists like atoi_alt("1234!@#$", ...);. Return converted value and a non-zero error. Note that with strtol(), this is not an error.

  • White-space trailing text: Initial conversion works, white-space follows like atoi_alt("1234\n", ...);. Return converted value and a zero error. Note that with strtol(), this is not an error.

  • White-space begins text: Ignore leading white-space and convert as above. Note that this is consistent with atoi() and strtol() and itself is not an error.

  • String not supplied: As nptr == NULL, return 0 and a non-zero error. Note that with strtol(), this is undefined behavior (UB).

  • Error address not supplied: Perform as above, but do not set an error.

Sample alternative code:

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

// To Do: refine error codes, perhaps as enum?
#define ATOI_BAD_ARG 1
#define ATOI_NO_CONVERSION 2
#define ATOI_RANGE 3
#define ATOI_EXTRA 4
int atoi_alt(const char *nptr, int *errorptr);

// Side effect: errno is assigned.
int atoi_alt(const char *nptr, int *errorptr) {
  int dummy;
  if (errorptr == NULL) {
    errorptr = &dummy;
  }
  if (nptr == NULL) {
    *errorptr = ATOI_BAD_ARG;
    return 0;
  }

  errno = 0;
  char *end;
  long lvalue = strtol(nptr, &end, 10);
  if (nptr == end) {
    *errorptr = ATOI_NO_CONVERSION;
    return 0;
  }

#if LONG_MIN == INT_MIN && LONG_MAX == INT_MAX
  if (errno == ERANGE) {
    *errorptr = ATOI_RANGE;
    return (int) lvalue;
  }
#else
  if (errno == ERANGE || lvalue < INT_MIN || lvalue > INT_MAX) {
    errno = ERANGE;
    *errorptr = ATOI_RANGE;
    return (lvalue < 0) ? INT_MIN : INT_MAX;
  }
#endif

  while (isspace(((unsigned char* ) end)[0])) {
    end++;
  }

  *errorptr = *end ? ATOI_EXTRA : 0;
  return (int) lvalue;
}

Code purposely does not carry the error information back to the caller via errno - my design choice. Easy enough to amend code to do otherwise.

Upvotes: 0

John Boker
John Boker

Reputation: 83729

It does say on Apple's Mac OS X Manual Page for atoi(3) (and in the BSD man pages too) that atoi has been deprecated.

The atoi() function has been deprecated by strtol() and should not be used in new code.

I would use the strtol() equivalent just for that reason, but i doubt you have to worry about atoi() being removed.

from http://www.codecogs.com/library/computing/c/stdlib.h/atoi.php Implementation Notes

* The atoi function is not thread-safe and also not async-cancel safe.
* The atoi function has been deprecated by strtol and should not be used in new code.

Upvotes: 8

Lundin
Lundin

Reputation: 215330

atoi is not deprecated, your source is incorrect. Nothing in the current C standard ISO 9899:2011 indicates this (see for example chapter 6.11 future language directions), nor anything in earlier standards.

As per the C standard, atoi is equivalent to strtol as follows, C11 7.22.1.2:

The atoi, atol, and atoll functions convert the initial portion of the string pointed to by nptr to int, long int, and long long int representation, respectively.

Except for the behavior on error, they are equivalent to

atoi: (int)strtol(nptr, (char **)NULL, 10)

atol: strtol(nptr, (char **)NULL, 10)

atoll: strtoll(nptr, (char **)NULL, 10)

strtol is preferred, as atoi invokes undefined behavior upon error. See 7.22.1 "If the value of the result cannot be represented, the behavior is undefined."

Upvotes: 23

Ben Voigt
Ben Voigt

Reputation: 283921

No, you shouldn't use the above instead of atoi.

You should actually check the error information that strtol makes available:

i = atoi(s);

should be replaced by

char* stopped;
i = (int)strtol(s, &stopped, 10);
if (*stopped) { /* handle error */ }

Upvotes: 3

pmg
pmg

Reputation: 108986

The description of atoi() has one very important point in relation to the similarities/differences to strtol()

> ... The call atoi(str) shall be equivalent to:
> (int) strtol(str, (char **)NULL, 10)
> except that the handling of errors may differ.

Try this for fun:

const char *buf = "forty two";
int t1 = atoi(buf);             /* detect errors? */
int t2 = strtol(buf, NULL, 10); /* detect errors? */

Upvotes: 4

Toad
Toad

Reputation: 15935

it means that at one point in time atoi will not be available anymore. So start changing your code now

Upvotes: -3

Related Questions