[C] Passage d'une structure en paramètre

Résolu/Fermé
ilan27 Messages postés 394 Date d'inscription mardi 25 septembre 2007 Statut Membre Dernière intervention 15 juin 2009 - 16 janv. 2008 à 19:21
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 - 17 janv. 2008 à 00:59
Bonsoir,
J'ai crée un petit programme, dont une fonction a du mal à compiler, et après plusieurs recherches, je ne trouve pas la solution. Mais je sais que ça doit être quelque chose de simple.

Voici la partie du main concernée: (Je crée une "Etiquette" aec un int, et un tableau de char)

struct Etiquette{
int adresse;
char nom[20];
};
//Je crée un tableau de 20 Etiquettes
struct Etiquette t[20];
//J'appelle la fonction, voir plus bas, censée écrire dans ce tableau, c'est-à-dire donner l'adresse et le nom aux structures
recupereEtiquettes(src, t, 20);

Et voici la fonction appelée (avec l'erreur de compliation):

void recupereEtiquettes(FILE * source, struct Etiquette t[], int taille){
int i=0, numligne=0;
char *ligne=(char *)malloc(60);
do{
fgets(ligne, 60, source);
//Je récupere une ligne d'un fichier
if(isEtiquette(ligne)){
t[i]={numligne, nomEtiquette(ligne)}; //Je définis ma structure---------->Erreur de compliation (voir plus bas)
i+=1;
}
numligne+=(sizeof(int));
}while(ligne!=NULL && i<taille);
if(i>=taille) printf("Trop d'étiquettes à stocker!\n");
}


Enfin; l'erreur de compliation est:(Tout concerne la meme ligne)
Invalid use of undefined type 'struct Etiquette'
Defercencing pointer to incomplete type
Syntax error before '{' token

ps: Erreur de compliation aussi si je mets à la place de cette ligne:
strcpy(t[i].nom, nomEtiquette(ligne));
t[i].adresse=numligne;

Merci beaucoup! (J'utilise Code::Blocks)
A voir également:

10 réponses

Pacorabanix Messages postés 3248 Date d'inscription jeudi 23 août 2007 Statut Membre Dernière intervention 19 mai 2013 660
16 janv. 2008 à 20:52
Bonjour,

je remarque plusieurs choses qui ne jouent pas .

char *ligne=(char *)malloc(60);
le (char *) est inutile et dangereux. Il ne faut pas "caster" (convertir) le retour de malloc.

ensuite concernant ton affectation qui ne compile pas :

t[i]={numligne, nomEtiquette(ligne)};

je ne crois pas qu'on puisse faire comme cela (sauf à la déclaration des variables ). par contre tu peux faire t[i].adresse = numligne
et pour la chaine de caractere faire une copie de chaine (voir https://c.developpez.com/faq/?page=Les-chaines-de-caracteres#STRINGS_string_init )

ensuite pour les struct etc... je m'embrouille toujours :) voir ici https://c.developpez.com/faq/#KEYWORD_typedef_struct pour utiliser typedef et struct.
0
lami20j Messages postés 21331 Date d'inscription jeudi 4 novembre 2004 Statut Modérateur, Contributeur sécurité Dernière intervention 30 octobre 2019 3 567
16 janv. 2008 à 21:06
Salut,

le (char *) est inutile et dangereux. Il ne faut pas "caster" (convertir) le retour de malloc.

des fois c'est nécessaire

typedef struct Element_{
    struct Element_ *suivant;
    void *donnee;
}Element;

Element *nouveau;

nouveau = (Element *) malloc (sizeof(Element));
0
ilan27 Messages postés 394 Date d'inscription mardi 25 septembre 2007 Statut Membre Dernière intervention 15 juin 2009 36
16 janv. 2008 à 21:49
Merci pour vos réponses!

En effet, j'ai déjà essayé :
strcpy(t[i].nom, nomEtiquette(ligne));
t[i].adresse=numligne;

Mais le résultat est le même (ça contredit vraiment ce que j'avais appris, ou du moins je ne vois pas de 'piège'...)

En ce qui concerne le cast, j'ai appris qu'il n'était pas nécessaire, mais qu'il était préférable de le mettre, alors tant qu'à faire...

J'ai regardé les liens, notamment sur les struct, mais les tableaux de struct ne sont pas abordés. J'ai donc essayé un typedef, mais ça n'a pas l'air de marcher.
Code::Blocks a vraiment un sale caractère! :p

Si vous détectez d'autres lueurs de solutions... ;)
Merci!
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
16 janv. 2008 à 22:10
C'est bien comme ça qu'il faut faire:
strcpy(t[i].nom, nomEtiquette(ligne)); 
t[i].adresse=numligne; 


Le problème c'est qu'il considère que ton type struct Etiquette n'est pas défini.
Tu n'aurais pas déclaré ton type struct Etiquette à l'intérieur d'une fonction et non pas de manière globale?

Sinon, il faudrait que tu nous mettes la source complète...
0
ilan27 Messages postés 394 Date d'inscription mardi 25 septembre 2007 Statut Membre Dernière intervention 15 juin 2009 36
16 janv. 2008 à 22:19
Merci pour ta réponse.

J'ai déclaré "struct Etiquette" et le tableau de struct Etiquette dans le main, et c'est dans le main que j'appelle la fonction dans laquelle il y a le problème. (Je passe le tableau en paramètre). Je ne vois pas ce qui pourrais être plus global... Tu penses qu'il y a une erreur à ce niveau?
Y a-t-il (on sait jamais) une bibliothèque particulière aux struct?
0

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

Posez votre question
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
16 janv. 2008 à 22:26
Oui il y a une erreur à ce niveau :-)
Si tu déclares un type dans une fonction (appelons là fonction1), la portée de ce type ne sera visible que dans cette fonction1, sa définition ne sera pas visible ailleurs même dans une autre fonction (appelons là fonction2) appelée dans cette fonction1. Car la définition de fonction2 se fait ailleurs, dans un endroit ou la définition de ton type n'est pas visible.

Il faut que tu rendes global la définition de ta structure, que tu la définises en dehors de toute fonction. Et juste le type, pas la variable.
0
ilan27 Messages postés 394 Date d'inscription mardi 25 septembre 2007 Statut Membre Dernière intervention 15 juin 2009 36
16 janv. 2008 à 22:39
J'ai essayé d'écrire

struct Etiquette{
int adresse;
char nom[20];
};
struct Etiquette t[20];

avant le main.

Du coup, je retire les paramètres "struct Etiquette * " dans l'appel et la définission de la fonction à problème...etc
Normalement elle devrait etre globale cette structure, et t aussi.
Et il 'ose' me mettre
" 't' undeclared, first use in this function"
Each undeclared identifier is reported only once for each function it appears in" (!!)

Je vous mets le code:

FICHIER MAIN.C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "utile.h"


int main()
{
int code;
int i=0;
FILE *src=fopen("essai.txt", "r");
FILE *cpy=fopen("copy.txt", "w");
//On ne souhaite que le lire: "r". Ici, src ---> nomdufichier
char *ligne=(char*)malloc(60);
for(i=0; i<60; i++) ligne[i]='\0';
//On va récupérer d'éventuelles étiquettes
struct Etiquette{
int adresse;
char nom[20];
};
struct Etiquette t[20];

recupereEtiquettes(src, t, 20);

fgets(ligne, 60, src);
code=traduction(ligne, t);
//t est nécessaire, car la traduction va l'utiliser pour associer les adresses
fprintf(cpy, "%d\n", code);

free(ligne);
fclose(cpy);
fclose(src);

return 0;
}


ET UTILE.C: (J'ai enlevé une partie qui n'avait rien à voir)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <math.h>



int isEtiquette(char c[]){
int i=0;
for(i; c[i]; i++){
if(c[i]==':') return 0;
}
return 1;
}

char * nomEtiquette(char *s){
int i=0;
char *res=(char *)malloc(20);
for(i; *(s+i)!=':'; i++){
*(res+i)=*(s+i);
}
return res;
}

void recupereEtiquettes(FILE * source, struct Etiquette * t,int taille){
int i=0, numligne=0;
char *ligne=(char *)malloc(60);
//temporaire
do{
fgets(ligne, 60, source);
if(isEtiquette(ligne)){
//struct Etiquette t[i];
//t[i]={0, ""};
//t[i]={numligne, nomEtiquette(ligne)};
strcpy(t[i].nom, nomEtiquette(ligne)); // -------------------------------------ICI-----------------------------
t[i].adresse=numligne;
i+=1;
}
numligne+=(sizeof(int));
}while(ligne!=NULL && i<taille);
if(i>=taille) printf("Trop d'étiquettes à stocker!\n");
}
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 836
16 janv. 2008 à 22:45
Salut,
Je constate dans ton code plusieurs erreurs.
Tout d'abord pourquoi faire de l'allocation dynamique alors que tu connais ta longueur à la déclaration ? Un simple char variable[50] suffirait.

t[i]={....} que tu as mis en commentaire, ne peut pas marcher sauf à la déclaration.

Ta structure n'est pas globale, donc elle n'est pas connue en dehors de la fonction dans laquelle tu l'as déclarée.

Remets le nouveau message d'erreur lors de la compilation.

Cordialement
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
16 janv. 2008 à 22:48
Ah mais il fallait le dire que c'était deux fichiers!
En ce cas il faut déclarer ton type de manière globale et complète pour les deux.
L'idéal: tu écris un fichier etiquettes.h dans le quel tu mets
struct Etiquette{ 
int adresse; 
char nom[20]; 
}; 


Tu l'inclues dans tes deux fichiers C et tu peux maintenant utiliser cette structure tranquillement:
#include "etiquettes.h"
0
ilan27 Messages postés 394 Date d'inscription mardi 25 septembre 2007 Statut Membre Dernière intervention 15 juin 2009 36
16 janv. 2008 à 23:04
EEEEXCELLENT!!!!!

Mille bravos!, admire le travail:
0 errors, 0 warnings
Un grand merci, ça me désespérait. ;)

(J'ai rajouté à etiquette.h le tableau de struct)

==>Je récapitule:
On "globalise" la structure et le tableau de structure dans un '.h' qu'on inclut dans les fichiers qui l'utilisent
On n'oublie pas de retirer le tableau des arguments, sans oublier les '.h'

Merci kilian!
0
kilian Messages postés 8731 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 20 août 2016 1 527
17 janv. 2008 à 00:59
Nononon........ On ne globalise que le type!

De manière générale:
_ On s'arrange pour qu'un type soit global (pour qu'il soit visible de partout), d'ailleurs je vois pas l'interêt d'un type local en C.
_On s'arrange pour qu'une variable soit locale (les variables globales, ça fout le bordel dans le code)
0