Convert char array to a int number in C

291,198

Solution 1

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.

Solution 2

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!

Solution 3

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.

Solution 4

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
Share:
291,198
SpcCode
Author by

SpcCode

Updated on July 09, 2022

Comments

  • SpcCode
    SpcCode almost 2 years

    I want to convert a char array[] like:

    char myarray[4] = {'-','1','2','3'}; //where the - means it is negative
    

    So it should be the integer: -1234 using standard libaries in C. I could not find any elegant way to do that.

    I can append the '\0' for sure.

  • BigMike
    BigMike about 12 years
    not exactly a good choice. It works by pure sheer of luck. the array is not null terminated so unpredictable resulst may come from atoi
  • Rich Drummond
    Rich Drummond about 12 years
    Yeah. I just realized that. ;-)
  • BigMike
    BigMike about 12 years
    degustibus... sscanf adds an entire overhead upon a trivial task (variable list arguments, format string parsing), and IMHO is more "error prone". For simple task I prefer to use simple functions (atoi is there for this reason)
  • penelope
    penelope about 12 years
    @BigMike When I was very little and just starting with C, somebody explained to me why using atoi is not preferable. Since then, I forgot the reasons, but I never liked using it much... Now I'm looking them up and I'm being reminded of them. I edited in a link to a question referring to the atoi problem, as well as one comparing it to other ways of converting a string to int.
  • SpcCode
    SpcCode about 12 years
    Thank you! I was missing the '\0'. I am using dynamic array so I just added a extra position.
  • BigMike
    BigMike about 12 years
    the only reason to deprecate atoi is related to thread safe stuff, strtol is still preferreable over sscanf for trivial tasks. the point is not using atoi or int foo(char *) is to use a trivial function against a complex function. the rest is just a matter of taste. sscanf sure does its work, simply is wasted on such a trivial tasks. When I learned programming, sparing that 4/5 cycles of clock was a must. If more people just had keep on that, now application would run at speed of light.
  • Eregrith
    Eregrith about 12 years
    And how do you think sscanf gets its %d parsed ? It calls atoi, so anyway that's bazooka for an ant...
  • penelope
    penelope about 12 years
    @Eregrith So, I learn something new everyday :) On the other hand, I never actually had to do any code using heavy int to string conversion, I knew that sscanf is safer in some way so when using it once or twice during the application run, I didn't bother that much with the performance issues.
  • kangear
    kangear almost 10 years
    Very good, like "pit_t" types, sscanf is very good for me. atoi is not ok.
  • Ben Voigt
    Ben Voigt almost 10 years
    @BigMike: The reason to deprecate atoi is that it fails silently. There's no static buffer that would cause thread-safety issues, though. strtol is indeed the right function to use here.
  • hyde
    hyde almost 9 years
    If you bother to add the '\0', it'd really be better to use standard library (see other answers). This approach would be useful, if you couldn't have the terminating NUL byte (with loop condition changed).
  • Otar Magaldadze
    Otar Magaldadze almost 9 years
    Yea, I came up with the one without using library.
  • milevyo
    milevyo over 8 years
    i use standard library when i feel lazy, i always adopt this approach when it comes to integers.
  • milevyo
    milevyo over 8 years
    assuming there is no other chars than {'-','+','0-9',\0};