Liste chainée

Fermé
silver53 - 28 févr. 2008 à 16:48
SebManfred Messages postés 484 Date d'inscription mardi 28 août 2007 Statut Membre Dernière intervention 20 mai 2011 - 3 mars 2008 à 10:32
Bonjour,
Je suis un peu perdu pour réaliser le code d'un projet.
A partir d'un fichier "contact.txt", je dois récupérer les données inscrites de la façon suivante "NOM PRENOM NUMERO EMAIL" avec un contact par ligne.
Je dois ensuite les ranger dans une liste chainée, puis trier cette liste chainée dans l'ordre alphabétique des noms pour enfin l'afficher.

Voilà mon début, pour commencer à remplir la liste chainée, j'aimerais savoir si je pars dans la bonne direction.



[cpp]
typedef struct contact_liste { // on définit la structure qui contiendra les infos du contact
char nom[30];
char prenom[30];
int numero[30];
char email[30];
struct contact_liste *suivant;
}contact;

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.
contact *debut;
contact *fin;
int taille;
}Liste;


void initialisation (Liste *liste){ // on initialise la liste chainée. liste est un pointeur de type Liste
liste->debut = NULL;
liste->fin = NULL;
taille = 0;
}


int insertion_dans_liste_vide (Liste * liste, char *NOM, char *PRENOM, int *NUMERO, char *EMAIL){
contact *nouveau_contact;
if ((nouveau_contact = (contact *) malloc (sizeof(contact)) == NULL)
{
printf("Erreur d'allocation mémoire" );
return -1;
}
else
{
strcpy (nouveau_contact->nom, NOM);
strcpy (nouveau_contact->prenom, PRENOM);
strcpy (nouveau_contact->numero, NUMERO);
strcpy (nouveau_contact->email, EMAIL);
nouveau_contact->suivant = NULL;
liste->debut = nouveau_contact;
liste->fin = nouveau_contact;
liste->taille++;
return 0;
}
/cpp

Merci en avance

7 réponses

oui, mais je dois récupérer le numéro dans un fichier, et j'ai vu que si je fais un fscanf(fichier, "%s %s %d %s", ...) et bien il ne me prend pas le 0 de mes numéros de telephonne.

Sinon une question : je devrais tirer les infos de mon fichier et les mettre dans un tableau de structure non? avant d'enclencher le processus de liste chainée?
1
SebManfred Messages postés 484 Date d'inscription mardi 28 août 2007 Statut Membre Dernière intervention 20 mai 2011 128
28 févr. 2008 à 17:00
Salut,
tu m'as l'air de partir dans la bonne direction, mais tu n'es pas forcé de faire 2 fonctions différentes pour ajouter le 1er maillon et les autres. il te suffit juste de tester si ta tête est nulle, si oui tu insère le nouvel élément à partir de la tête, sinon tu rentre dans ta boucle qui teste si courant->suivant est nul

ah... juste une petite erreur : numero est un tableau de int... avec un strcpy tu n'iras pas loin...
0
#include stdafx.h

typedef struct contact_liste { // on définit la structure qui contiendra les infos du contact
char nom[30];
char prenom[30];
int numero[30];
char email[30];
struct contact_liste *suivant;
}contact;

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.
contact *debut;
contact *fin;
int taille;
}Liste;


void initialisation (Liste *liste){ // on initialise la liste chainée. liste est un pointeur de type Liste
liste->debut = NULL;
liste->fin = NULL;
taille = 0;
}


int insertion_dans_liste_vide (Liste * liste, char *NOM, char *PRENOM, int *NUMERO, char *EMAIL){

contact *nouveau_contact;
if ((nouveau_contact = (contact *) malloc (sizeof(contact)) == NULL)
{
printf("Erreur d'allocation mémoire");
return -1;
}
else
{
strcpy (nouveau_contact->nom, NOM);
strcpy (nouveau_contact->prenom, PRENOM);
nouveau_contact->numero=NUMERO;
strcpy (nouveau_contact->email, EMAIL);
nouveau_contact->suivant = NULL;
liste->debut = nouveau_contact;
liste->fin = nouveau_contact;
liste->taille++;
return 0;
}
}


int insertion_fin_liste (Liste * liste, contact * courant, char *NOM, char *PRENOM, int *NUMERO, char *EMAIL){

contact *nouveau_contact;
if ((nouveau_contact = (contact *) malloc (sizeof (contact))) == NULL)
{
printf("Erreur d'allocation mémoire");
return -1;
}
else
{
strcpy (nouveau_contact->nom, NOM);
strcpy (nouveau_contact->prenom, PRENOM);
nouveau_contact->numero=NUMERO;
strcpy (nouveau_contact->email, EMAIL);
courant->suivant = nouveau_element;
nouveau_contact->suivant = NULL;
liste->fin = nouveau_contact;
liste->taille++;
return 0;
}




void affichage (Liste * liste){

contact *courant;
courant = liste->debut;
while (courant != NULL){
printf ("%p - %s %s %d %s\n", courant, courant->nom, courant->prenom, courant->numero, courant->email);
courant = courant->suivant;
}
}



J'ai donc fais une nouvelle fonction pour insérer un nouveau maillon à la suite de ma liste, et une fonction pour afficher ma liste. Signalez moi les erreurs ^^
Il va me falloir maintenant une fonction pour trier les contacts, pour celà je pensais utiliser un maillon "tampon" où je stockerai le contact mal rangé, je supprimerai ce contact, accrocherai le suivant à la place, et ensuite je mettrai le tampon a la suite. (c'est pas très clair, un schéma serait plus simple)

Mais d'abord, j'aimerais un coup de pouce pour passer les données du fichier à la liste chainée.
0
SebManfred Messages postés 484 Date d'inscription mardi 28 août 2007 Statut Membre Dernière intervention 20 mai 2011 128
29 févr. 2008 à 10:18
attention, nouveau_contact->numero=NUMERO; ... il faut attribuer élément du tableau par élément du tableau
for(int i=0; i<30;i++)
{
nouveau_contact->numero[i] = numero[i];
}

pour le reste, quand tu reçois un nouvel élément, tu le mets automatiquement à la fin ou tu les classes dans l'ordre alphabétique?
si tu veux les classer, il te vaut une fonction de tri (tu en as déjà parlé), permettant de dire si un individu A est avant ou après un individu B et une fonction te permettant d'insérer un maillon à un emplacement précis de ta chaine.
en gros, tu testes quel est le dernier contact qui se situe "avant" ton nouveau contact (que ça soit dans l'ordre alphabétique ou un autre ordre... c'est toi qui choisis), et tu insère ton nouveau contact juste après ce dernier contact.

sinon, pour ce qui est de tout stocker dans un tableau, je ne pense pas que ça soit une bonne idée. le gros avantage de la liste chainée sur le tableau, c'est que tu ne précise pas la taille. quand tu lis ton fichier, à priori, je ne pense pas que tu saches combien d'enregistrement il contient...
le mieux, au niveau de la gestion de la mémoire, est d'enregistrer tes contacts au fur et à mesure que tu les lis.

et pour débusquer les erreurs, ce qui va t'apprendre le plus de choses, c'est de compiler et d'exécuter pour voir comment ça se comporte. tu peux mettre des printf pour tracer ce que fait ton programme, si tu veux, mais si je t'explique moi ce qui ne va pas, ça te sera beaucoup moins profitable que si tu te prend la tête et que tu trouve tout par toi-même.
si tu bloques, je te donnerai un coup de main, mais essaie d'abord par toi même

mais ton programme m'a l'air d'être bien parti.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
sinon, pour ce qui est de tout stocker dans un tableau, je ne pense pas que ça soit une bonne idée. le gros avantage de la liste chainée sur le tableau, c'est que tu ne précise pas la taille. quand tu lis ton fichier, à priori, je ne pense pas que tu saches combien d'enregistrement il contient... 
le mieux, au niveau de la gestion de la mémoire, est d'enregistrer tes contacts au fur et à mesure que tu les lis. 


En fait là où je bloque, c'est pour récupérer les données du fichier et les passer dans la liste chainée. Je pensais faire un fgets et tout stocker dans des tableaux intermédiaires, mais comme tu le dis, ce n'est pas la meilleure solution.



void récupérer_contact(contact *contact1)

#define TAILLE_MAX 30
int carlu;
contact lesContacts[TAILLE_MAX];
int i=0;



FILE* fichier=NULL;
fichier=fopen("contact.txt","r"); // on ouvre le fichier contact.txt

if(!fichier)
printf("erreur"); // lorsque l'ouverture du fichier echoue
else
{
do
{
for (i=0; i<=1000; i++)
{
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

}
}
while(carlu!=EOF)
}
fclose(fichier);



Ici j'ai supposé qu'il n'y avait pas plus de 1000 contacts dans le fichiers.
Je pense qu'il doit y avoir une solution pour utiliser mes fonctions réalisées précédement afin de rentrer les données directement dans un maillon de la liste.
0
sinon, pour ce qui est de tout stocker dans un tableau, je ne pense pas que ça soit une bonne idée. le gros avantage de la liste chainée sur le tableau, c'est que tu ne précise pas la taille. quand tu lis ton fichier, à priori, je ne pense pas que tu saches combien d'enregistrement il contient...
le mieux, au niveau de la gestion de la mémoire, est d'enregistrer tes contacts au fur et à mesure que tu les lis.


En fait là où je bloque, c'est pour récupérer les données du fichier et les passer dans la liste chainée. Je pensais faire un fgets et tout stocker dans des tableaux intermédiaires, mais comme tu le dis, ce n'est pas la meilleure solution.



void récupérer_contact(contact *contact1)

#define TAILLE_MAX 30
int carlu;
contact lesContacts[TAILLE_MAX];
int i=0;



FILE* fichier=NULL;
fichier=fopen("contact.txt","r"); // on ouvre le fichier contact.txt

if(!fichier)
printf("erreur"); // lorsque l'ouverture du fichier echoue
else
{
do
{
for (i=0; i<=1000; i++)
{
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

}
}
while(carlu!=EOF)
}
fclose(fichier);



Ici j'ai supposé qu'il n'y avait pas plus de 1000 contacts dans le fichiers.
Je pense qu'il doit y avoir une solution pour utiliser mes fonctions réalisées précédement afin de rentrer les données directement dans un maillon de la liste.
0
Finalement :



void load(Contact **Tete){
FILE *contact = NULL;
Contact *Tete;
char NOM[TAILLE_MAX] = "";
char PRENOM[TAILLE_MAX] = "";
char NUMERO[TAILLE_MAX] = "";
char EMAIL[TAILLE_MAX] = "";
*Tete = NULL;

system("cls");
contact = fopen("contact.txt", "r");

if (contact != NULL){
while (fscanf(contact, "%s %s %s %s", NOM, PRENOM, NUMERO, EMAIL ) != NULL){
Contact *Nouveau = (Contact*)malloc(sizeof(Contact));
sprintf(Nouveau->nom, "%s",NOM);
sprintf(Nouveau->prenom, "%s",PRENOM);
sprintf(Nouveau->numero, "%s",NUMERO);
sprintf(Nouveau->email, "%s",EMAIL);


Nouveau->suivant = (*Tete);
(*Tete) = Nouveau;
}
}
fclose(contact);


system("pause");

}



maintenant j'aimerais trier cette liste chainée, voilà ce que j'ai fait :


void tri(Contact *tete)
{
Contact actuel = *tete;
Contact precedent = actuel->suivant;
Contact tmp = NULL;


printf("actuel : %d\n",actuel-> valeur);
printf("precedent : %d\n",precedent-> valeur);


while(precedent != NULL)
{

if (strcmp(actuel->nom, precedent->nom)>1)
{
tmp = precedent
precedent = actuel;
actuel = tmp ;
}


actuel=actuel->suivant;

}


aidez moi à m'en sortir
0
SebManfred Messages postés 484 Date d'inscription mardi 28 août 2007 Statut Membre Dernière intervention 20 mai 2011 128
3 mars 2008 à 10:32
je ne comprend pas très bien pourquoi tu fais comme ça, notamment le "precedent = actuel->suivant;"...
tu peux trier à l'enregistrement : tu as 5 noms : AAAA, DDDD, FFFF, JJJJ et MMMM, tu veux insérer le nom EEEE
tu teste à partir de la tête de ta liste, tant que le nom courant est inférieur au nouveau nom, tu passe au nom suivant, puis des que le nom courant est supérieur au nouveau nom, tu insère le nouveau nom entre le nom précédent et le nom courant, et ta liste sera triée dès sa création

après, si tu veux faire une fonction qui te trie une liste déjà existante, ça peut dépendre beaucoup de comment tu veux la trier : des algorithmes de tri, il en existe beaucoup, tout dépend de ce que tu veux en faire.
0