Convierte char a int en C y C ++

401

¿Cómo convierto una chara una inten C y C ++?

mainajaved
fuente
1
@ Matt: sería una buena idea ser más concreto. preguntar sobre una generalización solo invita a respuestas generalizadas que no son aplicables o incluso correctas para su tarea. tenga en cuenta que, cuando tenga que preguntar, probablemente no sepa lo suficiente para generalizar correctamente.
Saludos y hth. - Alf
@Alf P. Steinbach: La pregunta original era vaga sobre qué idioma. Con palabras clave cy c++, creo que las respuestas que enfrentan ambos idiomas son razonables.
Matt Joiner
8
Desde mi amplia experiencia en otros foros técnicos, mi intuición es que el OP realmente significa "¿cómo tomo la representación textual de un número (en la base 10) y la convierto en el número correspondiente?" En términos generales, los neófitos C y C ++ generalmente tienen ideas increíblemente confusas sobre cómo funciona el texto en esos lenguajes y lo que charrealmente significa.
Karl Knechtel
3
@KarlKnechtel: Si eso es cierto (le doy alrededor de 50/50, ya que muchos de los primeros tutoriales también alientan a sacar los valores ASCII de los caracteres, a pesar de que ASCII no cubre el rango completo), el OP necesita claridad, pero eso es un engaño de stackoverflow.com/questions/439573/… .
Fred Nurk
3
El OP tuvo tres horas para aclarar esta pregunta y no lo hizo. Tal como están las cosas, no hay forma de saber qué se pregunta realmente. Votado para cerrar.
sbi

Respuestas:

552

Depende de lo que quieras hacer:

Para leer el valor como un código ASCII, puede escribir

char a = 'a';
int ia = (int)a; 
/* note that the int cast is not necessary -- int ia = a would suffice */

para convertir el carácter '0' -> 0, '1' -> 1etc, se puede escribir

char a = '4';
int ia = a - '0';
/* check here if ia is bounded by 0 and 9 */

Explicación :
a - '0'es equivalente a ((int)a) - ((int)'0'), lo que significa que los valores ascii de los caracteres se restan entre sí. Como 0viene directamente antes 1en la tabla ascii (y así sucesivamente hasta 9), la diferencia entre los dos da el número que arepresenta el personaje .

Foo Bah
fuente
14
ia = (a - '0')% 48;
Kshitij Banerjee
@KshitijBanerjee Esa no es una buena idea por dos razones: le da un número negativo para caracteres ascii antes de '0' (como &-> -10), y le da números mayores que 10 (como x-> 26)
SheetJS
2
int ia = a - '0' - eso es lo que necesitas
funk
55
@ kevin001 Si desea convertir el carácter a int y un carácter '1'proporciona un número ASCII que no lo es 1, debe eliminar el desplazamiento '0'para realinearlo y contar de 0 a 9. Los números consecutivos 1-9 son adyacentes en el número entero ascii.
krisdestruction
No se requiere / desea el reparto
Craig Estey
97

Bueno, en el código ASCII, los números (dígitos) comienzan desde 48 . Todo lo que necesitas hacer es:

int x = (int)character - 48;
Vlad Isoc
fuente
19
@chad: no solo es más legible, también es más portátil. C y C ++ no garantizan una representación ASCII, pero sí garantizan que cualquier representación que esté en uso, las representaciones de los 10 dígitos decimales son contiguas y en orden numérico.
Ben Voigt
Lo único que habría cambiado es cumplir 48 años, lo que parece un poco "mágico"'0'
ArielGro
59

C y C ++ siempre promueven tipos al menos int. Además, los literales de caracteres son de tipo intC ychar en C ++.

Puede convertir un chartipo simplemente asignándolo a un int.

char c = 'a'; // narrowing on C
int a = c;
Matt Joiner
fuente
3
También podría utilizar el unario muy poco apreciado operator+()para este propósito.
Cubbi
24
-1 La respuesta es incorrecta para la única interpretación significativa de la pregunta. Este (código int a = c;) mantendrá cualquier valor negativo, que las funciones de biblioteca estándar de C no pueden manejar. Las funciones de la biblioteca estándar de C establecen el estándar de lo que significa manejar charvalores como int.
Saludos y hth. - Alf
66
@ Matt: Me quedo con el voto negativo. ¡Lo fortalecería si fuera posible! La interpretación de la pregunta que usted y otros han asumido no es significativa, porque es demasiado trivial, y porque para la combinación particular de tipos del OP hay un problema práctico no muy trivial muy importante. El consejo que da es directamente peligroso para el novato. Lo más probable es que resulte en Comportamiento indefinido para sus programas que usan funciones de clasificación de caracteres de biblioteca estándar de C. Re ref. a la respuesta de @ Sayam, ha eliminado esa respuesta.
Saludos y hth. - Alf
3
-1 por ser incorrecto: isupper () tendrá resultados indefinidos si pasa un carácter de 1252 bits altos.
Chris Becke
1
¿Qué quieres decir con "siempre promocionar"? Los valores se promueven durante las conversiones implícitas, ciertos tipos de parámetros que pasan (por ejemplo, a una función varargs) y cuando un operador debe hacer que sus operandos sean compatibles. Pero ciertamente hay momentos en que no se promueve un valor (como si le paso un carácter a una función que espera un carácter), de lo contrario no tendríamos ningún tipo más pequeño que un int.
Adrian McCarthy
31

