137

Is there a way to convert a character to an integer in C?

For example, from '5' to 5?

nbro
  • 15,395
  • 32
  • 113
  • 196
Flow
  • 1,373
  • 2
  • 10
  • 6

14 Answers14

199

As per other replies, this is fine:

char c = '5';
int x = c - '0';

Also, for error checking, you may wish to check isdigit(c) is true first. Note that you cannot completely portably do the same for letters, for example:

char c = 'b';
int x = c - 'a'; // x is now not necessarily 1

The standard guarantees that the char values for the digits '0' to '9' are contiguous, but makes no guarantees for other characters like letters of the alphabet.

Chris Young
  • 15,627
  • 7
  • 36
  • 42
  • 3
    @Paul Tomblin: Yes for digits not letters, because, as I said in the answer, the standard guarantees '0' to '9' are contiguous but does not make such guarantees for other characters such as 'a' to 'z'. – Chris Young May 18 '09 at 04:46
  • char c = 'b'; int x = c - 'a'; then x will be 1 only in ASCII? – dsfdf Jan 10 '13 at 02:20
  • @Pan In any encoding, including ASCII, that has 'b' 1 more than 'a'. This still holds true in EBCDIC, however it makes ('j' - 'i') == 8. – Chris Young Aug 26 '13 at 09:32
  • @ChrisYoung Why? Cause in EBCDIC,'j' is not 1 more than 'i'? – dsfdf Aug 26 '13 at 15:10
  • 2
    What am I missing here where atoi isn't used? – Daniel Jun 21 '18 at 19:20
50

Subtract '0' like this:

int i = c - '0';

The C Standard guarantees each digit in the range '0'..'9' is one greater than its previous digit (in section 5.2.1/3 of the C99 draft). The same counts for C++.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • 2
    This answer would be better if you mentioned that a char is /already/ effectively an integer, albiet of implementation defined sign (ie, might be signed or unsigned), and is CHAR_BITS long. – Arafangion Mar 10 '09 at 03:03
  • i wasn't sure knowing that really helps him. but Chris made a good point with a..z being not contiguous necessarily. i should have mentioned that instead. now he's won the race :) – Johannes Schaub - litb Mar 10 '09 at 03:09
  • 1
    Yours is better because you've qualified your answer, though - Chris could very well have just made his stuff up. :) – Arafangion Mar 10 '09 at 03:25
  • thanks for the appreciation. i admit i wasn't sure about the state for C. so i looked up and 'cause i already was at it i pasted the reference into the answer :) – Johannes Schaub - litb Mar 10 '09 at 03:28
  • And that, sir, is why you've got a couple more points than me. :) – Arafangion Mar 10 '09 at 03:51
  • i believe you mate. i often find myself not pasting the reference to some standard section when giving answers either. but this time i looked up after answering and had the section numbers at hand, so it was easy to change my answer and add it in :) cheers – Johannes Schaub - litb Mar 10 '09 at 15:48
37

If, by some crazy coincidence, you want to convert a string of characters to an integer, you can do that too!

char *num = "1024";
int val = atoi(num); // atoi = ASCII TO Int

val is now 1024. Apparently atoi() is fine, and what I said about it earlier only applies to me (on OS X (maybe (insert Lisp joke here))). I have heard it is a macro that maps roughly to the next example, which uses strtol(), a more general-purpose function, to do the conversion instead:

char *num = "1024";
int val = (int)strtol(num, (char **)NULL, 10); // strtol = STRing TO Long

strtol() works like this:

long strtol(const char *str, char **endptr, int base);

It converts *str to a long, treating it as if it were a base base number. If **endptr isn't null, it holds the first non-digit character strtol() found (but who cares about that).

