[C] Passage d'une structure en paramètre
Résolu
ilan27
Messages postés
394
Date d'inscription
Statut
Membre
Dernière intervention
-
kilian Messages postés 8732 Date d'inscription Statut Modérateur Dernière intervention -
kilian Messages postés 8732 Date d'inscription Statut Modérateur Dernière intervention -
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)
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:
- [C] Passage d'une structure en paramètre
- Remettre parametre usine pc - Guide
- Parametre dns - Guide
- Parametre windows - Guide
- Passage qwerty azerty - Guide
- Netflix paramètre compte - Guide
10 réponses
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.
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.
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!
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!
C'est bien comme ça qu'il faut faire:
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...
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...
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?
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?
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
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.
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.
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");
}
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");
}
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
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
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
Tu l'inclues dans tes deux fichiers C et tu peux maintenant utiliser cette structure tranquillement:
#include "etiquettes.h"
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"
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!
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!
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)
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)
le (char *) est inutile et dangereux. Il ne faut pas "caster" (convertir) le retour de malloc.
des fois c'est nécessaire