Bienvenido a nuestro sitio, aquí hallarás la resolución que estás buscando.
Solución:
Ignorar es exactamente lo que implica el nombre.
En su lugar, no “tira” algo que no necesita, sino que ignora la cantidad de caracteres que especifica cuando lo llama, hasta el carácter que especifica como punto de interrupción.
Funciona con búferes de entrada y salida.
Esencialmente, para std::cin
declaraciones que usa ignorar antes de hacer una getline
llamar, porque cuando un usuario ingresa algo con std::cin
, presionan enter y un 'n'
char se mete en el cin
buffer. Entonces si usas getline
, obtiene el carácter de nueva línea en lugar del string quieres. Entonces haces un std::cin.ignore(1000,'n')
y eso debería limpiar el búfer hasta el string eso que quieres. (El 1000 se coloca allí para omitir una cantidad específica de caracteres antes del punto de interrupción especificado, en este caso, el carácter n de nueva línea).
Estás pensando en esto de la manera incorrecta. Estás pensando en pasos lógicos cada vez cin
o getline
se utiliza. Ex. Primero pida un número, luego pida un nombre. Esa es la forma incorrecta de pensar cin
. Entonces te encuentras en una condición de carrera porque asumes que la transmisión es clara cada vez que solicitas una entrada.
Si escribe su programa únicamente como entrada, encontrará el problema:
void main(void)
double num;
string mystr;
cin >> num;
getline(cin, mystr);
cout << "num=" << num << ",mystr='" << mystr << "'" << endl;
En lo anterior, estás pensando, "primero obtén un número". Entonces escribes 123
presione enter, y su salida será num=123,mystr=''
. ¿Porqué es eso? Es porque en la corriente tienes 123n
y el 123
se analiza en el num
variable mientras n
todavía está en la corriente. Leyendo el documento para getline
función por defecto se verá en el istream
hasta un n
se encuentra. En este ejemplo, desde n
está en el flujo, parece que lo "omitió" pero funcionó correctamente.
Para que funcione lo anterior, tendrás que ingresar 123Hello World
que saldrá correctamente num=123,mystr='Hello World'
. Eso, o pones un cin.ignore
Entre los cin
y getline
para que se divida en los pasos lógicos que espera.
Por eso necesitas el ignore
mando. Porque está pensando en pasos lógicos en lugar de en forma de flujo, por lo que se encuentra en una condición de carrera.
Tome otro ejemplo de código que se encuentra comúnmente en las escuelas:
void main(void)
int age;
string firstName;
string lastName;
cout << "First name: ";
cin >> firstName;
cout << "Last name: ";
cin >> lastName;
cout << "Age: ";
cin >> age;
cout << "Hello " << firstName << " " << lastName << "! You are " << age << " years old!" << endl;
Lo anterior parece estar en pasos lógicos. Primero pregunte por el nombre, apellido y luego la edad. Así que si lo hicieras John
entrar, entonces Doe
entrar, entonces 19
Ingrese, la aplicación trabaja en cada paso lógico. Si lo piensa en "streams", simplemente puede ingresar John Doe 19
en la pregunta "Nombre:" y funcionaría también y parecería omitir las preguntas restantes. Para que lo anterior funcione en pasos lógicos, necesitaría ignore
el resto de la secuencia para cada ruptura lógica en las preguntas.
Solo recuerde pensar en la entrada de su programa como si estuviera leyendo de un "flujo" y no en pasos lógicos. Cada vez que llamas cin
se lee de una secuencia. Esto crea una aplicación bastante defectuosa si el usuario ingresa la entrada incorrecta. Por ejemplo, si ingresó un carácter donde un cin >> double
se espera, la aplicación producirá un resultado aparentemente extraño.
Respuesta corta
¿Por qué? Porque todavía quedan espacios en blanco (retornos de carro, tabulaciones, espacios, nueva línea) en el flujo de entrada.
¿Cuándo? Cuando está utilizando alguna función que no lo hace por sí sola, ignora los espacios en blanco iniciales. Cin de forma predeterminada ignora y elimina el espacio en blanco inicial, pero getline no ignora el espacio en blanco inicial por sí solo.
Ahora una respuesta detallada.
Todo lo que ingresa en la consola se lee desde la secuencia estándar stdin. Cuando ingresa algo, digamos 256 en su caso y presione enter, el contenido de la transmisión se convierte en 256n
. Ahora cin toma 256 y lo quita de la secuencia y n
aún quedando en el arroyo. Ahora, cuando ingrese su nombre, digamos Raddicus
, el nuevo contenido de la secuencia es nRaddicus
.
Ahora aquí viene la trampa. Cuando intenta leer una línea usando getline, si no se proporciona ningún delimitador como tercer argumento, getline por defecto lee hasta el carácter de nueva línea y elimina el carácter de nueva línea de la secuencia. Entonces, al llamar a una nueva línea, getline lee y descarta n
de la corriente y resulta en un vacío string read in mystr que parece que se omite getline (pero no lo es) porque ya había una nueva línea en la secuencia, getline no solicitará la entrada porque ya ha leído lo que se suponía que debía leer.
Ahora, ¿cómo ayuda cin.ignore aquí?
De acuerdo con el extracto de documentación ignorar de cplusplus.com-
istream & ignore (streamsize n = 1, int delim = EOF);
Extrae caracteres de la secuencia de entrada y los descarta, hasta que se hayan extraído n caracteres o uno se compare igual a delimitar.
La función también detiene la extracción de caracteres si se llega al final del archivo. Si esto se alcanza prematuramente (antes de extraer n caracteres o encontrar delim), la función establece el indicador eofbit.
Entonces, cin.ignore(256, 'n');
, ignora los primeros 256 caracteres o todo el carácter hasta que encuentra delimitador (aquí n en su caso), lo que ocurra primero (aquí n es el primer carácter, por lo que ignora hasta que se encuentra n).
Solo para su referencia, si no sabe exactamente cuántos caracteres omitir y su único propósito es borrar la transmisión para prepararse para leer un string usando getline o cin deberías usar cin.ignore(numeric_limits
.
Explicación rápida: Ignora los caracteres iguales al tamaño máximo de la secuencia o hasta que se encuentra un ' n', lo que ocurra primero.
Si sostienes algún reparo y capacidad de aclararse nuestro sección puedes escribir una acotación y con deseo lo observaremos.