2008-11-05 26 views
6

Estoy aprendiendo C++ y escribiendo pequeños programas a medida que avanzo. El siguiente es uno de esos programas:bucle infinito en C++

// This program is intended to take any integer and convert to the 
// corresponding signed char. 

#include <iostream> 

int main() 
{ 
    signed char sch = 0; 
    int n = 0; 
    while(true){ 
    std::cin >> n; 
    sch = n; 
    std::cout << n << " --> " << sch << std::endl; 
    } 
} 

Cuando ejecuto este programa y mantener las entradas al razonablemente pequeños valores absolutos, se comporta como se esperaba. Pero cuando ingreso entradas más grandes, por ejemplo, 10000000000, el programa escupe repetitivamente la misma salida. Algunas combinaciones de entrada causan un comportamiento errático. Por ejemplo:

#: ./int2ch 
10 
10 --> 

10000000000 
10 --> 

10 --> 

10 --> 

10 --> 

El programa escupe "10 ->" hasta que se destruye. (Con esta secuencia particular de entradas, la salida del programa cambia la velocidad de forma errática.) También noté que la salida de valores grandes está determinada por la entrada legal anterior así como también por el valor de la entrada ilegal actual.

¿Qué está pasando? (No me importa arreglar el programa, eso es fácil. Quiero entenderlo)

Respuesta

13

Básicamente, su secuencia cin está en un estado de falla y, por lo tanto, regresa inmediatamente cuando intenta leerla. Vuelva a escribir su ejemplo como este:

#include <iostream> 

int main() 
{ 
    signed char sch = 0; 
    int n = 0; 
    while(std::cin >> n){ 
    sch = n; 
    std::cout << n << " --> " << sch << std::endl; 
    } 
} 

cin >> n devolverá una referencia a cin, que se puede comprobar la "buena-dad" en una condicional. Así que, básicamente, el "while(std::cin >> n)" dice "mientras aún podía leer con éxito la entrada estándar, haga lo siguiente"

EDITAR: la razón por la que muestra repetidamente el último valor bueno ingresado es porque ese fue el último valor leído con éxito en n, la lecturas fallidas no va a cambiar el valor de n

EDIT: como se señala en un comentario, puede borrar el estado de error y vuelve a intentarlo algo como esto sería probablemente el trabajo y simplemente ignorar los malos números:

#include <iostream> 
#include <climits> 

int main() { 
    signed char sch = 0; 
    int n = 0; 
    while(true) { 
     if(std::cin >> n) { 
      sch = n; 
      std::cout << n << " --> " << sch << std::endl; 
     } else { 
      std::cin.clear(); // clear error state 
      std::cin.ignore(INT_MAX, '\n'); // ignore this line we couldn't read it 
     } 
    } 
} 
+0

Como alternativa, realice una llamada a std :: cin.clear() para eliminar el estado de error antes de la siguiente pasada del ciclo. – hark

3

Dado que usted está en una máquina de 32 bits, 10000000000 es un número demasiado grande para ser representado por un int. También la conversión de un int a un char solo le dará desde 0..255 o -128..127 dependiendo del compilador.

+0

Eso es 0..255 o -128..127, en realidad. :) – unwind

0

Un problema aquí es que un char tiene un tamaño de un byte, y por lo tanto puede solo mantenga un número entre -127 y 128. Un int, por otro lado, normalmente tiene 4 bytes y puede tomar valores mucho más grandes. El segundo problema es que está ingresando un valor que es demasiado grande incluso para un int.

+0

en primer lugar, la impresión de "algún personaje extraño" no es la causa, en segundo lugar, un carácter NO está firmado por defecto, esto depende del compilador. * A menudo * está firmado, pero no necesita ser. –

5

Sí, Evan Teran señaló la mayoría de las cosas ya. Una cosa que quiero agregar (ya que no puedo comentar su comentario todavía :)) es que debes poner la llamada a istream :: clear antes de llamar a istream :: ignore. La razón es que istream :: ignore igualmente se negará a hacer cualquier cosa si la transmisión todavía está en el estado de falla.

+0

Gracias, corregido. Obtienes un voto positivo para eso;) –