Convert char array to a int number in C
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
SpcCode
Updated on July 09, 2022Comments
-
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 about 12 yearsnot 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 about 12 yearsYeah. I just realized that. ;-)
-
BigMike about 12 yearsdegustibus... 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 about 12 years@BigMike When I was very little and just starting with
C
, somebody explained to me why usingatoi
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 theatoi
problem, as well as one comparing it to other ways of converting a string to int. -
SpcCode about 12 yearsThank you! I was missing the '\0'. I am using dynamic array so I just added a extra position.
-
BigMike about 12 yearsthe 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 about 12 yearsAnd how do you think
sscanf
gets its%d
parsed ? It callsatoi
, so anyway that's bazooka for an ant... -
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 almost 10 yearsVery good, like "pit_t" types, sscanf is very good for me. atoi is not ok.
-
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 almost 9 yearsIf 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 almost 9 yearsYea, I came up with the one without using library.
-
milevyo over 8 yearsi use standard library when i feel lazy, i always adopt this approach when it comes to integers.
-
milevyo over 8 yearsassuming there is no other chars than {'-','+','0-9',\0};