Extraction de chaines de caractères en C

Résolu/Fermé
ebom Messages postés 4 Date d'inscription samedi 31 octobre 2009 Statut Membre Dernière intervention 1 novembre 2009 - 31 oct. 2009 à 03:05
 pacorabanix - 31 oct. 2009 à 14:37
Bonjour à tous,

je souhaite extraire d'un fichier texte des chaines de caractères.
Chaque ligne du fichier contient dans l'ordre l'année de naissance, le nom et le prénom d'une personne, séparés par un espace.
Je souhaite extraire séparément ces 3 informations.
Voici mon code commenté:

1 fgets(chaine_lue,100,pFic); //je lis la première ligne du fichier référencé par pFic
2 //cette ligne est contenue dans chaine_lue
3 char* nom;
4 char* prenom;
5 int* annee;
6
7 annee=strtok(chaine_lue,"\0"); //avec strtok je récupère les 3 informations de la ligne
8 nom=strtok(NULL,"\0");
9 prenom=strtok(NULL,"\0");
10
11 inserer(pFile,&Creer_Fiche(&nom,&prenom,&annee));

//j'ai créé une fonction Creer_Fiche qui permet de sauvegarder les infos pour chaque personne sous forme de struct : struct fiche* Creer_Fiche(char nom[15],char prenom[15],int annee);

La fonction inserer me permet d'ajouter cette fiche à une liste pFile :
void inserer (struct file *pf,struct fiche pers);


Mais problème, cela ne compile pas :

ligne 7 warning: assignment from incompatible pointer type
ligne 11 warning: passing arg 1 of "Creer_Fiche" from incompatible pointer type
ligne 11 warning: passing arg 2 of "Creer_Fiche" from incompatible pointer type
ligne 11 warning: passing arg 3 of "Creer_Fiche" makes integer from pointer without a cast
ligne 11 error invalid lvalue in unary '&'

Lorsque j'enlève tous les & ligne 11 cela me retourne :

ligne 7 warning: assignment from incompatible pointer type
ligne 11 warning: passing arg 3 of "Creer_Fiche" makes integer from pointer without a cast
ligne 11 error: incompatible type for argument 2 of 'inserer'

je ne comprends même pas pourquoi le warning disparait pour le deuxième argument

Toute aide est la bienvenue, merci beaucoup!

3 réponses

pacorabanix
31 oct. 2009 à 03:59
ligne 7 warning: assignment from incompatible pointer type 


ça c'est simple. Le C est un langage fortement typé. Que retourne la fonction strtok ? elle retourne un char* (autement dit une chaine de caractères, ou plus précisément un pointeur vers le début de la chaine). Tu dois transformer cette chaine en nombre après coup, mais tu ne peux pas dire que c'est un pointeur cers un int.

Le truc c'est que le compilateur ne met qu'un warning car les pointeurs finalement, on peut faire plein de choses avec, y compris des mauvaises comme ce que tu as fait là ;).
0
pacorabanix
31 oct. 2009 à 04:20
ensuite pour ton souci :

 //prototype de Creer_Fiche
struct fiche* Creer_Fiche(char nom[15],char prenom[15],int annee);
//prototype de inserer
void inserer (struct file *pf,struct fiche pers); 
//ton appel :
11 inserer(pFile,&Creer_Fiche(&nom,&prenom,&annee));
  



oulalala ^^

nom, prenom, annee sont deja des pointeurs... faire "&" dessus n'a pas beaucoup de sens, ce sont déjà en eux-mêmes des références (enfin pas tout à fait en plus).

D'où les :
ligne 11 warning: passing arg 1 of "Creer_Fiche" from incompatible pointer type
ligne 11 warning: passing arg 2 of "Creer_Fiche" from incompatible pointer type
ligne 11 warning: passing arg 3 of "Creer_Fiche" makes integer from pointer without a cast 



Pour les erreurs:
ligne 11 error: incompatible type for argument 2 of 'inserer'
et
ligne 11 error invalid lvalue in unary '&' 

inserer() demande comme deuxième argument un "struct fiche". Ta fonction Creer_Fiche retourne un "struct fiche*", un pointeur vers cela. Tu dois donc
1) Soit déréférencer ton pointeur à l'aide de * (et pas & -> aucun sens de faire ça d'où l'erreur) pour que ce soir syntaxiquement correct. De plus c'est à droite qu'il faut mettre ça (je crois) pas à gauche.
soit 2) (beaucoup mieux!) faire en sorte que Creer_Fiche retourne directement une "struct fiche"

Pourquoi c'est mieux ? car si tu retournes un pointeur depuis une fonction, il faudra que tu crées ta "struct fiche" dans la fonction Creer_fiche de manière dynamique avec malloc ! Sinon, la fiche que tu crées sera tout simplement détruite à la sortie de cette fonction, et donc un pointeur qui pointe dessus est une erreur grave car elle passe à la compilation et peut causer de sérieux bugs plus tard. Le pointeur ne pointe en effet sur rien de valide après coup. Si tu retournes une vraie struct, alors la struct sera copiée pour être la bonne valeur de retour.


C'est une relativement bonne idée d'utiliser des pointeurs struct fiche comme argument dans les fonctions, c'en est une moins bonne de renvoyer des pointeurs, à moins que tu saches faire l'allocation dynamique avec malloc.

pour le problème avec les chaines en argument dans creer_fiche tu devrais spécifier comme argument "char*" plutôt il me semble, c'est cohérent avec le type de nom et adresse...
0
ebom Messages postés 4 Date d'inscription samedi 31 octobre 2009 Statut Membre Dernière intervention 1 novembre 2009
31 oct. 2009 à 14:24
Merci beaucoup pour ton aide, j'ai fait les corrections que tu m'as indiquées et ça marche parfaitement.

Au niveau de Creer_Fiche tu me suggère de retourner directement une "struct fiche", mais en fait je souhaite ajouter chaque fiche à la liste (fonction inserer) et même si la fiche est perdue si je n'utilise pas de malloc, elle est stockée dans ma liste (je pense). Donc j'ai juste déréférencer le pointeur à l'aide de * comme tu me l'as indiqué.

Encore merci!
0
pacorabanix
31 oct. 2009 à 14:37
mmm pas sûr, ça dépend comment tu as fait en détail.

N'oublie pas que tout ce que tu crées dans une fonction est irrémédiablement détruit à la sortie de cette fonction. Il se peut, mais c'est une grave erreur de logique de compter dessus, que ton pointeur pointe toujours vers l'endroit où était enregistré ta struct fiche et que les infos y soient toujours. Mais à priori rien ne l'assure, et ce genre d'erreur est ennuyeux car le compilateur laissera faire !

Pour préciser : le pointeur tu le retournes, donc il existe toujours, c'est vrai. Ce qui n'existe plus, c'est ce sur quoi le pointeur pointe !

Passer des struct fiche comme retour n'est pas très grave. En général on utilise les pointeurs pour gagner en efficacité, car retourner ou passer une struct implique la copie complète de celle-ci. Mais dans le cas de ton programme ceci ne pose AUCUN problème, tandis que ta manière de faire est un peu aléatoire et risque de causer des bugs.

L'important quand on programme est d'être très clair. Là ce n'est pas clair ;)
0