char es solo un entero de 1 byte. ¡No hay nada mágico con el tipo char! Así como puedes asignar un short a un int, o un int a un long, puedes asignar un char a un int.

Sí, el nombre del tipo de datos primitivo es "char", lo que insinúa que solo debe contener caracteres. Pero en realidad, "char" es solo una mala elección de nombre para confundir a todos los que intentan aprender el idioma. Un mejor nombre para él es int8_t, y puede usar ese nombre en su lugar, si su compilador sigue el último estándar de C.

Aunque, por supuesto, debe usar el tipo char al hacer el manejo de cadenas, porque el índice de la tabla ASCII clásica cabe en 1 byte. Usted podría sin embargo hacer manejo de cadenas de enteros normales, así, aunque no hay ninguna razón práctica en el mundo real por la que va a querer hacer eso. Por ejemplo, el siguiente código funcionará perfectamente:

  int str[] = {'h', 'e', 'l', 'l', 'o', '\0' };

  for(i=0; i<6; i++)
  {
    printf("%c", str[i]);
  }

Debes darte cuenta de que los caracteres y las cadenas son solo números, como todo lo demás en la computadora. Cuando escribe 'a' en el código fuente, se procesa previamente en el número 97, que es una constante entera.

Entonces, si escribes una expresión como

char ch = '5';
ch = ch - '0';

esto es realmente equivalente a

char ch = (int)53;
ch = ch - (int)48;

que luego pasa por las promociones de enteros en lenguaje C

ch = (int)ch - (int)48;

y luego truncado a un carácter para ajustarse al tipo de resultado

ch = (char)( (int)ch - (int)48 );

Hay muchas cosas sutiles como esta sucediendo entre líneas, donde char se trata implícitamente como un int.

Lundin
fuente
Como la pregunta no está etiquetada ascii, no debe asumir ninguna codificación específica. Establecer charigual a int8_testá mal porque igualmente podría ser uint8_to uint24_t.
Roland Illig
1
@RolandIllig No, a charsiempre es 1 byte y si los tipos int8_t/ uint8_texisten en el sistema dado (lo cual es muy probable), podrán ajustar el resultado de a char, porque entonces serán 8 bits. En sistemas altamente exóticos como varios DSP obsoletos, chartendrá 16 bits y uint8_tno existirá. Escribir código para la compatibilidad con DSP obsoletos no tiene sentido, al igual que escribir para la compatibilidad con los sistemas de complemento o signo y magnitud. Gran pérdida de tiempo, ya que tales sistemas apenas existen en el mundo real.
Lundin
18

(Esta respuesta aborda el lado C ++ de las cosas, pero el problema de la extensión del signo también existe en C).

El manejo de los tres chartipos ( signed, unsignedy char) es más delicado de lo que parece. Los valores en el rango de 0 a SCHAR_MAX(que es 127 para un 8 bits char) son fáciles:

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
int n = c;

Pero, cuando somevalueestá fuera de ese rango, solo pasar unsigned charle da resultados consistentes para los "mismos" charvalores en los tres tipos:

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
// Might not be true: int(c) == int(sc) and int(c) == int(uc).
int nc = (unsigned char)c;
int nsc = (unsigned char)sc;
int nuc = (unsigned char)uc;
// Always true: nc == nsc and nc == nuc.

Esto es importante cuando se utilizan funciones de ctype.h , como isuppero toupper, debido a la extensión del signo:

char c = negative_char;  // Assuming CHAR_MIN < 0.
int n = c;
bool b = isupper(n);  // Undefined behavior.

Tenga en cuenta que la conversión a través de int es implícita; esto tiene el mismo UB:

char c = negative_char;
bool b = isupper(c);

Para solucionar esto, vaya unsigned char, lo que se hace fácilmente envolviendo las funciones ctype.h a través de safe_ctype :

template<int (&F)(int)>
int safe_ctype(unsigned char c) { return F(c); }

//...
char c = CHAR_MIN;
bool b = safe_ctype<isupper>(c);  // No UB.

std::string s = "value that may contain negative chars; e.g. user input";
std::transform(s.begin(), s.end(), s.begin(), &safe_ctype<toupper>);
// Must wrap toupper to eliminate UB in this case, you can't cast
// to unsigned char because the function is called inside transform.

Esto funciona porque cualquier función que tome cualquiera de los tres tipos de caracteres también puede tomar los otros dos tipos de caracteres. Lleva a dos funciones que pueden manejar cualquiera de los tipos:

int ord(char c) { return (unsigned char)c; }
char chr(int n) {
  assert(0 <= n);  // Or other error-/sanity-checking.
  assert(n <= UCHAR_MAX);
  return (unsigned char)n;
}

// Ord and chr are named to match similar functions in other languages
// and libraries.

ord(c)siempre le da un valor no negativo, incluso cuando se pasa un valor negativo charo negativo signed char, y chrtoma cualquier valor que ordproduce y devuelve exactamente el mismochar .

En la práctica, probablemente solo transmitiría en unsigned charlugar de usar estos, pero lo hacen de forma sucinta, proporcionan un lugar conveniente para agregar la comprobación de errores para int-to- char, y sería más corto y más claro cuando necesite usarlos varias veces en estrecha proximidad.

Fred Nurk
fuente
7

Depende de lo que quieras decir con "convertir".

Si tiene una serie de caracteres que representa un número entero, como "123456", hay dos formas típicas de hacerlo en C: utilice una conversión de propósito especial como atoi () o strtol () , o el sscanf de propósito general () . C ++ (que es realmente un lenguaje diferente disfrazado de una actualización) agrega un tercer flujo de cadena.

Si quiere decir que desea que el patrón de bits exacto en una de sus intvariables sea tratado como unchar , eso es más fácil. En C, los diferentes tipos enteros son realmente más un estado mental que los "tipos" separados reales. Simplemente comience a usarlo donde charse le solicite, y debería estar bien. Es posible que necesite una conversión explícita para que el compilador deje de quejarse en ocasiones, pero todo lo que debería hacer es soltar cualquier bit adicional más allá de 256.

TED
fuente
6

Tengo absolutamente nullhabilidades en C, pero para un análisis simple:

char* something = "123456";

int number = parseInt(something);

... esto funcionó para mí:

int parseInt(char* chars)
{
    int sum = 0;
    int len = strlen(chars);
    for (int x = 0; x < len; x++)
    {
        int n = chars[len - (x + 1)] - '0';
        sum = sum + powInt(n, x);
    }
    return sum;
}

int powInt(int x, int y)
{
    for (int i = 0; i < y; i++)
    {
        x *= 10;
    }
    return x;
}
Henke
fuente
Este código invoca rápidamente un comportamiento indefinido y, por lo tanto, no es adecuado para copiar y pegar. (desbordamiento int)
Roland Illig
4

Presumiblemente, desea esta conversión para usar funciones de la biblioteca estándar de C.

En ese caso, hacer (sintaxis de C ++)

typedef unsigned char UChar;

char myCppFunc( char c )
{
    return char( someCFunc( UChar( c ) ) );
}

La expresión se UChar( c )convierte unsigned charen para deshacerse de los valores negativos, que, a excepción de EOF, no son compatibles con las funciones de C.

Luego, el resultado de esa expresión se usa como argumento real para un intargumento formal. Donde obtienes la promoción automática int. Alternativamente, puede escribir ese último paso explícitamente, comoint( UChar( c ) ) , pero personalmente me parece demasiado detallado.

Saludos y hth.

Saludos y hth. - Alf
fuente
0

Estaba teniendo problemas para convertir una matriz de caracteres como "7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e"en su valor entero real que podría ser representado por '7C' como un valor hexadecimal. Entonces, después de buscar ayuda, creé esto, y pensé que sería genial compartirlo.

Esto separa la cadena de caracteres en sus enteros correctos, y puede ser útil para más personas que solo yo;)

unsigned int* char2int(char *a, int len)
{
    int i,u;
    unsigned int *val = malloc(len*sizeof(unsigned long));

    for(i=0,u=0;i<len;i++){
        if(i%2==0){
            if(a[i] <= 57)
                val[u] = (a[i]-50)<<4;
            else
                val[u] = (a[i]-55)<<4;
        }
        else{
            if(a[i] <= 57)
                val[u] += (a[i]-50);
            else
                val[u] += (a[i]-55);
            u++;
        }
    }
    return val;
}

¡Espero eso ayude!

Mathorlaz
fuente
¿Alguna vez has probado este código? El 50 debería ser un 48, el 55 solo funciona para letras mayúsculas ASCII, mientras que su ejemplo contiene letras minúsculas.
Roland Illig
0

Para char o short to int, solo necesita asignar el valor.

char ch = 16;
int in = ch;

Lo mismo para int64.

long long lo = ch;

Todos los valores serán 16.

Riwels
fuente