¿Cómo convertir char a int?

123

¿Cuál es la forma correcta de convertir un chara int? Esto da 49:

int val = Convert.ToInt32('1');
//int val = Int32.Parse("1"); // Works

No quiero convertir a cadena y luego analizarlo.

tvr
fuente
1
Posible duplicado de esta pregunta.
RBT
Posible duplicado de Convertir char a int en C #
GSerg

Respuestas:

282

Me sorprende que nadie haya mencionado el método estático integrado en System.Char...

int val = (int)Char.GetNumericValue('8');
// val == 8
Joel Mueller
fuente
18
¡Buen lugar! +1 Muy extraño que devuelva un double, sin embargo
Marc Gravell
44
Estoy de acuerdo, no puedo entender por qué devuelve 'doble': ¿cómo puede un solo personaje representar un número de coma flotante?
Joel Mueller
49
Hay muchos caracteres Unicode que representan un número no entero, por ejemplo, U + 2153 .
dtb
26
@dtb: no lo había considerado. Char.GetNumericValue('⅓')de hecho vuelve 0.3333.... ¡Gracias por señalar eso!
Joel Mueller
1
Nota al pie: esta función no está disponible actualmente en NetMF.
GisMofx
40

que tal (para char c)

int i = (int)(c - '0');

¿Qué resta del valor de char?

Re la pregunta API (comentarios), ¿quizás un método de extensión?

public static class CharExtensions {
    public static int ParseInt32(this char value) {
        int i = (int)(value - '0');
        if (i < 0 || i > 9) throw new ArgumentOutOfRangeException("value");
        return i;
    }
}

luego usa int x = c.ParseInt32();

Marc Gravell
fuente
1
Debería haber mencionado, sabía esto, pero ¿hay alguna otra manera? ¿Quería saber si hay una API para hacer esto?
tvr
44
Si desea un comportamiento similar int.Parse, es decir, que se genere una excepción en una entrada no válida, deberá agregar una comprobación de límites adicional:if (i < 0 || i > 9) throw new FormatException();
Dirk Vollmar
@ user386338 Me temo que no hay.
Eugene Cheverda
@ user386338 - actualizado con una opción re API, que también incluye los comentarios de @ 0xA3
Marc Gravell
@ user386338 - vea la respuesta de Joel para un método API incorporado
Marc Gravell
21

Lo que todos están olvidando es explicar POR QUÉ sucede esto.

Un Char, es básicamente un número entero, pero con un puntero en la tabla ASCII. Todos los caracteres tienen un valor entero correspondiente como se puede ver claramente al intentar analizarlo.

Pranay tiene claramente un conjunto de caracteres diferente, por eso SU código no funciona. la única forma es

int val = '1' - '0';

porque esto busca el valor entero en la tabla de los '0'cuales es el 'valor base' restando su número en formato char de esto le dará el número original.

Stefanvds
fuente
15
int i = (int)char.GetNumericValue(c);

Otra opción más:

int i = c & 0x0f;

Esto debería lograr esto también.

Grif
fuente
4
int val = '1' - '0';

Esto se puede hacer usando códigos ASCII donde '0' es el más bajo y el número de caracteres cuenta desde allí

Tristan
fuente
¡Esto es brillante! Soy la solución más elegante aquí.
arabisoft
3
int val = '1' - 48;
x2.
fuente
@Luke Xu: '0' tiene un código ASCII 0x30 que es 48 en decimal, por lo que es lo mismo que '1' - '0'
NiKiZe
3

Puede usar el siguiente método de extensión:

public static class CharExtensions
    {
        public static int CharToInt(this char c)
        {
            if (c < '0' || c > '9')
                throw new ArgumentException("The character should be a number", "c");

            return c - '0';
        }
    }
Eugene Cheverda
fuente
1
@ 0xA3 La verificación del rango debe realizarse al principio del método en general. Semánticamente si vamos a convertir chara inttenemos que comprobar rango del parámetro de entrada, no la salida intde valor.
Eugene Cheverda
No es necesario verificar el intvalor del resultado porque el rango de caracteres numéricos se realizó al inicio del método, por lo que habrá un valor resultante correcto, si el carácter especificado no está en el rango de caracteres numéricos, se generará una excepción. La misma lógica que proporcionó, pero la verificación de rango se realiza al comienzo del método.
Eugene Cheverda
Lo siento, estaba leyendo mal su código de muestra. A veces es difícil ver las cosas más obvias. Apuesto a que el código decía if (c < 0 || c > 9)...
Dirk Vollmar
1

La forma más segura de lograr esto es utilizando el método Int32. TryParse. Ver aquí: http://dotnetperls.com/int-tryparse

MUG4N
fuente
TryParse es para cadenas, no para caracteres
tvr
Sí, pero todavía es la forma más segura de lograr la conversión
MUG4N
1
Convertir un solo carácter en un entero es un asunto de seguridad?
Joel Mueller
1
'Seguro' en este caso significa que no causará problemas si su carácter no es realmente un número ASCII, podría ser un carácter unicode de varios bytes.
Robin Bennett
1
int val = '1' & 15;

El binario de los caracteres ASCII 0-9 es:

0 - 00110000

1 - 00110001

2 - 00110010

3 - 00110011

4 - 00110100

5 - 00110101

6 - 00110110

7 - 00110111

8 - 00111000

9 - 00111001

y si toma en cada uno de ellos los primeros 4 LSB (usando bit a bit Y con 8'b00001111 que equivale a 15) obtendrá el número real (0000 = 0,0001 = 1,0010 = 2, ...)

Tomer Wolberg
fuente
¿Cómo funciona esto en términos de tipos? ¿Está utilizando un operador bit a bit entre un char y un int y luego devuelve un int? ¿El AND lógico usa la representación binaria tanto del carácter como del int y devuelve una representación binaria y luego, al definir var como int, usa esa representación?
mitomed
@mitnomed yes y si usa byte, por ejemplo, entonces usa la representación de byte.
Tomer Wolberg
0

Puedes probar algo como esto:

int val = Convert.ToInt32("" + '1');
briba
fuente
¿Por qué no solo .ToString ()?
Veikedo
@Veikedo quiere un int, y no una cadena.
briba
66
Quiero decirConvert.ToInt32('1'.ToString())
Veikedo
0

Una extensión de algunas otras respuestas que cubre la representación hexadecimal:

public int CharToInt(char c) 
{
    if (c >= '0' && c <= '9') 
    {
        return c - '0';
    }
    else if (c >= 'a' && c <= 'f') 
    {
        return 10 + c - 'a';
    }
    else if (c >= 'A' && c <= 'F') 
    {
        return 10 + c - 'A';
    }

    return -1;
}
Oleksandr Lytvyn
fuente