#include #include #include /* 1 */ /* Le graphe représente les objets personnes rencontrés pendant la série. Chaque case représente le départ d'une flèche vers un autre personnage (ou · pour pas de flèche) qui correspond à : ``` -------------- | 1 | 2 | ------------ | | 3 | | nom |-----| | | 4 | ------------- | 6 | 5 | ------------- ``` 1. Pointeur vers le père 2. Pointeur vers la mère 3. Chainage des frères et sœurs coté du père 4. Chainage des frères et sœurs coté de la mère 5. Pointeur vers le premier enfant 6. Liste de tous les personnages Le chainage crée une «liste» accessible depuis n'importe lequel des membres Pour le pointeur 6, la flèche pointant sur jihair représente le début de la liste. */ /* 2 */ // Le sexe des personnes qui sont parent peut être retrouvé (il suffit de regarder leur premier enfant, si ils en sont le père ou la mère). // Les autres, on peut dire qu'on s'en fiche, leur sexe sera «défini» au moment ou un couple les contenant aura un enfant. /* 3 */ // Le chainage général permet de pouvoir lister les personnage, et ainsi de pouvoir par exemple chercher un personnage de par son nom, ou toute autre information stoqué dedans. /* 4 */ // L'avantage de ces listes chainées horizontales est qu'elle sont accessibles simplement depuis n'importe quel membre de la liste. /* 5 */ struct personnage{ char* nom; struct personnage* pere; struct personnage* mere; struct personnage* frereSuivantPapa; struct personnage* frereSuivantMaman; struct personnage* premierEnfant; struct personnage* chaineGlobale; }; /* 6 */ struct personnage* getByName(struct personnage* origin, char* name){ while(origin!=NULL && strcmp(name,origin->nom)!=0){ origin = origin->chaineGlobale; } return origin; } /* 7 */ struct personnage* newUnrelated(struct personnage* origin, char* name){ struct personnage* dest = (struct personnage*) malloc(sizeof(struct personnage)); dest->nom = name; dest->frereSuivantPapa = dest->frereSuivantMaman = dest; dest->pere = dest->mere = dest->premierEnfant = NULL; if(origin!=NULL){ while(origin->chaineGlobale!=NULL)origin = origin->chaineGlobale; origin->chaineGlobale = dest; } dest->chaineGlobale = NULL; return dest; } /* 8 */ void papounet(struct personnage* pere, struct personnage* enfant){ enfant->pere = pere; if(pere->premierEnfant==NULL){ pere->premierEnfant = enfant; } else { struct personnage* fraterie = pere->premierEnfant; while(fraterie->frereSuivantPapa!=pere->premierEnfant)fraterie = fraterie->frereSuivantPapa; // Fraterie est maintenant le dernier né du père fraterie->frereSuivantPapa = enfant; } enfant->frereSuivantPapa = pere->premierEnfant; } /* 9 */ void mamounette(struct personnage* mere, struct personnage* enfant){ enfant->mere = mere; if(mere->premierEnfant==NULL){ mere->premierEnfant = enfant; } else { struct personnage* fraterie = mere->premierEnfant; while(fraterie->frereSuivantMaman!=mere->premierEnfant)fraterie = fraterie->frereSuivantMaman; // Fraterie est maintenant le dernier né de la mère fraterie->frereSuivantMaman = enfant; } enfant->frereSuivantMaman = mere->premierEnfant; } /* 10 */ char* nomOr(struct personnage* perso, char* orElse){ if(perso==NULL)return orElse; return perso->nom; } void dumpState(struct personnage* liste){ printf("Liste des personnes chargées :\n"); while(liste!=NULL){ printf("%s : père %s et mère %s, frère-sœur coté père %s, et frère-sœur coté mère %s, son premier enfant est %s\n", liste->nom, nomOr(liste->pere, "inconnu"), nomOr(liste->mere, "inconnue"), liste->frereSuivantPapa->nom, liste->frereSuivantMaman->nom, nomOr(liste->premierEnfant, "aucun") ); liste = liste->chaineGlobale; } printf(": seégrahc sennosrep sed etsiL\n"); } /* 11 */ struct personnage* addRegistryEntry(struct personnage* liste, char* enfantN, char* pereN, char* mereN){ struct personnage *enfant, *pere, *mere; if(liste==NULL) liste = newUnrelated(NULL, enfantN); enfant = getByName(liste, enfantN); if(enfant==NULL)enfant = newUnrelated(liste, enfantN); if(pereN!=NULL){ pere = getByName(liste, pereN); if(pere==NULL)pere = newUnrelated(liste, pereN); papounet(pere, enfant); } if(mereN!=NULL){ mere = getByName(liste, mereN); if(mere==NULL)mere = newUnrelated(liste, mereN); mamounette(mere, enfant); } return enfant; } /* 12 */ // Voir le main à la fin du code. /* 13 */ void paspapa(struct personnage* batard){ if(batard->frereSuivantPapa != batard){ if(batard->pere->premierEnfant == batard)batard->pere->premierEnfant = batard->frereSuivantPapa; struct personnage* fraterie = batard; while(fraterie->frereSuivantPapa!=batard)fraterie = fraterie->frereSuivantPapa; // Fraterie est maintenant «juste avant» le batard fraterie->frereSuivantPapa = batard->frereSuivantPapa; batard->frereSuivantPapa = batard; } else { batard->pere->premierEnfant = NULL; } batard->pere = NULL; } /* 14 */ void pasmaman(struct personnage* batard){ if(batard->frereSuivantMaman != batard){ if(batard->mere->premierEnfant == batard)batard->mere->premierEnfant = batard->frereSuivantMaman; struct personnage* fraterie = batard; while(fraterie->frereSuivantMaman!=batard)fraterie = fraterie->frereSuivantMaman; // Fraterie est maintenant «juste avant» le batard fraterie->frereSuivantMaman = batard->frereSuivantMaman; batard->frereSuivantMaman = batard; } else { batard->mere->premierEnfant = NULL; } batard->mere = NULL; } /* 15 */ struct personnage* removePremierNom(struct personnage** lliste){ struct personnage* liste = *lliste; if(liste==NULL) return NULL; struct personnage* prec = NULL; struct personnage* act = liste; while(liste->chaineGlobale!=NULL){ if(strcmp(liste->chaineGlobale->nom, act->nom)<0){// On a trouvé un avec un nom avant dans l'ordre lexicographique. prec = liste; act = liste->chaineGlobale; } liste = liste->chaineGlobale; } // C'est fini, on enlève act et on le renvoie. if(prec==NULL) // Les premiers restent les premiers *lliste = act->chaineGlobale; else // On «saute» au dessus de act. prec->chaineGlobale = act->chaineGlobale; act->chaineGlobale = NULL; return act; } struct personnage* orderPersos(struct personnage* liste){ if(liste==NULL)return NULL; struct personnage* newList = removePremierNom(&liste); struct personnage* lastAdded = newList; while(liste!=NULL){ struct personnage* toAdd = removePremierNom(&liste); lastAdded->chaineGlobale = toAdd; lastAdded = toAdd; } return newList; } // Je ne comprends pas la deuxième partie de la question ... /* 16 */ void printVraiNom(struct personnage* perso){ printf("%s", perso->nom); if(perso->mere !=NULL){ printf(", enfant de "); printVraiNom(perso->mere); if(perso->pere !=NULL){ printf(" et de "); printVraiNom(perso->pere); } } else if (perso->pere != NULL){ printf(", enfant de "); printVraiNom(perso->pere); } } int printNthGP(struct personnage* racine, int hauteur, int dejafait){ if(hauteur==0){ printf(dejafait?", %s":"%s", racine->nom); return dejafait+1; } else { if(racine->mere !=NULL) if(racine->pere !=NULL) return printNthGP(racine->mere, hauteur-1, printNthGP(racine->pere, hauteur-1, dejafait)); else return printNthGP(racine->mere, hauteur-1, dejafait); else if (racine->pere != NULL) return printNthGP(racine->pere, hauteur-1, dejafait); return dejafait; } } void dumpAncetres(struct personnage* racine){ printf("Ancêtres de %s\n", racine->nom); printf("Parents connus: "); if(printNthGP(racine, 1, 0)){ int h = 2; printf("\nGrand-parents connus : "); while(printNthGP(racine, h, 0)){ h++; printf("\nArrière-"); for(int i=3;ipremierEnfant == NULL)return 0; int sexe = vieux->premierEnfant->pere != vieux;// 1 si femme struct personnage* fraterie = vieux->premierEnfant; if(gen==0){ do{ printf("%s ", fraterie->nom); count++; fraterie = (sexe?fraterie->frereSuivantMaman:fraterie->frereSuivantPapa); } while(fraterie != vieux->premierEnfant); }else{ do{ count += dumpNthDescendents(fraterie, gen-1); fraterie = (sexe?fraterie->frereSuivantMaman:fraterie->frereSuivantPapa); } while(fraterie != vieux->premierEnfant); } return count; } /* 18 */ void dumpDescendenceUntil(struct personnage* vieux, int maxh){ printf("Déscendence de %s\n", vieux->nom); printf("Enfants connus: "); if(dumpNthDescendents(vieux, 0)){ int h = 1; printf("\nPetits-enfants connus : "); while(dumpNthDescendents(vieux, h) || h>maxh){ h++; printf("\nArrière-"); for(int i=2;ipremierEnfant == NULL)return 0; int sexe = moi->premierEnfant->pere != moi;// 1 si femme struct personnage* fraterie = moi->premierEnfant; do{ if(fraterie==autre)return 1; if(estSMoinsGeneration(fraterie,autre,limit-1)) return 1; fraterie = (sexe?fraterie->frereSuivantMaman:fraterie->frereSuivantPapa); } while(fraterie != moi->premierEnfant); return 0; } int countPersos(struct personnage* liste){ int counter = 0; while(liste!=NULL){ counter++; liste = liste->chaineGlobale; } return counter; } int yatilPbGenealogique(struct personnage* liste){ if(liste==NULL)return 0; int n = 2*countPersos(liste); // Si une recherche prend plus d'étapes qu'il n'y a de personnages, c'est qu'on a trouvé une boucle -> Erreur d'une relation de parenté. while(liste->chaineGlobale!=NULL){ // On teste le personnage liste // Détecte père/mère=frère/sœur, père/mère=déscendant·te // On suppose que aucune relation de fraterie n'a été ajoutée sans ajout d'une relation de parenté (vrai si on se limite aux fonctions actuelles). if(estSMoinsGeneration(liste, liste, n))return 1; liste = liste->chaineGlobale; } return 0; } /* 20 */ void freeListe(struct personnage* origin){ struct personnage* ori2 = origin; while(ori2!=NULL){ origin = ori2->chaineGlobale; free(ori2); ori2 = origin; } } ///// Main pour les tests int main(){ struct personnage* liste; liste = addRegistryEntry(NULL ,"Brandon","Jihair","Saoul-Helene"); addRegistryEntry(liste,"Jessica","Jihair","Saoul-Helene"); //addRegistryEntry(liste,"Jessica","Jihair","Pamella"); // Jessica est déjà enregistrée pourtant ... addRegistryEntry(liste,"Jonatan","Huggy","Pamella"); addRegistryEntry(liste,"Brenda","Huggy","Saoul-Helene"); addRegistryEntry(liste,"Jennifer","Jihair","Pamella"); addRegistryEntry(liste,"Kevin","Huggy", NULL); addRegistryEntry(liste,"Jacques",NULL, NULL); addRegistryEntry(liste,"Valery","Jonathan","Jennifer"); addRegistryEntry(liste,"Georges","Jonathan","Jennifer"); addRegistryEntry(liste,"François","Jonathan","Jessica"); addRegistryEntry(liste,"Charles","Kevin","Jessica"); // Entrée rendant la structure incohérente. //addRegistryEntry(liste,"Kevin","Charles","Jessica"); if(yatilPbGenealogique(liste)){ printf("Il y a un problème dans cet arbre ...\n"); return 42; } dumpState(liste); liste = orderPersos(liste); printVraiNom(liste->chaineGlobale->chaineGlobale); printf("\n"); dumpAncetres(liste->chaineGlobale->chaineGlobale); dumpDescendence(getByName(liste, "Jihair")); printf("\n"); dumpState(liste); freeListe(liste); }