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.