2011-05-03 11 views
17

En el siguiente bucle, si escribimos caracteres como la entrada cin en lugar de los números que se esperan, entonces entra en el bucle infinito. ¿Podría alguien explicarme por qué ocurre esto?Bucle infinito con cin cuando se escribe cadena mientras se espera un número

Cuando usamos cin, si la entrada no es un número, ¿hay formas de detectar esto para evitar los problemas mencionados anteriormente?

unsigned long ul_x1, ul_x2; 

while (1) 
{ 
    cin >> ul_x1 >> ul_x2; 
    cout << "ux_x1 is " << ul_x1 << endl << "ul_x2 is " << ul_x2 << endl; 
} 

Respuesta

23

bien que siempre tendrá un bucle infinito, pero sé lo que realmente quiere saber es por qué cin no impide solicitud de una entrada en cada repetición del bucle causa de su bucle infinito a FREERUN.

La razón es porque cin falla en la situación que describe y no leerá más entradas en esas variables. Al dar cin entrada incorrecta, cin entra en el fail state y deja de solicitar la línea de comando para la entrada que hace que el bucle se ejecute libremente.

Para la validación simple, puede intentar usar cin para validar sus entradas verificando si cin está en el estado de falla. Cuando se produce un error, clear the fail establece y fuerza la transmisión a throw away the bad input. Esto devuelve cin a la operación normal para que pueda solicitar más información.

if (cin.fail()) 
    { 
    cout << "ERROR -- You did not enter an integer"; 

    // get rid of failure state 
    cin.clear(); 

    // From Eric's answer (thanks Eric) 
    // discard 'bad' character(s) 
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 

    } 

Para la validación más sofisticado, es posible que desee leer en una cadena primero y hacer controles más sofisticados en la cadena para asegurarse de que coincide con lo que espera.

+0

O mejor aún, un stringstream. – Maxpm

+0

Si llamo a cin.clear() después de que cin falla, ¿por qué todavía no solicita una entrada la próxima vez que llamo cin >> x? –

+0

Esta respuesta no soluciona el problema de OP cumplido ya que está ** incompleto **. Por favor, eche un vistazo a mi respuesta :) –

6

Atención

Por favor, preste atención a la siguiente solución. Todavía no está completo para borrar el error en su caso. ¡Aún obtendrá un ciclo infinito!

if (cin.fail()) 
{ 
    cout << "Please enter an integer"; 
    cin.clear(); 
} 

solución completa

La razón es que necesita borrar el estado fallido de la corriente, así como caracteres no procesados ​​de descarte. De lo contrario, el personaje malo todavía está allí y todavía obtienes bucles infinitos. Puede simplemente std :: cin.ignore() para lograr esto. Por ejemplo,

if (cin.fail()) 
{ 
     cout << "Please enter an integer"; 
     // clear error state 
     cin.clear(); 
     // discard 'bad' character(s) 
     cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
} 

Otra solución

También puede utilizar getline y stringstream de lograr. Aquí hay un breve ejemplo.

string input; 
    while (1) 
    { 
     getline(cin, input); 
     stringstream(input) >> x; 
     cout << x << endl; 
    } 
+0

gracias, corrigió el error en mi respuesta –

1

Tal vez, es porque,

  1. cin es una función de transmisión. Cuando se ingresa un no numérico en lugar de los números , se ignora. Y usted está para volver a ingresar.
  2. Incluso si proporcionó entradas numéricas, , se le solicitarán más entradas ya que se encuentra en un bucle infinito.

Puede resolver este problema de la siguiente manera: 1. Cree una función para capturar una entrada de cadena. 2. devuélvalo como numérico después de la conversión. Use strtod() para la conversión.

Espero que esto ayude :)

0

Otra alternativa es operator!, es equivalente a la función miembro fail()

//from Doug's answer 
if (!cin) 
{ 
    cout << "ERROR -- You did not enter an integer"; 

    // get rid of failure state 
    cin.clear(); 

    // From Eric's answer (thanks Eric) 
    // discard 'bad' character(s) 
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
} 
Cuestiones relacionadas