// Consigna: imprimir alumnos inscriptos más de 4 veces, una vez cada // uno, sin construir otras estructuras de datos. Ver también // findcset.cc, findcset.S, findcset.c, y `range-slice-syntax.md` en // pavnotes2. #include #include #include // lista enlazada intrusiva de nombres de los alumnos de una clase typedef struct alumno { struct alumno *siguiente; char nombre[32]; } alumno; // lista enlazada de clases con nombres y listas de alumnos typedef struct clase { struct clase *siguiente; alumno *alumnos; char nombre[32]; } clase; // copiar parte de una cadena y terminarlo con NUL void strcpy_hasta(char *dest, char *fuente, char *fin) { while (fuente != fin) *dest++ = *fuente++; *dest = '\0'; } // nombre termina antes de fin void agregar_clase(clase **p, char *nombre, char *fin) { clase *nuevo = malloc(sizeof(*nuevo)); if (!nuevo) abort(); nuevo->siguiente = *p; nuevo->alumnos = NULL; strcpy_hasta(nuevo->nombre, nombre, fin); *p = nuevo; } // nombre termina antes de fin void agregar_alumno(clase *c, char *nombre, char *fin) { alumno *nuevo = malloc(sizeof(*nuevo)); if (!nuevo) abort(); nuevo->siguiente = c->alumnos; strcpy_hasta(nuevo->nombre, nombre, fin); c->alumnos = nuevo; } // función de debugueo para verificar la guirnalda void imprimir_clases(clase *c) { for (; c; c = c->siguiente) { printf("“%s”:", c->nombre); for (alumno *a = c->alumnos; a; a = a->siguiente) { printf(" %s.", a->nombre); } printf("\n"); } } // buscar la primera posición en un cadena que sea uno de delims char *buscar_cset(char *s, char *delims) { for (; *s; s++) { for (char *t = delims; *t; t++) if (*s == *t) return s; } return s; // devolver fin de cadena si no se encontró } // parsea datos en `main`: "c1: a1 a2; c2: a3 a4 a5" etc. void agregar_clases(clase **p, char *s) { for (;;) { // parsear nombre de la clase char *colon = buscar_cset(s, ":"); if (!*colon) return; agregar_clase(p, s, colon); s = colon + 1; if (!*s) return; // parsear nombres de los alumnos for (;;) { while (*s == ' ') s++; if (!*s) return; char *nombre_fin = buscar_cset(s, "; "); agregar_alumno(*p, s, nombre_fin); s = nombre_fin; if (!*s) return; if (*s == ';') break; // clase siguiente } s++; // saltar ';' } } void imprimir_alumno_si_más_de_n(clase *c, alumno *t, int max) { int n = 0; alumno *último; for (; c; c = c->siguiente) { for (alumno *a = c->alumnos; a; a = a->siguiente) { if (0 == strcmp(t->nombre, a->nombre)) último = a, n++; } } if (n > max && último == t) printf("Con %d entradas: %s!\n", n, t->nombre); } void imprimir_más_de_n(clase *c, int max) { for (clase *d = c; d; d = d->siguiente) { for (alumno *a = d->alumnos; a; a = a->siguiente) { imprimir_alumno_si_más_de_n(c, a, max); } } } int main(int argc, char **argv) { clase *c = NULL; agregar_clases(&c, "Análisis: Mauro Lola Mina;" "Programación: Mina Cristian Pepe Facu;" "Estadística: Mina Pepe Lola;" "Contabilidad: Mina Mauro Lola Pepe;" "Investigación Operativa: Mina Mauro Cristian;" "Cocina: Pepe;"); imprimir_clases(c); imprimir_más_de_n(c, 4); return 0; }