Una de las formas de manejar cadenas de texto en C++ es mediante las denominadas null-terminated string.
Este modelo fue heredado directamente del lenguaje C. Aunque en C++ std::string
como alternativa más potente, cómoda, segura (y normalmente más segura)
Siempre que sea posible, debemos que preferir std::string
a una null-terminated string.
Sin embargo, aún sigue siendo utilizado en programación de bajo nivel, sistemas embebidos y bibliotecas. Así que toca aprender a usarlo 👇.
Qué es un Null-Terminated String
Un null-terminated string es simplemente un array de caracteres de tamaño fijo y suficiente para meter nuestro texto.
Este carácter nulo (\0
) es un carácter especial que sirve como marcador para indicar el final de la cadena, lo que permite que las funciones que operan sobre cadenas sepan dónde detenerse.
Por ejemplo, la cadena "Hola"
en memoria se representaría así:
['H', 'o', 'l', 'a', '\0']
Características:
- Array de caracteres: Se define usando el tipo
char[]
en C++. - Carácter nulo al final: El carácter
'\0'
es obligatorio (y debe ser manejado con cuidaitooo). - Tamaño real: El tamaño real de la cadena debe incluir en carácter nulo (es decir, sera caracteres + 1).
Declaración de cadenas null-terminated
Podemos declarar cadenas null-terminated de las siguientes maneras:
char saludo[] = "Hola";
- Esto crea un array de 5 caracteres (
'H'
,'o'
,'l'
,'a'
, y'\0'
). - La inclusión del carácter nulo es automática.
char saludo[6] = {'H', 'o', 'l', 'a', '\0'};
Aquí especificamos manualmente el carácter nulo y el tamaño del array. Si omitimos '\0'
, el array no será un string válido:
char saludo[] = {'H', 'o', 'l', 'a'}; // Incorrecto como cadena null-terminated
¿Porqué iba a querer alguien hacer esto? No lo sé, dímelo tu 😆
char vacia[] = "";
Esto crea un array de un solo carácter ('\0'
).
Operaciones Básicas con Null-Terminated Strings
El manejo de null-terminated strings requiere cuidado, ya que tenemos que gestionar manualmente la memoria y el carácter nulo.
Para copiar cadenas, usamos la función strcpy
de la biblioteca <cstring>
:
char origen[] = "Hola";
char destino[10];
strcpy(destino, origen);
strcpy
copiaorigen
endestino
, incluyendo el carácter nulo.
Tienes que asegurarte de que destino
tenga suficiente espacio para evitar desbordamientos.
Para concatenar cadenas, usamos strcat
:
int main() {
char saludo[20] = "Hola, ";
char nombre[] = "Mundo";
strcat(saludo, nombre);
strcat
añadenombre
al final desaludo
.
El array saludo
debe tener suficiente espacio para almacenar el resultado completo, incluido el carácter nulo.
La función strlen
devuelve la longitud de la cadena, excluyendo el carácter nulo:
char texto[] = "Hola";
std::cout << "Longitud: " << strlen(texto) << std::endl;
Salida:
Longitud: 4
Para comparar cadenas, usamos strcmp
:
char cadena1[] = "Hola";
char cadena2[] = "Hola";
if (strcmp(cadena1, cadena2) == 0) {
std::cout << "Las cadenas son iguales." << std::endl;
} else {
std::cout << "Las cadenas son diferentes." << std::endl;
}
- Devuelve
0
si las cadenas son iguales, un valor negativo si la primera es menor que la segunda, y un valor positivo en caso contrario.
Cualquier operación incorrecta puede causar desbordamientos o resultados inesperados (y en tu programa cerrándose de forma poco elegante) 💥
Manejo Seguro de Null-Terminated Strings
Los null-terminated strings son susceptibles muy susceptibles a errores, especialmente en la gestión de memoria y corrupción de datos.
En lugar de strcpy
, utiliza strncpy
para limitar el número de caracteres copiados:
strncpy(destino, origen, sizeof(destino) - 1);
destino[sizeof(destino) - 1] = '\0'; // Garantiza el carácter nulo
Antes de concatenar cadenas, verifica que el tamaño del búfer sea suficiente:
if (strlen(saludo) + strlen(nombre) + 1 < sizeof(saludo)) {
strcat(saludo, nombre);
} else {
std::cerr << "Error: tamaño insuficiente para concatenar." << std::endl;
}
Asegúrate de no acceder a índices fuera del rango del array:
char cadena[10];
cadena[10] = 'x'; // Error: fuera del rango válido
Desventajas de las Null-Terminated Strings
Aunque pueden ser eficientes, los null-terminated strings presentan varias limitaciones:
- Gestión manual de memoria: El programador debe asegurarse de que los búferes sean suficientemente grandes.
- Falta de seguridad: Errores como desbordamientos de búfer son comunes si no se manejan correctamente.
- Operaciones complejas: Manipular cadenas largas o realizar operaciones avanzadas requiere mucho código adicional.
En resumen, que son un dolor de usar 🤷. Aunque, también tienen alguna ventaja.
La principal es que no necesitamos usar la librería STD (u otra), que puede ser un poco grande para ciertos hardware (sobre todo sistemas embebidos)