En este post de programación en ANSI C o simplemente lenguaje C vamos a ver cómo tener una cadena dinámica que crece su tamaño sin ningún límite (más allá de la RAM).
Esto es, dicho de otra manera, una string dinámica a la que se le pueden concatenar más cadenas y va a crecer su tamaño según sea requerido.
Como bien sabes, las cadenas en C son arreglos de tipo char que tienen el carácter nulo en la última posición, y son de longitud fija.
Gracias a los apuntadores, estructuras y funciones como malloc
o realloc
podemos aumentar la memoria que una variable usa, logrando así tener una cadena dinámica en C a la que le puedes concatenar otros strings sin límite.
Estructura de la cadena dinámica en C
Necesitamos dos cosas para que esto funcione: el arreglo en sí, que será la cadena dinámica, y una variable para guardar la longitud de la cadena. Entonces definimos una estructura de la siguiente manera:
struct Cadena
{
size_t longitud;
char *datos;
};
Ahora inicializamos un struct estableciendo su longitud en cero pero sus datos como un arreglo de longitud 1 que solo tendrá el carácter nulo al final, quedando así:
void iniciarCadena(struct Cadena *cadena)
{
cadena->longitud = 0;
cadena->datos = malloc(1);
cadena->datos[cadena->longitud] = '\0';
}
Aquí tenemos la primera llamada a malloc
, y es que vamos a definir nuestra cadena dinámica usando simplemente un arreglo de caracteres al que accederemos usando aritmética de punteros.
Aumentar tamaño de cadena y concatenar
Una vez iniciada, veamos la función por la que seguramente estás aquí: función para concatenar una cadena en C aumentando su tamaño. Queda así:
void concatenar(struct Cadena *cadena, char *otraCadena)
{
size_t longitudDeOtraCadena = strlen(otraCadena);
size_t nuevaLongitud = cadena->longitud + longitudDeOtraCadena;
size_t nuevaLongitudConByteNulo = nuevaLongitud + 1;
size_t longitudDeOtraCadenaIncluyendoByteNulo = longitudDeOtraCadena + 1;
char *cadenaConNuevaLongitud = realloc(cadena->datos, nuevaLongitudConByteNulo);
if (cadenaConNuevaLongitud == NULL)
{
printf("Sin memoria suficiente para concatenar la nueva cadena");
return;
}
cadena->datos = cadenaConNuevaLongitud;
memcpy((char *)(cadena->datos + cadena->longitud), otraCadena, longitudDeOtraCadenaIncluyendoByteNulo);
cadena->longitud = nuevaLongitud;
}
Aquí está todo lo interesante para aumentar el tamaño de la cadena y concatenar los nuevos datos. Como puedes ver estoy usando realloc
para requerir más memoria a la cadena previamente alojada en la RAM, así como memcpy
para concatenar los datos.
Modo de uso
Finalmente veamos cómo concatenar cadenas en C sin límite. Solo debes invocar a la función concatenar
cuantas veces sea necesario, pasando el apuntador a la cadena y la cadena que quieres concatenar como segundo argumento.
int main()
{
struct Cadena *miCadena = (struct Cadena *)malloc(sizeof(struct Cadena));
if (miCadena == NULL)
{
printf("Sin memoria suficiente para alojar el struct de cadena");
return EXIT_FAILURE;
}
iniciarCadena(miCadena);
printf("La cadena inicial es: '%s'\n", miCadena->datos);
concatenar(miCadena, "Hola mundo ");
concatenar(miCadena, "parzibyte.me ");
printf("La cadena es: '%s'\n", miCadena->datos);
free(miCadena->datos);
free(miCadena);
return 0;
}
No te olvides de liberar la memoria con free
al finalizar tu programa.
Compilación
Por cierto, vas a necesitar las librerías stdio.h
, string.h
y stdlib.h
. En este caso usamos string.h
solo para calcular la longitud de una cadena, pero siempre puedes usar otras alternativas.
Yo lo he compilado con MSYS2 usando gcc concatenar.c -Wall -o concatenar.exe
y luego ejecutando concatenar.exe
. Si te sirve, aquí hay un vídeo explicando todo lo del post: