no save
Assistance
Achat
News

Forum | programmation
Langage C pointeurs, creation de liste.
mamiemando, le ven. 31 mars 2006 à 09:31:34
Mmmh j'ai l'impression que tu n'as pas compris le code que je t'ai passé l'autre fois :-( Zut, ça veut dire que je n'ai pas été pédagogique :-/ L'idée c'est une opération basique relative aux listes implique une fonction. Parmi elles :
- obtenir le permier élément
- obtenir le dernier élément
- creer une liste vide
- insérer un nouveau maillon

Ze problem

Donc là ça fait 4 fonctions. Or toi tu as tout mis dans la même et ça n'a plus de sens, d'où erreur du compilateur. Je m'explique : tu écris

//ici tu devrais commencer la fonction begin()

//Obtenir le premier element
maillon * debut(struct Liste * l); // tu déclares un prototype de fonction !!
return l.debut;

//et ici la finir

au lieu de déclarer et implémenter la fonction debut() ! Normalement pour être cohérent avec ce que je t'ai donné tu aurais dû écrire :
maillon * debut(struct Liste l){
return l.debut;
}
ou à la rigueur :
maillon * debut(struct Liste * l){
return l->debut; //equivalent à (*l).debut
}
Du coup tu te retrouves avec des morceaux de codes dans CreerListe qui n'ont rien à voir !! Appuies-toi sur le code que je t'ai passé l'autre fois. Par la suite tu te retrouves même avec un main à l'intérieur de la fonction CreerListe !! (apparemment tu as oublié une accolade !)

Comprendre les messages du compilateur

Maintenant je pense que tu comprends pourquoi le compilateur est perdu. Examinons ce qu'il te dit :

