Menu

Flujos de cadenas en C++: análisis y construcción con stringstream

Cómo usar std::stringstream, istringstream y ostringstream para analizar texto, dividir cadenas por espacios en blanco, convertir entre cadenas y números, y construir cadenas formateadas en memoria.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Un flujo que vive en una cadena

Ya conoces cin y cout: flujos conectados al teclado y a la pantalla. Un flujo de cadena es la misma idea, salvo que los datos viven en una std::string en memoria. Escribes en él con << y extraes valores con >>, exactamente igual que con los flujos de consola, pero nada toca la terminal.

Esa única idea resuelve dos problemas cotidianos: analizar texto separándolo en valores tipados y construir una cadena formateada a partir de piezas mezcladas. Todo vive en la cabecera <sstream> y viene en tres variantes:

  • istringstream - solo lectura, para analizar entrada.
  • ostringstream - solo escritura, para construir salida.
  • stringstream - en ambas direcciones.

ss.str() devuelve todo lo escrito hasta ahora como una string simple. Los operadores << hicieron el mismo formateo de int a texto que hace cout; solo que capturaste el resultado en lugar de imprimirlo.

Análisis: extraer valores tipados

El verdadero poder aparece con >>. Dale algo de texto a un flujo y la extracción convierte cada token al tipo que pidas, saltando los espacios en blanco intermedios. Esta es la forma limpia de dividir una línea en varios campos tipados:

Cada >> lee hasta el siguiente espacio en blanco y convierte: "Ada" a una string, "36" a un int, "5.5" a un double. Fíjate en istringstream aquí: el tipo de solo entrada deja claro que únicamente estás analizando.

Convertir cadenas a números (de forma segura)

Una tarea frecuente es convertir una sola cadena como "42" en un int. Un stringstream lo hace, y además te dice si el texto era realmente un número válido, algo que atoi nunca hace:

Aquí ss >> value lee 123, se detiene en la a y tiene éxito, así que valida siempre la cadena completa si eso importa. Una comprobación robusta consiste en leer el número y luego confirmar que no queda nada significativo. Para conversiones sencillas de un solo valor, std::stoi, std::stod y compañía (explicados junto al casteo de tipos) son más cortos; recurre a stringstream cuando una cadena contenga varios valores mezclados.

Dividir una cadena por un delimitador

Dividir texto es la tarea de flujos de cadenas más buscada en Google. Combina un flujo con std::getline, que puede leer hasta cualquier carácter delimitador, no solo un salto de línea:

El patrón while (getline(...)) itera hasta que el flujo se agota, porque getline devuelve el flujo y este se evalúa como false cuando no queda nada. Quita el tercer argumento y dividirás por tokens separados por espacios con >>; elige el delimitador que use tu información.

Construir cadenas en memoria

En sentido inverso, ostringstream arma una cadena formateada sin el riesgo de desbordamiento de búfer de sprintf ni la frágil concatenación manual. Es perfecto para líneas de registro, nombres de archivo o mensajes compuestos de números y texto:

Todo el formateo de <iomanip> que usarías con cout - setw, setfill, setprecision, hex - funciona de forma idéntica en un flujo de cadena, así que obtienes salida rellenada, de ancho fijo o en hexadecimal capturada directamente en una string.

El detalle: restablece antes de reutilizar

La trampa que atrapa a todos es reutilizar un flujo sin restablecerlo. Una vez que un flujo llega al final de sus datos, sus indicadores eof y fail se quedan activados, y cada >> posterior no hace nada en silencio: ningún error, solo valores obsoletos:

stringstream ss("10");
int a, b;
ss >> a;            // a = 10, el flujo ahora al final -> indicador eof activado
ss.str("20");       // carga texto nuevo...
ss >> b;            // FALLA EN SILENCIO - los indicadores de error siguen activos, b no cambia

Debes limpiar el estado de error y el contenido. El orden correcto es clear() primero, luego str():

Dos errores relacionados: ss.clear() restablece los indicadores pero no vacía el búfer (usa ss.str("") para eso), y un stringstream al que sigues añadiendo con << seguirá creciendo: crea uno nuevo dentro del bucle en lugar de reutilizar uno sucio en cada iteración.

Siguiente: Arreglos

Los flujos de cadenas te dieron una forma limpia de convertir texto en valores tipados y viceversa, a menudo una lista entera de ellos, como el vector que llenaste al dividir el CSV. Para almacenar e indexar colecciones fijas de esos valores, necesitas el contenedor más fundamental del lenguaje. A continuación veremos los arreglos: cómo declararlos, indexarlos, recorrerlos y evitar el acceso fuera de límites que causa tanto comportamiento indefinido en C++.

Preguntas frecuentes

¿Qué es un stringstream en C++?

Un std::stringstream es un flujo respaldado por una string en lugar del teclado o un archivo. Escribes en él con << y lees de él con >>, igual que con cout y cin, lo que lo convierte en la herramienta estándar para analizar texto y construir cadenas en memoria. Vive en la cabecera <sstream>.

¿Cómo se convierte una cadena a int en C++ con stringstream?

Coloca el texto en un flujo y extráelo a un número: stringstream ss("42"); int n; ss >> n;. Comprueba if (ss) (o if (ss >> n)) para confirmar que la conversión realmente tuvo éxito. Para casos sencillos std::stoi es más corto, pero stringstream brilla cuando una sola cadena contiene varios valores mezclados.

¿Por qué necesito llamar a clear() en un stringstream?

Una vez que un flujo llega al final de sus datos, sus bits eof/fail quedan activados y cada >> posterior no hace nada en silencio. Si reutilizas el mismo stringstream con contenido nuevo, llama a ss.clear() para restablecer esos indicadores de error y luego a ss.str(newText) para cargar datos frescos; de lo contrario, las lecturas fallan sin avisar.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR