lunes, 15 de septiembre de 2008

getline luego de cin

Desde no hace mucho estoy intentando aprender C++. Viste que todo el mundo te dice: "Un informático no puedo no saber C++...", así que como creo que tienen algo de razón encaminé mi vida por el sendero del qué dirán.

C++ tiene muchas diferencias con respecto a otros lenguajes, no es solo aprenderse la nueva sintaxis, sino que existen nuevos conceptos previamente inexistentes para mi. Aparte de esto, a veces me encuentro con pequeños detalles pelotudos que me hacen renegar. Uno de esos detalles "pelotudos" se me dio este fin de semana: Simplemente utilizaba para leer un número entero el cin>>n y líneas más abajo para leer un renglón completo utilizaba un cin.getline().

Todo parecía y compilaba bien, pero al momento de ejecutar mi pequeño programa obtenía comportamientos NO esperados (para mi pobre lógica). Acá un fragmento de código que reproduce el problema:


cout<<"Cantidad de cadenas a ingresar:";
cin>>n;
for (int i=1;i<=n;i++){
cout<<"Cadena: ";
cin.getline(cadena);
}


La salida da lo siguiente:

Cantidad de cadenas a ingresar: 3
Cadena: Cadena:


Como se ve, el programa no esperó para ingresar la primer cadena, sino que siguió con el ingreso de la segunda cadena. ¿Por qué pasa esto?

El tema es que cin>> agrega al flujo de entrada previo al dato a leer un (caracter "\n") e ignora el último (caracter "\n"). Luego, cuando getline() encuentra en el flujo ingresado previamente el primer "\n" culmina su ejecución -recordemos que el getline() lee hasta encontrar un salto de carro, o sea un "\n"-.

Solución:

Yo la hice simple, uso luego del cin un getline que lea un caracter, de modo que captura el "\n" que tanto jodía antes, quedaría así:


char s[1];
cout<<"Cantidad de cadenas a ingresar:";
cin>>n;
cin.getline(s);

for (int i=1;i<=n;i++){
cout<<"Cadena: ";
cin.getline(cadena);
}