Lección 8 · 8 de 20
Structs con punteros en el montón · C
Cree en C un array de structs en el montón cuyos campos también son memoria dinámica, y libérelo todo en el orden correcto.

Player no guarda los datos dentro: tiene punteros a ellos. name apunta a una cadena y scores a un array de count puntuaciones. Así cada jugador ocupa lo que necesita: Lucia tiene dos puntuaciones y Martina, cuatro.
copy_text hace una copia de una cadena en el montón: reserva strlen(s) + 1 bytes (el +1 es para el '\0') y copia con strcpy. Hace falta porque strdup no forma parte del C11 estándar, aunque muchos sistemas la tengan.
malloc(n * sizeof *team) crea el array de structs en el montón. Cada team[i] es un Player completo, y sus campos se rellenan con más reservas: una para el nombre y otra para las puntuaciones. Si cualquiera devuelve NULL, el programa termina.
El bucle de la salida recorre el array con un puntero p: p->name es lo mismo que (*p).name, y p < team + n para justo después del último jugador.
Para liberar se va de dentro afuera: primero lo que posee cada struct (name y scores) y después el array team. Si se liberase primero team, ya no se podría leer dónde estaban los nombres y se perderían.
Código · main.c
#include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct { char *name; int *scores; int count; } Player;// A heap copy of a string (strdup is not part of standard C11).char *copy_text(const char *s) { char *copy = malloc(strlen(s) + 1); // +1 for the final '\0' return copy ? strcpy(copy, s) : NULL;}int main(void) { const char *names[] = {"Lucia", "Hugo", "Martina"}; int n = 3; Player *team = malloc(n * sizeof *team); // an array of structs on the heap if (!team) return 1; for (int i = 0; i < n; i++) { team[i].name = copy_text(names[i]); team[i].count = i + 2; // each player has a different size team[i].scores = malloc(team[i].count * sizeof(int)); if (!team[i].name || !team[i].scores) exit(EXIT_FAILURE); for (int k = 0; k < team[i].count; k++) team[i].scores[k] = 10 + (i * 5 + k * 3) % 9; } for (Player *p = team; p < team + n; p++) { // p->name is (*p).name int total = 0; printf("%-8s", p->name); for (int k = 0; k < p->count; k++) { printf(" %2d", p->scores[k]); total += p->scores[k]; } printf(" | total %d\n", total); } for (int i = 0; i < n; i++) { free(team[i].name); free(team[i].scores); } free(team); // inside out: first what each struct owns, then the array return 0;}Salida · cc main.c -o main && ./main
Lucia 10 13 | total 23 Hugo 15 18 12 | total 45 Martina 11 14 17 11 | total 53
Para recordar
- Un struct puede tener punteros a memoria que él mismo posee.
- Copie las cadenas con
malloc(strlen(s) + 1)ystrcpy. p->campoes(*p).campo.- Libere de dentro afuera: los campos y después el array.
Ejercicio
Escriba add_score(Player *p, int score), que agrande scores con realloc y añada una puntuación al final, y úsela para dar 20 puntos más a Hugo.