Robert Columbia
  • 6,313
  • 15
  • 32
  • 40
Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • There are no thread issues with atoi (it has no static data) and it is not deprecated. In fact it is functionally equivalent to: #define atoi(x) (int)(strtol((x), NULL, 10) – Evan Teran Mar 10 '09 at 14:43
  • 5
    The issue with atoi is that it uses 0 as a "can't find a number here" value, so atoi("0") and atoi("one") both return 0. If that doesn't work for what you're using it for, look for strtol() or sscanf(). – David Thornley Mar 11 '09 at 20:39
  • The other advantage of strtol, of course, is that you may well need to read other things from the same string that come after the number. – dfeuer Jul 21 '12 at 21:30
  • @EvanTeran Unfortunately if you run Visual Studio you get a depreciation warning (and won't compile without being disabled). VS now recommends `itoa_s()`. – Xantium Jun 14 '19 at 10:03
19

To convert character digit to corresponding integer. Do as shown below:

char c = '8';                    
int i = c - '0';

Logic behind the calculation above is to play with ASCII values. ASCII value of character 8 is 56, ASCII value of character 0 is 48. ASCII value of integer 8 is 8.

If we subtract two characters, subtraction will happen between ASCII of characters.

int i = 56 - 48;   
i = 8;
Andre Hofmeister
  • 3,185
  • 11
  • 51
  • 74
Ashish
  • 450
  • 4
  • 5
  • 2
    Why am I the only one to upvote this? The explanation is so simple and informative :+1: – Brandon Benefield Aug 09 '18 at 19:29
  • Thank you, this explanation covers the fact that someone looking into this property of C may not connect the dots back to ASCII. I came here straight from K&R, and they kind of gloss over this. – Quincy Tennyson Dec 02 '21 at 13:22
14

Subtract char '0' or int 48 like this:

char c = '5';
int i = c - '0';

Explanation: Internally it works with ASCII value. From the ASCII table, decimal value of character 5 is 53 and 0 is 48. So 53 - 48 = 5

OR

char c = '5';
int i = c - 48; // Because decimal value of char '0' is 48

That means if you deduct 48 from any numeral character, it will convert integer automatically.

Arif
  • 6,094
  • 4
  • 49
  • 81
6
char numeralChar = '4';
int numeral = (int) (numeralChar - '0');
easeout
  • 8,665
  • 5
  • 43
  • 51
  • `numeralChar - '0'` is already of type `int`, so you don't need the cast. Even if it wasn't, the cast is not needed. – Alok Singhal Feb 26 '10 at 05:15
  • Huh, yeah that would coerce, wouldn't it? Maybe Java has colored my perceptions. Or maybe I'm completely mistaken and it would even coerce in Java. :) – easeout Mar 01 '10 at 15:23
2

Here are helper functions which allow to convert digit in char to int and vice versa:

int toInt(char c) {
    return c - '0';
}

char toChar(int i) {
    return i + '0';
}
Maxim Makhun
  • 2,197
  • 1
  • 22
  • 26
1

Just use the atol()function:

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

int main() 
{
    const char *c = "5";
    int d = atol(c);
    printf("%d\n", d);

}
0

When I need to do something like this I prebake an array with the values I want.

const static int lookup[256] = { -1, ..., 0,1,2,3,4,5,6,7,8,9, .... };

Then the conversion is easy

int digit_to_int( unsigned char c ) { return lookup[ static_cast<int>(c) ]; }

This is basically the approach taken by many implementations of the ctype library. You can trivially adapt this to work with hex digits too.

Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
  • That seems extremely inefficient for converting a single decimal (or octal) digit. If the relevant portion of your lookup table doesn't happen to be in L1 cache, you'll blow a bunch of cycles to pull it in just to get one value. Frankly, I tend to doubt this is even a good idea if you're converting a whole slew of digits, but you'd have to measure that. It's much more competitive for hex, of course. – dfeuer Jul 21 '12 at 21:41
0

Check this,

char s='A';

int i = (s<='9')?(s-'0'):(s<='F')?((s-'A')+10):((s-'a')+10);

for only 0,1,2,....,E,F.

fredtantini
  • 15,966
  • 8
  • 49
  • 55
Shiva
  • 1
0

If your digit is, say, '5', in ASCII it is represented as the binary number 0011 0101 (53). Every digit has the highest four bits 0011 and the lowest 4 bits represent the digit in bcd. So you just do

char cdig = '5';
int dig = cdig & 0xf; // dig contains the number 5

to get the lowest 4 bits, or, what its same, the digit. In asm, it uses and operation instead of sub(as in the other answers).

Garmekain
  • 664
  • 5
  • 18
0

If it's just a single character 0-9 in ASCII, then subtracting the the value of the ASCII zero character from ASCII value should work fine.

If you want to convert larger numbers then the following will do:

char *string = "24";

int value;

int assigned = sscanf(string, "%d", &value);

** don't forget to check the status (which should be 1 if it worked in the above case).

Paul.

Paul W Homer
  • 2,728
  • 1
  • 19
  • 25
0
char chVal = '5';
char chIndex;

if ((chVal >= '0') && (chVal <= '9')) {

    chIndex = chVal - '0';
}
else 
if ((chVal >= 'a') && (chVal <= 'z')) {

    chIndex = chVal - 'a';
}
else 
if ((chVal >= 'A') && (chVal <= 'Z')) {

    chIndex = chVal - 'A';
}
else {
    chIndex = -1; // Error value !!!
}
Evan Teran
  • 87,561
  • 32
  • 179
  • 238
Alphaneo
  • 12,079
  • 22
  • 71
  • 89
-3

You would cast it to an int (or float or double or what ever else you want to do with it) and store it in anoter variable.

SeanJA
  • 10,234
  • 5
  • 32
  • 42