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 >> xgetline(...)
LeeHasta el siguiente espacio o salto de líneaLa 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 dejaSí — así es como sabe que la línea terminó
Sirve paraNúmeros, palabras sueltasNombres, 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

Preguntas de entrevista y tareas

  1. «¿Por qué falla el getline después de cin?» — la respuesta de arriba, de un tirón: >> deja el salto de línea; getline lo consume y devuelve una línea vacía.
  2. «¿Cómo leerías un nombre y un apellido?» — dos lecturas con >> (si siempre son exactamente dos palabras) o un solo getline (si el formato puede variar), y luego justifícalo.
  3. «¿Qué devuelve >>?» — el propio stream, y por eso while (cin >> x) funciona como un bucle que lee hasta el fallo.

Practica en el editor

  1. Arregla la primera demo añadiendo cin.ignore(); entre las dos lecturas — confirma que name=[Tom].
  2. 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é.
  3. Rómpelo otra vez: quita el ignore y cambia la entrada a 20 99 en líneas separadas. ¿Qué contiene name ahora?

Relacionado: for vs while (el patrón de leer hasta un centinela usa estas lecturas), errores habituales del compilador (EN), qué es int main().