2009-04-23 24 views
33

Si quiero convertir un solo numérico char a su valor numérico, por ejemplo, si:Char a int conversión en C

char c = '5'; 

y quiero c para mantener 5 en lugar de '5', es 100% portátil haciéndolo así?

c = c - '0'; 

oí que todos los juegos de caracteres almacenar los números en orden consecutivo, así que supongo que sí, pero me gustaría saber si hay una función de biblioteca organizada para hacer esta conversión, y cómo se hace convencionalmente. Soy un verdadero principiante :)

+0

@ binary- el duplicado publicado es para C++, a pesar de que la respuesta es la misma, se aplica a un idioma diferente – TStamper

+0

Es cierto, el matiz se me escapó. –

+0

Buena pregunta .. – SNce

Respuesta

27

Sí, esto es una conversión segura. C requiere que funcione. Esta garantía está en la sección 5.2.1 párrafo 2 de la última norma ISO C, un proyecto reciente de las cuales es N1570:

Tanto la fuente básica y conjuntos de carácter básico de ejecución tendrán los siguientes miembros:
[ ...]
los 10 dígitos decimales
0 1 2 3 4 5 6 7 8 9
[...]
en tanto la fuente como de ejecución de juegos de caracteres básicos, el valor de cada personaje después de 0 en el abov La lista de dígitos decimales debe ser uno mayor que el valor del anterior.

Tanto ASCII como EBCDIC, y los conjuntos de caracteres derivados de ellos, satisfacen este requisito, por lo que el estándar C pudo imponerlo. Tenga en cuenta que las letras son y no contiguas en EBCDIC, y C no las requiere.

No hay función de biblioteca que lo haga por un solo char, lo que se necesita para construir una cadena primero:

int digit_to_int(char d) 
{ 
char str[2]; 

str[0] = d; 
str[1] = '\0'; 
return (int) strtol(str, NULL, 10); 
} 

Usted podría también utilizar la función atoi() para hacer la conversión, una vez que tenga una cadena , pero strtol() es mejor y más seguro.

Como los comentaristas han señalado, es extremadamente exagerado llamar a una función para hacer esta conversión; su enfoque inicial para restar '0' es la forma correcta de hacerlo. Solo quería mostrar cómo se usaría el enfoque estándar recomendado para convertir un número como una cadena a un número "verdadero", aquí.

+3

Esta es una manera bastante compleja y costosa de hacer lo que es una operación muy directa, es decir, int i = d - '0' –

+2

Esta es una respuesta a su pregunta pero no la mejor respuesta. Esto es excesivo. Usted respondió su propia pregunta con c = c-'0 '; - Esa es la mejor respuesta. – zooropa

+1

Sí, por supuesto, el uso de una función es excesivo. Tal vez debería haber sido más claro en esa parte. – unwind

1

Sí. Esto es seguro siempre que use caracteres ascii estándar, como lo es en este ejemplo.

5

Puede usar atoi, que es parte de la biblioteca estándar.

9

Prueba esto:

char c = '5' - '0'; 
+0

+1. Solo voy a sugerir envolver esto en una función. – MyNameIsZero

2

Como solo está convirtiendo un carácter, la función atoi() es exagerada. atoi() es útil si está convirtiendo representaciones de cadena de números. Las otras publicaciones han dado ejemplos de esto. Si leo tu publicación correctamente, solo estás convirtiendo un carácter numérico. Entonces, solo vas a convertir un personaje que es el rango de 0 a 9.En el caso de la conversión solamente un carácter numérico, su sugerencia para restar '0' le dará el resultado que desea. La razón por la que esto funciona es porque los valores ASCII son consecutivos (como usted dijo). Por lo tanto, restando el valor ASCII de 0 (valor ASCII 48 - ver ASCII Table de valores) de un carácter numérico dará el valor del número. Entonces, su ejemplo de c = c - '0' donde c = '5', lo que realmente está pasando es 53 (el valor ASCII de 5) - 48 (el valor ASCII de 0) = 5.

Cuando Primero publiqué esta respuesta, no tomé en consideración tu comentario acerca de ser 100% portátil entre diferentes conjuntos de caracteres. Seguí mirando alrededor y parece que tu respuesta sigue siendo en su mayoría correcta. El problema es que está usando un char que es un tipo de datos de 8 bits. Lo cual no funcionaría con todos los tipos de caracteres. Lee este artículo por Joel Spolsky on Unicode para obtener más información sobre Unicode. En este artículo, dice que usa wchar_t para los personajes. Esto ha funcionado bien para él y publica su sitio web en 29 idiomas. Entonces, necesitarías cambiar tu char a wchar_t. Aparte de eso, dice que el personaje bajo el valor 127 y más abajo es básicamente el mismo. Esto incluiría personajes que representan números. Esto significa que la matemática básica que propones debería funcionar para lo que estabas tratando de lograr.

4
int i = c - '0'; 

Debe tener en cuenta que este no realiza ninguna validación contra el carácter - por ejemplo, si el personaje era 'un', entonces se podrían obtener 91 - 48 = 49. Sobre todo si se trata con el usuario o entrada de red, probablemente deba realizar una validación para evitar el mal comportamiento en su programa. Sólo tienes que comprobar la gama:

if ('0' <= c && c <= '9') { 
    i = c - '0'; 
} else { 
    /* handle error */ 
} 

Tenga en cuenta que si desea que su conversión a manejar dígitos hexadecimales se puede comprobar el alcance y realizar el cálculo correspondiente.

if ('0' <= c && c <= '9') { 
    i = c - '0'; 
} else if ('a' <= c && c <= 'f') { 
    i = 10 + c - 'a'; 
} else if ('A' <= c && c <= 'F') { 
    i = 10 + c - 'A'; 
} else { 
    /* handle error */ 
} 

que convertirá un solo carácter hexadecimal, mayúsculas o minúsculas independiente, en un entero.

+0

ctype.h proporciona las siguientes funciones/macros para realizar la validación: isdigit, isxdigit, isspace y muchas otras. Ver la página man. –

0

Normalmente, si no hay ninguna garantía de que su entrada está en el rango de '0' .. '9', que tendría que realizar una comprobación de la siguiente manera:

if (c >= '0' && c <= '9') { 
    int v = c - '0'; 
    // safely use v 
} 

Una alternativa es utilizar una tabla de búsqueda. Se obtiene la comprobación sencilla gama y conversión con menos (y posiblemente más rápido) Código:

// one-time setup of an array of 256 integers; 
// all slots set to -1 except for ones corresponding 
// to the numeric characters 
static const int CHAR_TO_NUMBER[] = { 
    -1, -1, -1, ..., 
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // '0'..'9' 
    -1, -1, -1, ... 
}; 

// Now, all you need is: 

int v = CHAR_TO_NUMBER[c]; 

if (v != -1) { 
    // safely use v 
} 

P. S. Yo sé que esto es una exageración . Solo quería presentarlo como una solución alternativa que puede no ser inmediatamente evidente.

+1

#include .... if (isdigit (c)) {...} – sigjuice

0

Como otros han sugerido, pero envuelto en una función:

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

Ahora sólo tiene que utilizar la función. Si, por la línea, decide utilizar un método diferente, sólo tiene que cambiar la aplicación (rendimiento, las diferencias de conjunto de caracteres, lo que sea), usted no necesita cambiar las personas que llaman.

Esta versión supone que c contiene un char que representa un dígito. Puede verificarlo antes de llamar a la función, utilizando la función isdigit de ctype.h.

0

Puesto que los códigos ASCII para '0', '1', '2' .... se colocan 48 a 57 que son esencialmente continua. Ahora las operaciones aritméticas requieren la conversión de tipo de datos char a int tipo de datos.Por lo tanto, básicamente lo que está haciendo es: 53-48 y, por lo tanto, almacena el valor 5 con el que puede realizar operaciones enteras. Tenga en cuenta que al convertir de nuevo de int a char, el compilador no da error sino que realiza una operación de módulo 256 para poner el valor en su rango aceptable

0

puede simplemente usar la función atol():

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

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

}