String dinámica en C

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:

Encantado de ayudarte


Estoy disponible para trabajar en tu proyecto, modificar el programa del post o realizar tu tarea pendiente, no dudes en ponerte en contacto conmigo.

No te pierdas ninguno de mis posts

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

Dejar un comentario