2010-03-09 15 views
9

¿Qué ocurre cuando cin >> letter to int variable? Probé el código simple para agregar 2 números enteros, primero los leí, luego los agregué. Pero cuando ingreso una letra, simplemente falla e imprime toneladas de números en la pantalla. Pero, ¿qué causa este error? Quiero decir, esperaba que se cargara y utilizara el código ASCII de esa letra.C++ character to int

+1

¿Puedes publicar el código que usaste? –

Respuesta

3

si explícitamente transfieres tu char a una int, usará el código ASCII, de lo contrario no se lanzará solo a int, por lo que obtienes los resultados extraños que estás obteniendo.

1

Usted podría utilizar int istream::get();

10

que se supone que tiene un código como éste:

int n; 
while (someCondition) { 
    std::cin >> n; 
    ..... 
    std::cout << someOutput; 
} 

Al entrar en algo que no puede ser leído como un entero, la corriente (std :: cin) entra en un fallido estado y todos los siguientes intentos de entrada fallan siempre y cuando no se ocupe del error de entrada.

Puede comprobar el éxito de una operación de entrada:

if (!(std::cin >> n)) //failed to read int 

y puede restaurar el flujo a un estado bueno y desechar caracteres no procesados ​​(la entrada que provocó el fallo de entrada):

std::cin.clear(); 
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 

Otra posibilidad es aceptar la entrada en una variable de cadena (que rara vez falla) e intentar convertir la cadena a int.

Este es un problema muy común con la entrada y debería haber toneladas de hilos al respecto aquí y en otros lugares.

+0

Gracias, así que si lo hago bien, stdout en realidad envía código ASCII para programar, pero std :: cin reconoce qué tipo es y lo usa de esa manera. – Vit

+1

Si espera ingresar a ** int ** variable, entonces "123" está bien, pero "xyz" hace que la operación de entrada falle. La transmisión obtiene solo una secuencia de caracteres de la entrada, pero realiza las conversiones según el tipo que solicitó, e indica que no lo hizo de una manera que puede y debe probar. – visitor

1

El problema es que cuando lee en una variable entera, usando flujos de C++, el método de entrada espera caracteres que pueden componer un número, como '+', '-', '0' ... '9 '. Cualquier carácter que no esté en este conjunto termina la entrada y se crea un número a partir de estos caracteres.

Para obtener el valor ASCII de un carácter, debe ingresar los datos en una variable char. Internamente, tiene el valor ASCII (siempre que el programa no lea caracteres de 16 bits o EBCDIC). Si desea ver el valor ASCII, deberá generar la variable char como un número entero (que generalmente requiere un molde antes de la salida).

Si falla la lectura de un entero, su programa debe informar al usuario que la entrada fue incorrecta. El programa puede requerir que el usuario ingrese el número nuevamente antes de que el programa pueda procesar los datos de entrada.

1

Cuando haces algo como:

int x; 
cin >> x; 

se están dando instrucciones C++ esperar para leer un int del teclado. En realidad, cuando ingresa algo que no es int, el flujo de entrada (entrada estándar, en este caso) se vuelve inutilizable debido a su estado de error.

Es por eso que personalmente prefiero leer cadenas y convertirlas en números si es necesario. Hay funciones de conversión en la parte C de la biblioteca estándar de C++ que pueden ayudar con esto.

double cnvtToNumber(const std::string &num) 
{ 
    char * ptr; 
    double toret = strtod(num.c_str(), &ptr); 

    if (*ptr != 0) { // If it got to the end of the string, then it is correct. 
     throw std::runtime_error("input was not a number"); 
    } 
    return toret; 
} 

Aquí está convirtiendo un número, y detectando si la conversión fue correcta.strtod(s) solo se detendrá cuando encuentre el final de la cadena o un espacio. Con el fin de evitar los espacios finales engañando a la función, usted podría necesitar una función de ajuste:

std::string &trim(std::string &str) 
{ 
    // Remove trailing spaces 
    unsigned int pos = str.length() -1; 

    while(str[ pos ] == ' ') { 
     --pos; 
    } 

    if (pos < (str.length() -1)) { 
     str.erase(pos + 1); 
    } 

    // Remove spaces at the beginning 
    pos = 0; 
    while(str[ pos ] == ' ') { 
     ++pos; 
    } 

    if (pos < 1) { 
     str.erase(0, pos); 
    } 

    return str; 
} 

Ahora se puede leer de forma segura desde la consola (o cualquier otra corriente de entrada):

int main() 
{ 
    std::string entry; 

    try { 
     std::getline(std::cin, entry); 
     int age = cnvtToNumber(trim(entry)); 

     std::cout << age << std::endl; 
    } catch(const std::exception &e) { 
     std::cerr << e.what() << std::endl; 
    } 
} 

Por supuesto que puede pierda precisión si siempre lee double y luego conviértelos. Hay funciones específicas para enteros (strtol(s)), en caso de que quiera investigar más a fondo.