Convert char array to a int number in C

I personally don't like atoi function. I would suggest sscanf:

char myarray[5] = {'-', '1', '2', '3', '\0'};
int i;
sscanf(myarray, "%d", &i);

It's very standard, it's in the stdio.h library :)

And in my opinion, it allows you much more freedom than atoi, arbitrary formatting of your number-string, and probably also allows for non-number characters at the end.

EDIT I just found this wonderful question here on the site that explains and compares 3 different ways to do it - atoi, sscanf and strtol. Also, there is a nice more-detailed insight into sscanf (actually, the whole family of *scanf functions).

EDIT2 Looks like it's not just me personally disliking the atoi function. Here's a link to an answer explaining that the atoi function is deprecated and should not be used in newer code.


Why not just use atoi? For example:

char myarray[4] = {'-','1','2','3'};

int i = atoi(myarray);

printf("%d\n", i);

Gives me, as expected:

-123

Update: why not - the character array is not null terminated. Doh!


It isn't that hard to deal with the character array itself without converting the array to a string. Especially in the case where the length of the character array is know or can be easily found. With the character array, the length must be determined in the same scope as the array definition, e.g.:

size_t len sizeof myarray/sizeof *myarray;

For strings you, of course, have strlen available.

With the length known, regardless of whether it is a character array or a string, you can convert the character values to a number with a short function similar to the following:

/* convert character array to integer */
int char2int (char *array, size_t n)
{    
    int number = 0;
    int mult = 1;

    n = (int)n < 0 ? -n : n;       /* quick absolute value check  */

    /* for each character in array */
    while (n--)
    {
        /* if not digit or '-', check if number > 0, break or continue */
        if ((array[n] < '0' || array[n] > '9') && array[n] != '-') {
            if (number)
                break;
            else
                continue;
        }

        if (array[n] == '-') {      /* if '-' if number, negate, break */
            if (number) {
                number = -number;
                break;
            }
        }
        else {                      /* convert digit to numeric value   */
            number += (array[n] - '0') * mult;
            mult *= 10;
        }
    }

    return number;
}

Above is simply the standard char to int conversion approach with a few additional conditionals included. To handle stray characters, in addition to the digits and '-', the only trick is making smart choices about when to start collecting digits and when to stop.

If you start collecting digits for conversion when you encounter the first digit, then the conversion ends when you encounter the first '-' or non-digit. This makes the conversion much more convenient when interested in indexes such as (e.g. file_0127.txt).

A short example of its use:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int char2int (char *array, size_t n);

int main (void) {

    char myarray[4] = {'-','1','2','3'}; 
    char *string = "some-goofy-string-with-123-inside";
    char *fname = "file-0123.txt";

    size_t mlen = sizeof myarray/sizeof *myarray;
    size_t slen = strlen (string);
    size_t flen = strlen (fname);

    printf ("\n myarray[4] = {'-','1','2','3'};\n\n");
    printf ("   char2int (myarray, mlen):  %d\n\n", char2int (myarray, mlen));

    printf (" string = \"some-goofy-string-with-123-inside\";\n\n");
    printf ("   char2int (string, slen) :  %d\n\n", char2int (string, slen));

    printf (" fname = \"file-0123.txt\";\n\n");
    printf ("   char2int (fname, flen)  :  %d\n\n", char2int (fname, flen));

    return 0;
}

Note: when faced with '-' delimited file indexes (or the like), it is up to you to negate the result. (e.g. file-0123.txt compared to file_0123.txt where the first would return -123 while the second 123).

Example Output

$ ./bin/atoic_array

 myarray[4] = {'-','1','2','3'};

   char2int (myarray, mlen):  -123

 string = "some-goofy-string-with-123-inside";

   char2int (string, slen) :  -123

 fname = "file-0123.txt";

   char2int (fname, flen)  :  -123

Note: there are always corner cases, etc. that can cause problems. This isn't intended to be 100% bulletproof in all character sets, etc., but instead work an overwhelming majority of the time and provide additional conversion flexibility without the initial parsing or conversion to string required by atoi or strtol, etc.


So, the idea is to convert character numbers (in single quotes, e.g. '8') to integer expression. For instance char c = '8'; int i = c - '0' //would yield integer 8; And sum up all the converted numbers by the principle that 908=9*100+0*10+8, which is done in a loop.

char t[5] = {'-', '9', '0', '8', '\0'}; //Should be terminated properly.

int s = 1;
int i = -1;
int res = 0;

if (c[0] == '-') {
  s = -1;
  i = 0;
}

while (c[++i] != '\0') { //iterate until the array end
  res = res*10 + (c[i] - '0'); //generating the integer according to read parsed numbers.
}

res = res*s; //answer: -908