Menu

Cadenas en C++: fundamentos de std::string, métodos y trampas

Cómo usar std::string en C++: construir, unir, buscar y cortar texto de forma segura, y por qué casi nunca conviene un char* crudo para trabajo real.

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

std::string: texto que se gestiona solo

En la página anterior viste cómo los punteros inteligentes permiten que un objeto sea dueño de un recurso y lo libere automáticamente. std::string es esa misma idea aplicada al texto: posee un búfer de caracteres, lo hace crecer cuando añades algo y lo libera cuando la cadena sale de ámbito. Nunca llamas a new, nunca cuentas bytes y nunca te preocupas por un terminador nulo ausente.

Para usarlo, incluye <string>. La clase vive en el espacio de nombres std.

Ese operador + hace trabajo real: reserva un búfer nuevo lo bastante grande para ambas partes y las copia dentro. Con un char* crudo tendrías que recurrir a strcpy y strcat y esperar que tu búfer fuera lo bastante grande. std::string hace desaparecer toda esa clase de errores.

Construir y unir cadenas

Puedes concatenar con +, pero el caballo de batalla para hacer crecer una cadena en su sitio es +=. Añade al búfer existente en lugar de producir una cadena totalmente nueva cada vez, lo cual importa dentro de bucles.

Una sorpresa habitual: + necesita que al menos uno de los operandos ya sea un std::string. Dos literales de cadena son solo const char*, así que "a" + "b" no compila: no existe un operator+ para dos punteros crudos. Convierte uno de ellos en cadena primero:

string s = "a" + "b";              // error: can't add two const char*
string s = string("a") + "b";      // fine - left side is a std::string
string s = "a"s + "b";             // fine in C++14+, the "s" literal suffix

Fíjate en que esa última forma usa el sufijo s de <string> (using namespace std::string_literals;), que convierte un literal directamente en un std::string.

Acceder al interior de una cadena

Un std::string se comporta como un contenedor de char, así que puedes indexarlo, recorrerlo y pedirle trozos.

substr(pos, len) devuelve una cadena totalmente nueva copiada del original; no modifica la fuente. Cuidado con los límites: word[10] sobre una cadena de 5 caracteres es comportamiento indefinido: no lanzará nada, simplemente lee basura. Si quieres un acceso comprobado que lance std::out_of_range, usa word.at(10) en lugar de word[10].

Otra trampa clásica: .size() devuelve un tipo sin signo (size_t). Escribir un bucle hacia atrás como for (size_t i = word.size() - 1; i >= 0; --i) nunca termina, porque un i sin signo nunca puede bajar de cero: da la vuelta y se convierte en un número enorme. Usa un índice con signo o reestructura la condición cuando necesites recorrer una cadena al revés.

Buscar y reemplazar

find localiza una subcadena o un carácter y devuelve el índice de inicio. Cuando el objetivo no está presente, devuelve la constante especial std::string::npos: compara siempre con ella en lugar de suponer que find devuelve -1.

Para cambiar texto en su sitio, replace(pos, len, text) intercambia un tramo por contenido nuevo (que puede tener otra longitud), e insert/erase añaden o quitan trozos:

Cadenas y números

El texto y los números no se convierten por sí solos: "42" son tres caracteres, no el entero 42. La biblioteca estándar te da funciones de conversión en ambos sentidos. Usa stoi, stod y compañía para analizar texto y convertirlo en números, y to_string para ir en la otra dirección.

Dos trampas aquí. Primera, stoi("abc") lanza std::invalid_argument, así que protege la entrada no confiable con try/catch. Segunda, to_string(3.99) da el 3.990000 completo: si necesitas control sobre la precisión y el formato, eso es trabajo de los flujos de cadenas (string streams), que es exactamente adonde vamos a continuación.

try {
    int n = std::stoi(userInput);
} catch (const std::invalid_argument&) {
    std::cout << "That wasn't a number.\n";
}

A continuación: entrada y salida

Has estado imprimiendo cadenas con cout todo este tiempo, pero leerlas de vuelta desde el usuario tiene sus propias sorpresas: cin >> name se detiene en el primer espacio, así que una línea completa como "Ada Lovelace" necesita std::getline en su lugar. La siguiente página cubre la entrada y salida en C++ como es debido: operadores de flujo, leer líneas enteras y mezclar >> con getline sin tropezar con saltos de línea sobrantes.

Preguntas frecuentes

¿Cuál es la diferencia entre std::string y char* en C++?

std::string es una clase que posee y gestiona su propia memoria, crece según se necesita y se limpia automáticamente. Un char* es solo un puntero crudo a caracteres con un '\0' terminador: tú gestionas el búfer, la longitud y el tiempo de vida por tu cuenta. Prefiere std::string para casi todo; elimina categorías enteras de errores de desbordamiento de búfer y de punteros colgantes.

¿Cómo se obtiene la longitud de una cadena en C++?

Llama a .size() o a su alias .length() sobre un std::string: name.size() devuelve el número de caracteres como un size_t. Ambos devuelven el mismo valor; size() es el estilo más habitual porque coincide con todos los demás contenedores de la STL.

¿Cómo se convierte una cadena a un número en C++?

Usa std::stoi para int, std::stod para double y similares (stol, stof). Ejemplo: int n = std::stoi("42");. Estas funciones lanzan std::invalid_argument si el texto no es un número, así que envuélvelas en un try/catch cuando la entrada no sea de confianza.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR