Convierta un dígito de carácter al número entero correspondiente en C

103

¿Hay alguna forma de convertir un carácter en un número entero en C?

Por ejemplo, de '5'a 5?

Fluir
fuente

Respuestas:

148

Según otras respuestas, esto está bien:

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

Además, para la verificación de errores, es posible que desee verificar que isdigit (c) sea verdadero primero. Tenga en cuenta que no puede hacer lo mismo de manera completamente portátil con las letras, por ejemplo:

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

El estándar garantiza que los valores de caracteres para los dígitos '0' a '9' sean contiguos, pero no ofrece garantías para otros caracteres como letras del alfabeto.

Chris Young
fuente
3
@Paul Tomblin: Sí para dígitos, no letras, porque, como dije en la respuesta, el estándar garantiza que '0' a '9' son contiguos pero no ofrece tales garantías para otros caracteres como 'a' a 'z'.
Chris Young
char c = 'b'; int x = c - 'a'; entonces x será 1 solo en ASCII?
Pan
@Pan En cualquier codificación, incluido ASCII, que tenga 'b' 1 más que 'a'. Esto todavía es cierto en EBCDIC, sin embargo, hace ('j' - 'i') == 8.
Chris Young
@ChrisYoung ¿Por qué? ¿Porque en EBCDIC, 'j' no es 1 más que 'i'?
Pan
2
¿Qué me falta aquí donde no se usa atoi?
Daniel
41

Reste '0' así:

int i = c - '0';

El estándar C garantiza que cada dígito en el rango '0'..'9'es uno mayor que su dígito anterior (en la sección 5.2.1/3del borrador C99 ). Lo mismo cuenta para C ++.

Johannes Schaub - litb
fuente
1
Esta respuesta sería mejor si mencionas que un char es / ya / efectivamente un entero, aunque sea un signo definido por la implementación (es decir, puede estar firmado o sin firmar) y tiene CHAR_BITS de largo.
Arafangion
No estaba seguro de saber que eso realmente lo ayuda. pero Chris hizo un buen punto con a..z no necesariamente contiguo. debería haber mencionado eso en su lugar. ahora ha ganado la carrera :)
Johannes Schaub - litb
1
Sin embargo, la tuya es mejor porque has calificado tu respuesta: Chris podría muy bien haber inventado sus cosas. :)
Arafangion
Gracias por la apreciación. Admito que no estaba seguro sobre el estado de C., así que miré hacia arriba y porque ya estaba en eso, pegué la referencia en la respuesta :)
Johannes Schaub - litb
Y por eso, señor, tiene un par de puntos más que yo. :)
Arafangion
29

Si, por alguna loca coincidencia, desea convertir una cadena de caracteres en un número entero, ¡también puede hacerlo!

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

valahora es 1024. Aparentemente atoi()está bien, y lo que dije antes solo se aplica a mí (en OS X (tal vez (inserte aquí la broma de Lisp))). Escuché que es una macro que se asigna aproximadamente al siguiente ejemplo, que usa strtol()una función de propósito más general para hacer la conversión en su lugar:

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

strtol() funciona así:

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

Se convierte en *stra long, tratándolo como si fuera un basenúmero base . Si **endptrno es nulo, contiene el primer carácter que no es un dígito strtol()encontrado (pero a quién le importa eso).

Chris Lutz
fuente
No hay problemas de subprocesos con atoi (no tiene datos estáticos) y no está en desuso. De hecho, es funcionalmente equivalente a: #define atoi (x) (int) (strtol ((x), NULL, 10)
Evan Teran
5
El problema con atoi es que usa 0 como un valor de "no se puede encontrar un número aquí", por lo que atoi ("0") y atoi ("uno") ambos devuelven 0. Si eso no funciona para lo que ' Lo está usando para, busque strtol () o sscanf ().
David Thornley
La otra ventaja de strtol, por supuesto, es que es posible que deba leer otras cosas de la misma cadena que vienen después del número.
dfeuer
@EvanTeran Desafortunadamente, si ejecuta Visual Studio, recibe una advertencia de depreciación (y no se compilará sin estar deshabilitado). VS ahora recomienda itoa_s().
Simon
7

Reste char '0' o int 48 así:

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

Explicación: Internamente funciona con valor ASCII . De la tabla ASCII, el valor decimal del carácter 5 es 53 y 0 es 48 . Entonces 53 - 48 = 5

O

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

Eso significa que si deduce 48 de cualquier carácter numérico, convertirá el número entero automáticamente.

Arif
fuente
6
char numeralChar = '4';
int numeral = (int) (numeralChar - '0');
Kevin Conner
fuente
numeralChar - '0'ya es de tipo int, por lo que no necesita el yeso. Incluso si no fuera así, el yeso no es necesario.
Alok Singhal
Eh, sí, eso obligaría, ¿no? Quizás Java haya coloreado mis percepciones. O tal vez estoy completamente equivocado e incluso coaccionaría en Java. :)
Kevin Conner
5

Para convertir el dígito de carácter al entero correspondiente. Haz lo que se muestra a continuación:

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

La lógica detrás del cálculo anterior es jugar con valores ASCII. El valor ASCII del carácter 8 es 56, el valor ASCII del carácter 0 es 48. El valor ASCII del entero 8 es 8.

Si restamos dos caracteres, la resta ocurrirá entre ASCII de caracteres.

int i = 56 - 48;   
i = 8;
Ashish
fuente
¿Por qué soy el único en votar esto? La explicación es tan simple e informativa: +1:
Brandon Benefield
0

Si es solo un solo carácter 0-9 en ASCII, entonces restar el valor del carácter cero ASCII del valor ASCII debería funcionar bien.

Si desea convertir números más grandes, lo siguiente será suficiente:

char *string = "24";

int value;

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

** no olvide verificar el estado (que debería ser 1 si funcionó en el caso anterior).

Pablo.

Paul W Homer
fuente
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 !!!
}
Alphaneo
fuente
0

Cuando necesito hacer algo como esto, horneo previamente una matriz con los valores que quiero.

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

Entonces la conversión es fácil

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

Este es básicamente el enfoque adoptado por muchas implementaciones de la biblioteca ctype. Puede adaptar esto trivialmente para que funcione también con dígitos hexadecimales.

Michael Anderson
fuente
Eso parece extremadamente ineficiente para convertir un solo dígito decimal (u octal). Si la parte relevante de su tabla de búsqueda no está en la caché L1, gastará un montón de ciclos para extraerla solo para obtener un valor. Francamente, tiendo a dudar que esto sea incluso una buena idea si está convirtiendo una gran cantidad de dígitos, pero tendría que medir eso. Es mucho más competitivo para el maleficio, por supuesto.
dfeuer
0

Mira esto,

char s='A';

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

por solo 0,1,2, ...., E, F.

Shiva
fuente
0

Solo usa la atol()función:

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

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

}
Pasillos Dylan
fuente
0

Si su dígito está, digamos, '5'en ASCII, se representa como el número binario 0011 0101(53). Cada dígito tiene los cuatro bits más altos 0011y los 4 bits más bajos representan el dígito en bcd. Así que lo haces

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

para obtener los 4 bits más bajos, o lo que es lo mismo, el dígito. En asm, usa andoperación en lugar de sub(como en las otras respuestas).

Garmekain
fuente
'5'es 53 ( 00110101)
eyllanesc
@eyllanesc Al principio era un 4. Gracias. Lo edité.
Garmekain
0

Aquí hay funciones auxiliares que permiten convertir dígitos en char a int y viceversa:

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

char toChar(int i) {
    return i + '0';
}
Maxim Makhun
fuente
-2

función de uso: atoi para matriz a entero, atof para matriz a tipo flotante; o

char c = '5';
int b = c - 48;
printf("%d", b);
K.tin
fuente
Varias respuestas ya cubrieron esto. Esto no agrega nada que no hayan cubierto ya.
ShadowRanger
-3

Lo convertiría en un int (o flotante o doble o lo que sea que quiera hacer con él) y lo almacenaría en otra variable.

SeanJA
fuente