2012-05-30 21 views
22

Tengo curiosidad por saber por qué sucede esto.C++ Evaluación booleana

int main() 
{ 
    bool answer = true; 
    while(answer) 
    { 
     cout << "\nInput?\n"; 
     cin >> answer; 
    } 
return 0; 
} 

comportamiento esperado: 0 - programa sale, 1 - Solicita de nuevo, Cualquier distinto de cero entero distinto de 1 - Solicita de nuevo

comportamiento real: 0 - Como se esperaba, 1 - Como era de esperar, Cualquier distinto de cero entero distinto de 1 - bucle infinito

de http://www.learncpp.com/cpp-tutorial/26-boolean-values/

One additional note: when converting integers to booleans, 
the integer zero resolves to boolean false, 
whereas non-zero integers all resolve to true. 

¿Por qué el programa entra en un ciclo infinito?

+8

+1 para una pregunta bien planteada.El booleano es un arenque rojo; el verdadero problema tiene que ver con la forma en que funciona la entrada de flujo. Pruebe lo mismo con un int, y luego ingrese una letra y vea lo que sucede ;-) – Cameron

+0

Quizás estoy equivocado, pero cuando toma la entrada desde la línea de comando ... ¿no se convierte en una cadena? convirtiendo entre cadena y booleano? Que podría arruinar las cosas .... –

+0

Cameron hace un buen punto: un personaje se puede convertir a un número entero. Por ejemplo, '' A '== 65', pero pasa lo mismo. – chris

Respuesta

23

En efecto, el operator>> sobrecarga usado para leer un bool sólo permite un valor de 0 o 1 entrada como válida. La sobrecarga del operador se remite a la plantilla num_get clase, que lee el siguiente número de la secuencia de entrada y luego se comporta de la siguiente manera (C++ 11 §22.4.2.1/6):

  • Si el valor de ser almacenado es 0 luego se almacena false.

  • Si el valor es 1, entonces se almacena true.

  • De lo contrario true se almacena y ios_base::failbit se asigna a err.

(err aquí es el estado de error de la corriente desde el que está leyendo;. cin en este caso Observe que no es un texto adicional que especifica el comportamiento cuando se utiliza el manipulador boolalpha, que permite booleanos a ser insertado y extraído por medio de sus nombres, true y false;. he omitido estos otros detalles por razones de brevedad)

Cuando se introduce un valor que no sea cero o uno, el estado falla se encuentra en la corriente, lo que hace más extracciones fallar answer se establece en true y permanece en true para siempre, lo que causa el bucle infinito.

Debe probar el estado de la secuencia después de cada extracción, para ver si la extracción se realizó correctamente y si la secuencia todavía está en buen estado. Por ejemplo, puede reescribir su ciclo como:

bool answer = true; 
while (std::cin && answer) 
{ 
    std::cout << "\nInput?\n"; 
    std::cin >> answer; 
} 
+0

+1: Respuesta mucho mejor que la aceptada porque explica que el estándar exige este comportamiento. –

+0

De acuerdo :) Cambié la respuesta para reflejar una mejor comprensión. Definitivamente un ejemplo de por qué la validación de entrada siempre es importante :) –

15

Porque operator>> falla si la entrada no es 0 o 1, y cuando falla, no consume entrada. Entonces, el ciclo consiste en leer el dígito y luego quitarlo, varias veces.

trate de cambiar el código como el siguiente para verlo:

if (cin >> answer) { 
    cout << answer << endl; 
} else { 
    cerr << "oops" << endl; 
    break; 
} 
+4

Aunque generalmente desea escribir 'if (! (Cin >> answer))' en lugar de 'cin >> answer; if (cin.fail()) ' –

+0

Acabo de probar esto y el programa tipo" cuelga "si solo escribes algo y presionas return. Sin embargo, si lo vuelve a escribir, continuará evaluando la entrada. ¿Por qué? –

+3

Downvoted para propagar el anti-patrón 'if (cin.fail())'. Pruebe el resultado de la operación (como sugiere @SteveJessop), no el estado de la transmisión. –