How to convert a string to integer in C?

I am trying to find out if there is an alternative way of converting string to integer in C.

I regularly pattern the following in my code.

char s[] = "45";

int num = atoi(s);

So, is there a better way or another way?

Solutions

There is strtol which is better IMO. Also I have taken a liking in strtonum, so use it if you have it (but remember it's not portable):

long long
     strtonum(const char *nptr, long long minval, long long maxval,
     const char **errstr);

You might also be interested in strtoumax and strtoimax which are standard functions in C99. For example you could say:

uintmax_t num = strtoumax(s, NULL, 10);
if (num == UINTMAX_MAX && errno == ERANGE)
    /* Could not convert. */

Anyway, stay away from atoi:

The call atoi(str) shall be equivalent to:

(int) strtol(str, (char **)NULL, 10)

except that the handling of errors may differ. If the value cannot be represented, the behavior is undefined.

Robust C89 strtol-based solution

With:

  • no undefined behavior (as could be had with the atoi family)
  • a stricter definition of integer than strtol (e.g. no leading whitespace nor trailing trash chars)
  • classification of the error case (e.g. to give useful error messages to users)
  • a "testsuite"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

typedef enum {
    STR2INT_SUCCESS,
    STR2INT_OVERFLOW,
    STR2INT_UNDERFLOW,
    STR2INT_INCONVERTIBLE
} str2int_errno;

/* Convert string s to int out.
 *
 * @param[out] out The converted int. Cannot be NULL.
 *
 * @param[in] s Input string to be converted.
 *
 *     The format is the same as strtol,
 *     except that the following are inconvertible:
 *
 *     - empty string
 *     - leading whitespace
 *     - any trailing characters that are not part of the number
 *
 *     Cannot be NULL.
 *
 * @param[in] base Base to interpret string in. Same range as strtol (2 to 36).
 *
 * @return Indicates if the operation succeeded, or why it failed.
 */
str2int_errno str2int(int *out, char *s, int base) {
    char *end;
    if (s[0] == '\0' || isspace(s[0]))
        return STR2INT_INCONVERTIBLE;
    errno = 0;
    long l = strtol(s, &end, base);
    /* Both checks are needed because INT_MAX == LONG_MAX is possible. */
    if (l > INT_MAX || (errno == ERANGE && l == LONG_MAX))
        return STR2INT_OVERFLOW;
    if (l < INT_MIN || (errno == ERANGE && l == LONG_MIN))
        return STR2INT_UNDERFLOW;
    if (*end != '\0')
        return STR2INT_INCONVERTIBLE;
    *out = l;
    return STR2INT_SUCCESS;
}

int main(void) {
    int i;
    /* Lazy to calculate this size properly. */
    char s[256];

    /* Simple case. */
    assert(str2int(&i, "11", 10) == STR2INT_SUCCESS);
    assert(i == 11);

    /* Negative number . */
    assert(str2int(&i, "-11", 10) == STR2INT_SUCCESS);
    assert(i == -11);

    /* Different base. */
    assert(str2int(&i, "11", 16) == STR2INT_SUCCESS);
    assert(i == 17);

    /* 0 */
    assert(str2int(&i, "0", 10) == STR2INT_SUCCESS);
    assert(i == 0);

    /* INT_MAX. */
    sprintf(s, "%d", INT_MAX);
    assert(str2int(&i, s, 10) == STR2INT_SUCCESS);
    assert(i == INT_MAX);

    /* INT_MIN. */
    sprintf(s, "%d", INT_MIN);
    assert(str2int(&i, s, 10) == STR2INT_SUCCESS);
    assert(i == INT_MIN);

    /* Leading and trailing space. */
    assert(str2int(&i, " 1", 10) == STR2INT_INCONVERTIBLE);
    assert(str2int(&i, "1 ", 10) == STR2INT_INCONVERTIBLE);

    /* Trash characters. */
    assert(str2int(&i, "a10", 10) == STR2INT_INCONVERTIBLE);
    assert(str2int(&i, "10a", 10) == STR2INT_INCONVERTIBLE);

    /* int overflow.
     *
     * `if` needed to avoid undefined behaviour
     * on `INT_MAX + 1` if INT_MAX == LONG_MAX.
     */
    if (INT_MAX < LONG_MAX) {
        sprintf(s, "%ld", (long int)INT_MAX + 1L);
        assert(str2int(&i, s, 10) == STR2INT_OVERFLOW);
    }

    /* int underflow */
    if (LONG_MIN < INT_MIN) {
        sprintf(s, "%ld", (long int)INT_MIN - 1L);
        assert(str2int(&i, s, 10) == STR2INT_UNDERFLOW);
    }

    /* long overflow */
    sprintf(s, "%ld0", LONG_MAX);
    assert(str2int(&i, s, 10) == STR2INT_OVERFLOW);

    /* long underflow */
    sprintf(s, "%ld0", LONG_MIN);
    assert(str2int(&i, s, 10) == STR2INT_UNDERFLOW);

    return EXIT_SUCCESS;
}

GitHub upstream.

Based on: https://stackoverflow.com/a/6154614/895245

Don't use functions from ato... group. These are broken and virtually useless. A moderately better solution would be to use sscanf, although it is not perfect either.

To convert string to integer, functions from strto... group should be used. In your specific case it would be strtol function.

Tags: C / String / ATOI

Similar questions

How to convert integer to string to print integer on UART
I want to print out an integer value which is computed in the program on a uart screen. I am basically creating a data logging system. The user must be able to view the times when a character arrives. I am not able to use printf or snprintf or sprint as i am creating a time triggered system and printf takes some time to execute. I have searched sta...
Convert char String to an int but not possible to convert a char from an char string to an int?
Is there a solution to convert an char "slice" of an char string into an int? Short description: User inputs a string with values for example: 1, 2 3 4 ,5 Iam formating that string to 12345 With each number i want to continue to work with the index of an array.
How to convert binary string to integer string
Possible Duplicate: Converting string of 1s and 0s into binary value Lets say that I have string which contains 1024 characters (represents 0 and 1). I want to present it as an number in decimal base (also as a string). The tricky part is that i have to do it in C/C++ without 3rd part libraries. Any clues?
C++ C
How to convert a signed integer to a corresponding unsigned integer in C?
I'd like to define a C macro , which takes a signed integer x (can be: signed char, short, int, long, long long, or anything else, even something longer than a long long), and it converts x to the corresponding unsigned integer type of the same size. It's OK to assume that signed integers use the two's complement representation. So to convert any v...
Convert character to integer, and integer back to same character
I want two create two functions that can do this. So one function takes a character, for example the character a and returns the integer 97. The other function takes this integer 97 and returns the character a. I know this can be done by using the ASCII codes of these characters, but then it wouldn't work for characters like é, à, ö. Can this be do...
Formula to convert byte array representing signed integer into integer
This question is more generic without a particular language. I am more interested in solving this generally across languages. Every answer I find references a built-in method of something like getInt32 to extract an integer from a byte array. I have a byte array which contains the big-endian representation of a signed integer. Getting the values fo...

Also ask

We use cookies to deliver the best possible experience on our website. By continuing to use this site, accepting or closing this box, you consent to our use of cookies. To learn more, visit our privacy policy.