Procedo a explicarlo. Lo primero que tenemos que saber es que hay un buffer por ahí que guarda lo que metemos por consola. Entonces, lo primero que hace std::cin>> es comprobar que no haya datos en ese buffer. Si no los hay, entonces procedemos a pedir datos por la consola. Si le damos a enter sin meter nada, entonces se imprimirá un espacio de línea y te pedirá de nuevo que ingreses datos (pues no has ingresado nada), y así hasta que introduzcas algún dato. Entonces, sabiendo que el buffer que maneja std::cin tiene algo, procedemos a comprobar. Lo primero que tenemos que saber es que std::cin recogerá datos de su buffer (que es como una cadena de caracteres) hasta que se encuentre con un espacio (' ') o un salto de línea ('\n'). Entonces, comprobamos si esos datos pueden ser almacenados en la variable que queríamos modificar. Por ejemplo, si la variable es de tipo entero pero "Hola", entonces se determina que no son datos compatibles. En ese caso, a esa variable se le asigna el valor 0 y se establece una bandera de error para que así sepamos que ha habido un error. Date cuenta que si los datos no corresponden, el buffer no se limpia, sino que permanece con los datos introducidos. Pero si los datos concuerdan, entonces se transforman al tipo de variable de entrada y se eliminan esos datos del buffer que maneja std::cin (se eliminan los datos hasta el espacio o salto de línea) y en último lugar se imprime un salto de línea.
Espero que lo hayan entendido y que despeje muchas dudas
Ejemplos prácticos de las consecuencias de este diagrama:
Código
#include <iostream> #include <limits> int main() { int nValor = 1; std::string cString; std::cout << "Introduzca un número: "; std::cin >> nValor; std::cin >> cString; std::cout << "nValor = " << nValor << std::endl; std::cout << "cString = \"" << cString << "\""; std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::cin.get(); return 0; }
Si compilamos y ejecutamos este código, obtendremos la siguiente salida (la salida está enmarcada. Lo otro son explicaciones):
Código:
Introduzca un número:
Vamos a teclear Hola (que evidentemente no es un entero como se pide) para ver que pasa:
Vamos a comprobar si estáis atentos. ¿Qué debería pasar ahora?
Bien, lo que va a pasar ahora es que std::cin >> cString va a ver que el buffer ya tiene datos guardados (no se han eliminado puesto que se ha producido un error), por lo que el thread no se va a detener como esperaríamos desde un principio, sino que directamente va a asignar esos datos a cString (aquí no hay ningún error, pues "Hola" es un string)
Entonces, una vez pulsado enter al introducir hola, la salida quedaría así:
Código:
Introduzca un número: Hola
nValor = 0
cString = "Hola"
Como veis, la variable 'nValor' tiene un valor de 0, pese a que la hemos inicializado como 1. Eso quiere decir que std::cin ha cambiado el valor de esta variable a 0 (tal y como sale en el diagrama).
Bueno, eso es todo. La mejor manera de que lo veáis es que ejecutéis el código por vosotros mismos y experimentéis. Un último apunte: la función std::cin.clear() lo que hace es limpiar la lista de errores producidos, no limpia el buffer!
Gracias por su atención.
Se aceptan sugerencias y/o optimicaciones