You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 13 Next »

Use strtol() or a related function to convert a string token to an integer. The strtol(), strtoll(), strtoul(), and strtoull() functions convert the initial portion of a string token to long int, long long int, unsigned long int, and unsigned long long int representation, respectively. These functions provide more robust error handling than alternative solutions.

Non-Compliant Example 1

This non-compliant code example converts the string token stored in the static array buff to a signed integer value using the atoi() function.

int si;

if (argc > 1) {
  si = atoi(argv[1]);
}

The atoi(), atol(), and atoll() functions convert the initial portion of a string token 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)

Unfortunately, atoi() and related functions lack a mechanism for reporting errors for invalid values. Specifically, the atoi(), atol(), and atoll() functions:

  • do not need to set errno on an error
  • have undefined behavior if the value of the result cannot be represented

Non-Compliant Example 2

This non-compliant example uses the sscanf() function to convert a string token to an integer. The sscanf() function has the same problems as atoi().

int si;

if (argc > 1) {
  sscanf(argv[1], "%d", &si);
}

Compliant Solution

The following compliant example uses strtol() to convert a string token to an integer value and provides error checking to make sure that the value is in the range of int.

long sl;
int si;
char *end_ptr;

if (argc > 1) {

  errno = 0;

  sl = strtol(argv[1], &end_ptr, 0);

  if (ERANGE == errno) {
    puts("number out of range\n");
  }
  else if (sl > INT_MAX) {
    printf("%ld too large!\n", sl);
  }
  else if (sl < INT_MIN) {
    printf("%ld too small!\n", sl);
  }
  else if (end_ptr == argv[1]) {
    puts("invalid numeric input\n");
  }
  else if ('\0' != *end_ptr) {
    puts("extra characters on input line\n");
  }
  else {
    si = (int)sl;
  }
}

If you are attempting to convert a string token to a smaller integer type (int, short, or signed char), then you only need test the result against the limits for that type. The tests do nothing if the smaller type happens to have the same size and representation on a particular compiler.

References

  • No labels