cin >> vs getline(): por qué tu entrada de texto sale vacía
Respuesta corta: cin >> lee un solo bloque separado por espacios y deja la tecla Enter en el búfer de entrada. getline lee una línea entera — espacios incluidos — y consume el Enter. Si mezclas los dos sin limpiar, getline se queda con ese Enter sobrante y te devuelve una cadena vacía.
Este es el bug de entrada más común cuando empiezas con C++. La demo de abajo lo reproduce tal cual — lee un número y después una línea de texto. La caja de entrada envía 20 en una línea y Tom en la siguiente. Predice qué se imprime antes de ejecutar:
#include <iostream>
using namespace std;
int main() {
int age;
char name[20];
cin >> age; // lee 20 — ¡pero deja "\n" en el búfer!
cin.getline(name, 20); // lee el "\n" sobrante → cadena vacía
cout << "age=" << age << " name=[" << name << "]" << endl;
return 0;
}
name está vacío. cin >> age se detuvo en el Enter que tecleaste después de 20, y ese Enter se quedó en el búfer. El getline inmediatamente posterior se despertó, vio que la línea ya había terminado y devolvió una línea vacía. Tu programa no llegó a leer Tom.
El modelo mental: dos lectores distintos
cin >> x | getline(...) | |
|---|---|---|
| Lee | Hasta el siguiente espacio o salto de línea | La línea entera, espacios incluidos |
| ¿Salta los espacios en blanco iniciales? | Sí | No — toma la línea tal cual |
| ¿Consume el Enter final? | No — lo deja | Sí — así es como sabe que la línea terminó |
| Sirve para | Números, palabras sueltas | Nombres, frases, cualquier cosa con espacios |
Fíjate en cómo parte las palabras por sí solo — >> trata un espacio como «siguiente valor, por favor»:
#include <iostream>
using namespace std;
int main() {
char a[20], b[20];
cin >> a >> b; // «Tom Smith» se parte en el espacio
cout << "a=[" << a << "] b=[" << b << "]" << endl;
return 0;
}
Y getline conserva los espacios tal cual — lo que >> no puede hacer:
#include <iostream>
using namespace std;
int main() {
char line[30];
cin.getline(line, 30); // la línea entera, con espacios y todo
cout << "line=[" << line << "]" << endl;
return 0;
}
La solución: cómete el Enter sobrante
Entre una lectura con >> y un getline, descarta el salto de línea suelto con cin.ignore():
int age;
char name[20];
cin >> age;
cin.ignore(); // descarta el "\n" sobrante
cin.getline(name, 20); // ahora lee la línea de verdad: «Tom»
En un compilador de escritorio, la forma más a prueba de balas descarta todo lo que queda en la línea, no solo un carácter:
#include <limits>
cin.ignore(numeric_limits<streamsize>::max(), '\n');
Nota: nuestro motor del navegador cubre el núcleo didáctico y cin.ignore() lo hace fallar, así que los ejemplos de la solución van como bloques de código, no como demos ejecutables. Las demos usan arrays de caracteres (char name[20]) — en tu compilador de escritorio la forma habitual es std::string name; getline(cin, name); y el comportamiento del búfer es exactamente el mismo.
Reglas prácticas
- ¿Solo lees números o palabras con
>>? Ningún problema —>>salta los espacios en blanco iniciales en cada lectura. - ¿Mezclas
>>ygetline? Poncin.ignore()en cada frontera. Siempre. Aunque parezca funcionar sin él. - ¿Solo lees líneas completas? Usa
getlineen todo el código — sin trampas. - «¡Mi getline se salta!» ya es un bug que puedes diagnosticar en cinco segundos: algo anterior dejó un Enter en el búfer.
Preguntas de entrevista y tareas
- «¿Por qué falla el
getlinedespués decin?» — la respuesta de arriba, de un tirón:>>deja el salto de línea;getlinelo consume y devuelve una línea vacía. - «¿Cómo leerías un nombre y un apellido?» — dos lecturas con
>>(si siempre son exactamente dos palabras) o un sologetline(si el formato puede variar), y luego justifícalo. - «¿Qué devuelve
>>?» — el propio stream, y por esowhile (cin >> x)funciona como un bucle que lee hasta el fallo.
Practica en el editor
- Arregla la primera demo añadiendo
cin.ignore();entre las dos lecturas — confirma quename=[Tom]. - Lee dos líneas completas (el título de un libro y su autor) con dos llamadas a
getline— no hace falta ningún ignore. Explica por qué. - Rómpelo otra vez: quita el ignore y cambia la entrada a
20 99en líneas separadas. ¿Qué contienenameahora?
Relacionado: for vs while (el patrón de leer hasta un centinela usa estas lecturas), errores habituales del compilador (EN), qué es int main().