plop.c:31: erreur: syntax error before ‘*' token
plop.c: In function ‘CreerFiche':
plop.c:35: erreur: ‘l' undeclared (first use in this function)
plop.c:35: erreur: (Chaque identificateur non déclaré est rapporté une seule fois
plop.c:35: erreur: pour chaque fonction dans laquelle il apparaît.)
plop.c:44: attention : ‘struct liste' declared inside parameter list
plop.c:44: attention : visible uniquement depuis cette définition ou déclaration, ce qui n'est probablement pas ce que vous désirez
plop.c: In function ‘add':
plop.c:45: erreur: déréférencement d'un pointeur de type incomplet
plop.c:47: erreur: déréférencement d'un pointeur de type incomplet
plop.c:48: erreur: déréférencement d'un pointeur de type incomplet
plop.c: In function ‘CreerFiche':
plop.c:53: erreur: déréférencement d'un pointeur de type incomplet
plop.c: In function ‘main':
plop.c:78: attention : assignment from incompatible pointer type
plop.c: In function ‘CreerFiche':
plop.c:90: erreur: syntax error at end of input
Bon en C on se prends toujours plein d'erreur en cascade, donc il faut traiter les erreurs dans l'ordre (partir de la première qu'écrit le compilateur). Ici :
plop.c:31: erreur: syntax error before ‘*' token
Alors pourquoi cette erreur ?

typedef struct Fiche{
char Nom[256];
struct Fiche * Suivante;
}fiche;
...
Fiche *CreerFiche(char Texte[] )
Alors en C la casse (minuscule/majuscule) est importante !! En d'autres termes, soit tu parles d'une struct Fiche, soit d'une fiche, mais Fiche seule n'a pas de sens. J'ai eu le même problème que toi au début en C, car les prof mettent tout de suite la ligne de typedef avec la déclaration de struct. En réalité c'est :

//Déclaration de struct Fiche
struct Fiche{
char Nom[256];
struct Fiche * Suivante;
};

//Déclaration de fiche=struct Fiche
typedef struct Fiche fiche;

Petits conseils :
- évite les majuscules en C (sauf pour les #define), en général on écrit tout en minuscule avec des _, les majuscules c'est plutôt des notations java. Même si rien ne t'empêche de les utiliser ;-) C'est juste une convention.
- évite de coller les * comme tu le fais dans : "fiche*CreerFiche(char Texte[] )", ça ne coûte rien d'aérer :-)
- il ne faut pas se sentir obligé de faire un typedef. Un typedef sert just à alléger le code à la lecture.
fiche * CreerFiche(char Texte[] )

Ok donc là il suffit juste de mettre :
fiche *CreerFiche(char Texte[] )
ou :
struct Fiche *CreerFiche(char Texte[] )
Ok, maintenant l'erreur l31 est traité, on recompile, mais l'erreur l35 est toujours là.
plop.c:35: erreur: ‘l' undeclared (first use in this function
Allons ligne 35.

...
fiche *CreerFiche(char Texte[] )
{
//Obtenir le premier element
maillon * debut(struct Liste * l);
return l.debut;
...
Donc là ça rejoint ce que je t'ai dit en début de post. Tu déclares un prototype de fonction dans une fonction (ce qui est TRES mal), et tu as mis le code de cette fonction dans CreerFiche. Ca n'a donc pas de sens, il faut bien faire :

...
//1ere fonction
struct Maillon * debut(struct Liste l){
return l.debut;
}
/*
//ou la rigueur
struct Maillon * debut(struct Liste * l){
return l->debut;
}
*/

//2e fonction
struct Fiche *CreerFiche(char Texte[] )
{
...
}

Idem ensuite avec la fonction fin().
Bon ensuite la section de code que je t'ai donné
struct maillon *m_it;
struct maillon *m_fin=fin(l); // je me suis trompée ici l'autre fois.. habitude du C++ ;-)
for(m_it=debut(l) ; m_it!=m_fin ; m_it=m_it->Suivante) //idem
{
//traiter le struct maillon courant (*m_it)
}
c'est un squelette de code à incorporer dans une fonction devant parcourir la liste. Par exemple pour afficher la liste tu dois en parcourir chaque maillon donc tu peux utiliser ce genre de boucles.

Exemple :
void show_fiches(struct Liste l){
struct Maillon *m_it;
struct Maillon *m_fin=fin(l);
for(m_it=debut(l) ; m_it!=m_fin ; m_it=m_it->suite)
{
struct Fiche *f=(struct Fiche *) m_it->data; //f contient l'adresse de la fiche
printf("%s\n",f->Nom);
}
}

Même erreur sur les majuscules de fiche pour la fonction add.

Par ailleurs les fiches n'ont pas de raison de stocker un pointeur sur la fiche suivante, c'est le rôle du maillon. Normalement tu as juste le char[256] dans ta fiche, mais si par la suite tu as besoin de stocker l'âge tu pourras facilement rajouter un unsigned int... Tes structures sont donc :

typedef struct Fiche{
char Nom[256];
//unsigned int age;
}fiche;

typedef struct Maillon{
void * data;
struct Maillon * suite;
}maillon;

typedef struct Liste{
maillon * debut;
maillon * fin;
}liste;

Une fois toutes ces corrections apportées ont essayé de voir si on a rien oublié en mettant plein de warning :
(mando@H101-b) (~) $ gcc -W -Wall plop.c
plop.c: In function ‘CreerFiche':
plop.c:41: attention : unused variable ‘ptrfiche'
plop.c:42: attention : control reaches end of non-void function
plop.c: Hors de toute fonction :
plop.c:39: attention : unused parameter ‘Texte'
plop.c: In function ‘main':
plop.c:99: attention : control reaches end of non-void function
/tmp/cc0uzfiF.o: dans la fonction « main »:
plop.c:(.text+0x132): AVERTISSEMENT: the `gets' function is dangerous and should not be use

Allons voir ce qui s'y passe. Ah oui en effet il faut corriger CreerFiche (cf code final). Ensuite il faut supprimer la ligne faisant intervenir Suivant dans le main qui n'a plus de sens puisqu'on a retiré ce champ de Fiche, et rajouter à la fin du main un return 0 (qui spécifie au système que le programme s'est bien déroulé.)

On obtient donc le code :

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define LGTXT 256



typedef struct Fiche{
char Nom[256];
}fiche;

typedef struct Maillon{
void * data;
struct Maillon * suite;
}maillon;

typedef struct Liste{
maillon * debut;
maillon * fin;
}liste;

//Creer une nouvelle liste
struct Liste nliste(){
struct Liste l;
l.debut=NULL;
l.fin=NULL;
return l;
}
//Obtenir le premier element
struct Maillon * debut(struct Liste l){
return l.debut;
}

//Obtenir le dernier element
struct Maillon * fin(struct Liste l){
return l.fin;
}

fiche *CreerFiche(char Texte[] )
{
fiche* ptrfiche=(fiche*)malloc(sizeof(fiche));
strcpy(ptrfiche->Nom,Texte);
return ptrfiche;
}
//Inserer un élément en fin de liste
void add(struct Liste * l,maillon * x){
maillon *m=l->fin;
if (m!=NULL) m->suite=x;
else l->debut=x;
l->fin=x;
}

void show_fiches(struct Liste l){
struct Maillon *m_it;
struct Maillon *m_fin=fin(l);
for(m_it=debut(l) ; m_it!=m_fin ; m_it=m_it->suite)
{
struct Fiche *f=(struct Fiche *) m_it->data; //f contient l'adresse de la fiche
printf("%s\n",f->Nom);
}
}

int main()
{
int arret;
char reponse[256];
fiche* ptrnouveau;
fiche* ptrdebut;
int nombre;

arret = 1;
ptrdebut = NULL;
ptrnouveau = NULL;
nombre = 0;

do{
printf("Entrer le nom de la fiche.\n\nEntrer ''Fin'' pour terminer le programme.
\n\n");
gets (reponse);
printf("\n\n\n");
if (strcmp(reponse,"Fin"))
{
/* ptrnouveau = CreerFiche(reponse);
ptrdebut = ptrnouveau;
nombre++; */
//utilise ici les fonctions que l'on a défini, notamment la fonction add
}
else arret=0;
}while(arret);

if(nombre>1) printf("Vous avez cree %d fiches.",nombre);
else printf("Vous avez cree %d fiche.",nombre);

getchar();
return 0;
}
Bonne chance
PrécédentUn Gars
mars 06
Un Gars
mars 06
Suivant
REPONSES
mamiemando
mars 06
Un Gars
mars 06
mamiemando
mars 06
Un Gars
mars 06
mamiemando
mars 06
Un Gars
mars 06
mamiemando
mars 06
Un Gars
mars 06
mamiemando
avr. 06
Drayell / Ank[58]f1x : Webmaster, Coder(C/C++, Asm), Designer
avr. 06
Version Web
Réalisé par RedShift
no save