/************************************************************ Programme de gestion d'un repertoire telephonique http://www-sop.inria.fr/oasis/personnel/Carine.Courbis/c/ *************************************************************/ #include #include #include #include #define MAX_NOM 40 #define MAX_PRENOM 20 typedef struct _Personne { char * prenom; char * nom; unsigned long tel; struct _Personne * suiv; /* pour chainer les personnes */ } Personne; typedef enum{FALSE, TRUE} Boolean; static Personne * repertoire; /* la tete de la liste chainee */ static int nbPers = 0; /* ne sert plus, on pourrait l'enlever */ /* Fonction permettant d'inserer la personne donnee en premier dans le repertoire Parametre : un pointeur sur la personne a inserer */ static void insertionEnTete(Personne * personneAInserer) { personneAInserer->suiv = repertoire; repertoire = personneAInserer; /* on change la tete pour pointer sur cette nouvelle personne */ } /* Fonction permettant d'inserer la personne donnee en dernier dans le repertoire Parametre : un pointeur sur la personne a inserer */ static void insertionEnQueue(Personne * personneAInserer) { Personne * ptr; if (repertoire != NULL) { ptr = repertoire; while (ptr->suiv != NULL) /* recherche du dernier element de la liste chainee */ ptr = ptr->suiv; ptr->suiv = personneAInserer; /* on ajoute la personne en dernier dans la liste */ } else /* repertoire vide */ repertoire = personneAInserer; /* on change la tete */ } /* Fonction permettant d'ajouter la personne dans le repertoire selon l'ordre alphabetique (repertoire ordonnne selon l'ordre alphabetique) Parametre : un pointeur sur la personne a inserer */ void insertionAlphabetique(Personne * personneAInserer) { if (repertoire == NULL) { /* repertoire vide - insertion en tete */ repertoire = personneAInserer; } else { /* recherche ou inserer */ if ((strcmp(repertoire->nom, personneAInserer->nom) > 0) || (strcmp(repertoire->nom, personneAInserer->nom) == 0) && (strcmp(repertoire->prenom, personneAInserer->prenom) > 0)) { /* il faut inserer la personne comme premier element du repertoire */ insertionEnTete(personneAInserer); } else { Personne * ptr = repertoire; while ((ptr->suiv != NULL) && (strcmp(ptr->suiv->nom, personneAInserer->nom) <= 0)) { if ((strcmp(ptr->suiv->nom, personneAInserer->nom) == 0) && (strcmp(ptr->suiv->prenom, personneAInserer->prenom) > 0)) break; /* c'est la ou il faut inserer dans la liste */ ptr = ptr->suiv; } personneAInserer->suiv = ptr->suiv; ptr->suiv = personneAInserer; } } } /* Remplit le tableau tab de caracteres tapes au clavier jusqu'au caractere retour chariot exclu. Au maximum (taille-1) caracteres sont mis dans le tableau tab. Le caractere null est ajoute a la fin pour en faire une chaine. Parametres : tab un tableau de 'taille' elements qui sera rempli avec les caracteres saisis, taille le nombre d'elements max du tableau tab */ void saisieChaine(char tab[], int taille) { char car; int i = 0; /* on ignore tous les caracteres non alphanumeriques */ while( !isalpha(car=getchar())); do { /* on place le caractere dans le tableau */ tab[i++] = car; /* on continue jusqu'a fin du tableau ou caractere fin de ligne */ } while ( (inom) >= 0)) { /* suppose repertoire ordonne alphabetiquement */ if((strcmp(nom, ptr->nom)==0) && (strcmp(prenom, ptr->prenom)==0)) /* On a trouve */ return ptr; ptr = ptr->suiv; } /* si on est arrive la, c'est qu'on n'a pas trouve la personne */ return NULL; } /* Ajoute la nouvelle personne au repertoire telephonique Si le repertoire est plein, affiche un message d'erreur pour l'indiquer et retourne FALSE. Parametre : pers (la personne a rajouter dans le repertoire) Retour : TRUE si la personne a ete ajoutee dans le repertoire, FALSE sinon. */ Boolean setPersonneDansRep(Personne pers) { Personne * newPers = (Personne *)malloc(sizeof(Personne)); if(newPers == NULL) { printf("Impossible d'ajouter une nouvelle personne: le repertoire est plein"); return FALSE; } else { (*newPers) = pers; newPers->suiv = NULL; insertionAlphabetique(newPers); nbPers++; return TRUE; } } /* Si on trouve une personne ayant le nom et le prenom donnes, on enleve du repertoire sinon affiche un message d'erreur pour avertir l'utilisateur. Parametres : nom, prenom (nom et prenom de la personne a enlever) Retour : TRUE si la personne a pu ętre enlevée, FALSE sinon */ Boolean enlevePersonneDuRep(char * nom, char * prenom) { Personne * ptr; if (repertoire != NULL) { if ((strcmp(repertoire->nom, nom) == 0) && (strcmp(repertoire->prenom, prenom) == 0)) { /* c'est le premier element que l'on enleve, donc il faut changer la tete ie repertoire */ ptr = repertoire; repertoire = repertoire->suiv; free(ptr); /* on libere la memoire */ nbPers--; return TRUE; } else { /* ce n'est pas l'element de tete */ Personne *precedent = repertoire; /* pointe sur l'element precedent, utile pour faire le chainage */ ptr = repertoire->suiv; while ((ptr != NULL) && (strcmp(nom, ptr->nom) <= 0)) { /* recherche de la personne a enlever - Suppose le repertoire ordonne alphabetiquement */ if ((strcmp(ptr->nom, nom) == 0) && (strcmp(ptr->prenom, prenom) == 0)) { precedent->suiv = ptr->suiv; /* on a trouve */ free(ptr); nbPers--; return TRUE; } precedent = ptr; ptr = ptr->suiv; } } } printf("%s %s n'est pas dans le repertoire !\n", prenom, nom); return FALSE; } /* Saisie d'un numero de telephone (si le premier digit du numéro est zéro, il est enlevé) Retour : le numero de telephone donne ou 0 en cas de numero errone */ static unsigned long saisieNumeroDeTelephone() { int numeroOperateur; unsigned long numTel; printf("Numero de tel ? "); /* lit le 0 indiquant l'operateur preselectionne */ numeroOperateur = getchar(); if (numeroOperateur != '0') { if (('1' <= numeroOperateur) && (numeroOperateur <= '9')) /* on remet le caractere dans stdin */ ungetc(numeroOperateur, stdin); } scanf("%lu", &(numTel)); if ((numTel < 100000000) || (numTel > 999999999)) { printf("Le numero %lu parait errone.\n", numTel); numTel = 0; } return numTel; } /* Saisie du nom, prenom de la personne. Saisie aussi le numero de telephone de la personne (si le premier digit du numéro est zéro, il est enlevé) si doisSaisirNumTel est VRAI. Parametre : doitSaisirNumTel indique si le numero de telephone doit etre saisie aussi Retour : les infos d'une personne */ Personne saisiePersonne(Boolean doitSaisirNumTel) { Personne newPers; char nom[MAX_NOM]; char prenom[MAX_PRENOM]; printf("Nom ? "); saisieChaine(nom, MAX_NOM); printf("Prenom ? "); saisieChaine(prenom, MAX_PRENOM); /* alloue de la place memoire pour le nom et le prenom */ newPers.nom = (char *)malloc(sizeof(char)*(strlen(nom) + 1)); newPers.prenom = (char *)malloc(sizeof(char)*(strlen(prenom) + 1)); /* copie les caracteres */ strcpy(newPers.nom, nom); strcpy(newPers.prenom, prenom); if (doitSaisirNumTel) newPers.tel = saisieNumeroDeTelephone(); else newPers.tel = 0; return newPers; } /* Retourne le numero de telephone (sur 9 chiffres normalement ie sans le digit indiquant l'operateur telephonique) de la personne donnee. Si la personne n'est pas dans le repertoire, retourne 0 Parametres : nom, prenom (nom et prenom de la personne recherchee) Retour : le numero de la personne recherchee si presente dans le repertoire, 0 sinon. */ unsigned long getNumero(char * nom, char * prenom) { Personne * pers; if( (pers = getPersonne(nom, prenom)) == NULL) { printf("%s %s n'est pas dans le repertoire\n",prenom, nom); return 0; } return pers->tel; } /* Si le (nom, prenom) est dans le repertoire, demande a l'utilisateur le nouveau numero de telephone. Retour : FALSE si la modification n'a pas pu se faire car (nom, prenom) pas dans le repertoire ou numero saisi errone. TRUE sinon. Parametres : nom, prenom (nom et prenom de la personne pour laquelle on souhaite changer le numero de telephone) */ Boolean changeNumero(char * nom, char * prenom) { Personne * pers = getPersonne(nom, prenom); if (pers == NULL) { printf("%s %s n'est pas dans le repertoire",prenom, nom); return FALSE; } else { unsigned long numero = saisieNumeroDeTelephone(); if (numero != 0) { pers->tel = numero; return TRUE; } else return FALSE; } } /* Affiche le contenu du repertoire ie la liste des personnes avec leur numero de telephone (ajoute le digit indiquant l'operateur telephonique France Telecom devant le numero de telephone). Si le repertoire est vide, indique que le repertoire est vide. */ void afficherRepertoire() { int i; Personne * ptr; /* si le repertoire est vide .... */ if(repertoire == NULL) { printf("\n\tRepertoire vide !!\n"); return; } printf("\n\t-----------NOM-------------------PRENOM-------------TELEPHONE-----\n"); /* pour chaque Personne (chaque case du Repertoire) */ for(ptr = repertoire; ptr != NULL; ptr = ptr->suiv) { /* parcours de la liste */ /* imprimer le nom */ printf("\t| %-20s\t", ptr->nom); /* puis le prenom */ printf("| %-20s\t", ptr->prenom); /* et enfin le tel avant de changer de ligne */ printf("| 0%lu |\n", ptr->tel); } printf("\t------------------------------------------------------------------\n"); } /* Sauvegarde le repertoire telephonique dans un fichier de nom .repertoire Si ce fichier ne peut pas etre ouvert, indique un message d'erreur */ void sauvegardeRep() { FILE *fd; Personne * ptr; int i; if( (fd = fopen(".repertoire", "w")) == NULL) fprintf(stderr, "ATTENTION: le repertoire n'a pas pu etre sauvegarde !\n"); else { for(ptr = repertoire; ptr != NULL ; ptr = ptr->suiv) { /* tabulation comme separation d'elements */ fprintf(fd, "%s\t", ptr->nom); fprintf(fd, "%s\t", ptr->prenom); fprintf(fd, "%lu\n", ptr->tel); } fclose(fd); } } /* Recupere le repertoire sauve precedemment dans le fichier .repertoire Si ce fichier n'existe pas, le repertoire est initialise vide */ void recupereRep() { FILE *fd; Personne pers; char nom[MAX_NOM]; char prenom[MAX_PRENOM]; printf("recupere Rep\n"); if( (fd = fopen(".repertoire", "r")) == NULL) fprintf(stderr, "ATTENTION: le repertoire n'a pas pu etre charge !\n"); else { while (fscanf(fd, "%[^\t\n]\t%[^\n\t]\t%lu\n", nom, prenom, &(pers.tel))==3) { /* alloue de la place memoire pour le nom et le prenom puis les copie */ pers.nom = (char *)malloc(sizeof(char)*(strlen(nom)+1)); pers.prenom = (char *)malloc(sizeof(char)*(strlen(prenom)+1)); strcpy(pers.nom, nom); strcpy(pers.prenom, prenom); setPersonneDansRep(pers); /* ajoute la personne dans le repertoire */ } /* %[^\t\n] permet de pouvoir lire toute une chaine de caractere jusqu'a une tabulation ou un retour chariot (des espaces peuvent etre contenus dans la chaine). %s lit une chaine jusqu'a un espace, retour chariot ou tabulation (donc un espace est vu comme un separateur). Si on utilise %s, cela signifie que l'on ne pourra pas lire des noms/prenoms contenant plusieurs mots et donc des espaces. */ } } /* Affiche un menu permettant d'effectuer des operations sur le repertoire */ void afficherMenu() { printf("\t******************************************************************\n"); printf("\tChoisissez une option:\n"); printf("\t******************************************************************\n"); printf("\t\t s sort du programme\n"); printf("\t\t 1 affiche le repertoire courant\n"); printf("\t\t 2 recherche le numero de telephone \n"); printf("\t\t 3 ajoute une personne dans le repertoire\n"); printf("\t\t 4 ajoute une personne sans telephone \n"); printf("\t\t 5 enleve une personne du repertoire \n"); printf("\t\t 6 changer le numero de telephone \n"); printf("\t******************************************************************\n"); printf("\t Votre choix : "); } /* programme principal */ void main() { char car; Personne pers; unsigned long numTel; recupereRep(); do { afficherMenu(); /* ignore tous les caracteres non alphanumeriques */ while(!isalnum(car=getchar())); switch (car) { case 's': sauvegardeRep(); break; case '1': afficherRepertoire(); break; case '2': pers = saisiePersonne(FALSE); if((numTel = getNumero(pers.nom, pers.prenom))!=0) printf("Le numero de telephone de %s %s est: 0%lu\n", pers.prenom, pers.nom, numTel); else printf("%s %s n'a pas de numero enregistre\n",pers.prenom, pers.nom); free(pers.nom); free(pers.prenom); break; case '3': setPersonneDansRep(saisiePersonne(TRUE)); break; case '4': setPersonneDansRep(saisiePersonne(FALSE)); break; case '5': pers = saisiePersonne(FALSE); if(enlevePersonneDuRep(pers.nom, pers.prenom)) printf("J'ai enleve %s %s du repertoire\n", pers.prenom, pers.nom); free(pers.nom); free(pers.prenom); break; case '6': pers = saisiePersonne(FALSE); if(changeNumero(pers.nom, pers.prenom)) printf("J'ai change le telephone de %s %s\n", pers.prenom, pers.nom); free(pers.nom); free(pers.prenom); break; default: fprintf(stderr,"%c: commande inconnue !\n",car); } } while (car != 's'); sauvegardeRep(); }