Liste doublement chainée

Liste doublement chainée - C - Programmation

Marsh Posté le 26-02-2008 à 18:44:22    

Bonjour, je vais aller au plus simple :
 
J'ai un fichier texte (contact.txt) de la forme "nom prenom 0601012222 email@mail.fr" sur chaque ligne.
Je voudrais dans un premier temps rentrer chaque contact dans une cellule d'une liste doublement chainée et circulaire. Malheureusement je ne maitrise pas les listes chainées.
Voici ce que j'ai fait :  
 

Code :
  1. typedef struct contact{ // on définit une structure pour y rentrer les contacts issus du fichier contact.txt
  2. char nom[30];
  3. char prenom[30];
  4. char numero[30];
  5. char email[30];
  6. }contact;
  7. typedef contact* ptr_contact; // on définit un poiteur sur la structure contact
  8. void récupérer_contact(contact *contact1)
  9. int trier_contact();
  10. int carlu;
  11. contact nouveau_contact;
  12. FILE* fichier=NULL;
  13. fichier=fopen("contact.txt","r" ); // on ouvre le fichier contact.txt
  14. if(!fichier)
  15.  printf("erreur" );  // lorsque l'ouverture du fichier echoue
  16. else
  17. {
  18.  do
  19.  {
  20.   carlu=fscanf(fichier, %s %s %s %s , ptr_contact.nom, ptr_contact.prenom, ptr_contact.numero, ptr_contact.email); // on rentre les données dans la structure
  21.   toupper
  22.   trier_contact(contact1, nouveau_contact)
  23.  }
  24.  while(carlu!=EOF)
  25. fclose(fichier);


 
A noter que j'ai utilisé une fonction (trier_contact) qui me servira à trier la liste chainée dans l'ordre alphabétique des noms.
 
Merci pour votre aide


Message édité par silver53000 le 26-02-2008 à 20:15:34
Reply

Marsh Posté le 26-02-2008 à 18:44:22   

Reply

Marsh Posté le 26-02-2008 à 18:54:43    

je vois pas trop ce que tu veux faire avec une "liste chaînée circulaire"...
 
en tout cas, pour faire une liste chaînée "simple", il faut que ta struct comporte un pointeur sur le type de ta struct, qui servira à stocker un lien vers le contact "fils".
et pour une liste chaînée double, bah c'est pareil, sauf qu'il faut deux pointeurs, un pour le fils et un pour le père.
 
ensuite il faut simplement une fonction "inserer(*contact fils, *contact pere);"
=> et elle s'occupe de rechercher le père, lui colle comme fils le nouveau contact, qui prend elle-même l'ancien fils du père pour fils, et pour père, le père.
 
pour ce qui est de "trier", si ta liste est réellement circulaire, je ne vois pas trop comment tu veux trier ça, en tout cas, un tri se fera à grands coups de permutations utilisant ta fonction inserer() et enlever() (qui s'occupe de lier le fils et le père d'un contact ensembler et allourer 0 comme pointeurs père et fils à ton pointeur enlevé)


Message édité par MagicBuzz le 26-02-2008 à 18:56:20
Reply

Marsh Posté le 26-02-2008 à 19:09:11    

Oui tout compte fait, ce n'est pas utile que la liste chainée soit circulaire, le but de la liste chainée étant :
Partir d'un fichier de contacts non trié,  
Rentrer les contacts dans une liste chainée,  
Trier celle-ci,  
Réécrire le fichier dans l'ordre alphabétique.
 
Je sais théoriquement comment fonctionne un liste chainée, avec un pointeur sur suivant et un autre sur précédent, mais je n'arrive pas à mettre celà en application avec un fichier (rentrer les données du fichier dans la liste chainée)

Reply

Marsh Posté le 26-02-2008 à 19:24:11    

man sort

Reply

Marsh Posté le 26-02-2008 à 20:08:44    

ton code est foireux (outre que y'a eu des problèmes de copier/coller, enfin j'espère).
 
char carlu;
 while(carlu=!EOF)
 
pour contenir le code eof, il faut passer par un int.
!= au lieu de =!  
 
 
 
 

Reply

Marsh Posté le 26-02-2008 à 20:16:19    

ok je vais reprendre tout ça avec mon poly de cours et reposter une solution

Reply

Marsh Posté le 26-02-2008 à 21:01:14    

Code :
  1. typedef struct contact{ // on définit une structure pour y rentrer les contacts issus du fichier contact.txt
  2. char nom[30];
  3. char prenom[30];
  4. char numero[30];
  5. char email[30];
  6. struct contact *suivant;
  7. struct contact *precedant;
  8. }contact;
  9. void récupérer_contact(contact *contact1)
  10. #define TAILLE_MAX 30
  11. contact *contact_1=NULL;
  12. int carlu;
  13. contact lesContacts[TAILLE_MAX];
  14. int i=0;
  15. FILE* fichier=NULL;
  16. fichier=fopen("contact.txt","r" ); // on ouvre le fichier contact.txt
  17.  if(!fichier)
  18.   printf("erreur" );  // lorsque l'ouverture du fichier echoue
  19.  else
  20.  {
  21.   do
  22.   {
  23.    for (i=0; i<=1000; i++)
  24.    {
  25.     carlu=fscanf(fichier, "%s %s %s %s", lesContacts[i].nom, lesContacts[i].prenom, lesContacts[i].numéro, lesContacts[i].email);// on rentre les données dans la structure
  26.         }
  27.   }
  28.   while(carlu!=EOF)
  29.  }
  30.  fclose(fichier);


 
bon j'ai rentré les données du fichier dans un tableau de structure. Ensuite je voudrais le passer dans une liste chainée, à partir de là je coince :(


Message édité par silver53000 le 26-02-2008 à 21:03:27
Reply

Marsh Posté le 26-02-2008 à 21:56:26    

mais sinon tu peux compiler ce que tu écris ? ou tu fais tout à l'aveugle ? c'est censé être une solution compilable telle que ou un bootleg de patricia kaas ? (je blagouille hein panique pas)
 
bon:
d'un point de vue design (heu heu): si c'est pour avoir liste triée, tu peux faire une liste chainée simple. (enfin bon si on t'impose une liste doublement chainée)
 
donc un "contact *suivant" par entrée et pas de précédent. et un "contact *premier" en local au main de préférence (et pas global, enfin là je sais pas trop ce que tu faisais).
 
quand tu as lu avec succès une entrée que tu as stocké dans un maillon alloué, tu te balade du premier au dernier maillon, en l'insérant devant si il est plus petit.
 
donc je veux voir:
- une fonction qui alloue et initialise un maillon
- une fonction qui compare deux maillon pour les trier
- un main qui utilise la première fonction, tente de la renseigner, libère le maillon si le renseignement échoue ou qui le passe à une fonction d'insertion triée dans la liste (et qui donc utilise la fonction de comparaison de maillon).


Message édité par bjone le 26-02-2008 à 21:57:00
Reply

Marsh Posté le 26-02-2008 à 23:00:15    

Code :
  1. typedef struct contact_liste { // on définit la structure qui contiendra les infos du contact
  2. char nom[30];
  3. char prenom[30];
  4. int numero[30];
  5. char email[30];
  6. struct contact_liste *suivant;
  7. }contact;
  8. typedef struct Liste_Repere { // on définit la structure pour avoir le contrôle sur la liste chainée contact_liste. On indique le premier élément, le dernier élément et le nombre d'éléments.  
  9.   contact *debut;
  10.   contact *fin;
  11.   int taille;
  12. }Liste;
  13. void initialisation (Liste *liste){ // on initialise la liste chainée. liste est un pointeur de type Liste
  14.   liste->debut = NULL;
  15.   liste->fin = NULL;
  16.   taille = 0;
  17. }
  18. int insertion_dans_liste_vide (Liste * liste, char *NOM, char *PRENOM, int *NUMERO, char *EMAIL){
  19.   contact *nouveau_contact;
  20.   if ((nouveau_contact = (contact *) malloc (sizeof(contact)) == NULL)
  21. {
  22.  printf("Erreur d'allocation mémoire" );
  23.  return -1;
  24.  }
  25.   else
  26. {
  27.  strcpy (nouveau_contact->nom, NOM);
  28.  strcpy (nouveau_contact->prenom, PRENOM);
  29.  strcpy (nouveau_contact->numero, NUMERO);
  30.  strcpy (nouveau_contact->email, EMAIL);
  31.  nouveau_contact->suivant = NULL;
  32.      liste->debut = nouveau_contact;
  33.      liste->fin = nouveau_contact;
  34.  liste->taille++;
  35.   return 0;
  36. }


 
 
Je me suis aidé de commentçamarche.  
Là j'ai définit ma structure avec les contact, une autre structure pour lier les maillons. Au début j'initialise tout à NULL. Mais ensuite je ne comprend pas vraiment à partir des strcpy (je connais cette fonction strcpy, mais je ne comprends pas ce qu'est *NOM etc...)  
Je rappelle que je me suis aidé d'un tuto, j'ai copié mais je n'ai pas saisi réellement ce qu'il fait quand il copie nouveau_contact->nom dans *NOM.
nouveau_contact est censé être rempli de données là? Et il les copie dans quoi?


Message édité par silver53000 le 26-02-2008 à 23:02:16
Reply

Marsh Posté le 27-02-2008 à 22:13:59    

Je crois avoir compris en fait. Quelqu'un peut il me confirmer si ce début est correct svp.  
Par contre il faudra que je remplisse les chainne de caractère NOM, PRENOM NUMERO et EMAIL au préalable. Comment faire pour que le premier contact soit rempli avec ses bonnes coordonées, ne faut il pas incrémenter?
Autre question, je rempli d'abord toute la liste chainée puis je la trie? ou je trie en même temps que je la rempli? (en gros je la rempli dans le bon ordre)

Reply

Marsh Posté le 27-02-2008 à 22:13:59   

Reply

Marsh Posté le 28-02-2008 à 22:02:46    

Quand tu insère en fin de liste, le début ne change pas ! Par contre le precedent dernier elt de la lsite doit pointer sur le nouveau dernier elt.
Ca donne quelque chose du genre
 

Code :
  1. list->fin->suivant = nouveau
  2. list->fin = nouveau

Reply

Marsh Posté le 29-02-2008 à 10:25:26    

oui, ici la fonction insertion_dans_liste_vide ne sert seulement qu'à ajouter le 1er maillon. Pour ajouter à la suite, j'ai fais cette fonction :  
 

Code :
  1. int insertion_fin_liste (Liste * liste, contact * courant, char *NOM, char *PRENOM, int *NUMERO, char *EMAIL){
  2.  
  3.   contact *nouveau_contact;
  4.   if ((nouveau_contact = (contact *) malloc (sizeof (contact))) == NULL)
  5.   {
  6.   printf("Erreur d'allocation mémoire" );
  7.       return -1;
  8.   }
  9.   else
  10.   {
  11.   strcpy (nouveau_contact->nom, NOM);
  12.   strcpy (nouveau_contact->prenom, PRENOM);
  13.   nouveau_contact->numero=NUMERO;
  14.   strcpy (nouveau_contact->email, EMAIL);
  15.   courant->suivant = nouveau_contact;
  16.   nouveau_contact->suivant = NULL;
  17.   liste->fin = nouveau_contact;
  18.   liste->taille++;
  19.   return 0;
  20.   }
  21. }


Message édité par silver53000 le 29-02-2008 à 10:26:51
Reply

Marsh Posté le 29-02-2008 à 10:31:48    

strcpy (nouveau_contact->nom, NOM);
 
badaboum ! utilise strncpy + chaine[taille - 1] = '\0', voire strlcpy si tu as.

Reply

Marsh Posté le 29-02-2008 à 19:02:04    

ça ne va pas m'apporter grand chose à ce que j'ai pu lire sur strncpy

Reply

Marsh Posté le 02-03-2008 à 20:50:56    

pour trier vous pensez que je part dans la bonne direction?
 

Code :
  1. void tri(Contact *tete)
  2. {
  3. Contact actuel = *tete;
  4. Contact precedent = actuel->suivant;
  5. Contact tmp = NULL;
  6. printf("actuel : %d\n",actuel-> valeur);
  7. printf("precedent : %d\n",precedent-> valeur);
  8.        
  9. while(precedent != NULL)
  10. {   
  11. if (strcmp(actuel->nom, precedent->nom)>0)
  12.       {                                           
  13.         tmp = precedent;
  14.  precedent = actuel; 
  15.  actuel  = tmp ;                 
  16.       }
  17.            
  18.            
  19. actuel=actuel->suivant;
  20. printf("actuel : %d\n",actuel-> valeur);
  21. printf("precedent : %d\n",precedent-> valeur);
  22.                
  23. }


Message édité par silver53000 le 02-03-2008 à 20:51:42
Reply

Marsh Posté le 03-03-2008 à 14:48:02    

silver53000 a écrit :

ça ne va pas m'apporter grand chose à ce que j'ai pu lire sur strncpy


Faire un programme correct ?

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed