IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Pb de porté des typedef et des variables globales


Sujet :

C

  1. #1
    Membre à l'essai
    Inscrit en
    Mars 2010
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 23
    Points : 21
    Points
    21
    Par défaut Pb de porté des typedef et des variables globales
    Bonjour,

    j'ai un problème à propos "les variables globales".. et la portée des nouveaux types pour tout les fichiers .c du meme projet..
    j'ai fait la recherche à l'internet.. et j'ai fait la déclaration des variables par "extern" etc..
    et ça compile mais il aura une erreur dans l'exécution.. lors de l'appel d'une fonction d'affichage qui prend en paramètre une variable globale traitée dans une autre fonction..
    Mon travail exige que tout mes fonction renvoie soit true ou false.. (et pas une variable) donc le traitement ce fait sur les variables entrées en réference..

    voici le code en résumé.. :

    main.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    #include <stdio.h>
    #include <stdlib.h>
    #define TRUE 1
    #define FALSE 0
     
    typedef struct s_tag_
    {
        char name[512];
        char value[512];
        struct s_tag_ *nxt;
    }s_tag; 
     
    typedef s_tag* taglist; // type des listes chainées (je veux qu'il soit globale)
     
    taglist listep = NULL; // variable globale
     
    int fct_parsing (char *listep);
    void afficherListe(taglist listep);
     
    int main()
    {
        fct_parsing(&listep);
        afficherListe(listep);
        return 0;
    }
    et voici le fichier parsing.c :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define TRUE 1
    #define FALSE 0
    
    typedef struct s_tag_
    {
        char name[512];
        char value[512];
        struct s_tag_ *nxt;
    }s_tag; // j'ai répéter la définition des type pour qu'il compile :oops:
    typedef s_tag* taglist; // ...
    
    extern taglist listep;
    
    /// affichage ///
    void afficherListe(taglist listep)
    {
        
        //s_tag *tmp = listep;
        while(listep != NULL)
        {
            printf("name: %s\nvalue: %s\n", listep->name, listep->value);
            listep = listep->nxt;
        }
    }
    
    
    int texte_parser (taglist *listep)
    {
        listep = NULL;
        /* des traitements sur un fichier pour récupérer des valeurs "tagnames et tagvalues"
        ajouterEnFin(tagnames, tagvalues, &listep); // remplissage dans la liste chainée
        afficherListe(listep); // ici l'affichage est parfait !!
        return 0;
    }
    
    int fct_parsing (taglist *listep)
    {
        texte_parser(&listep);
        afficherListe(listep); // ici l'affichage crash !!
        return 0;
    }
    Merci de m'aider !

  2. #2
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Points : 2 505
    Points
    2 505
    Par défaut
    afficherListe() attend un taglist, et tu lui passes un taglist * (dans les deux cas, d'ailleurs). J'ai l'impression que tu t'es mélangé les pinceaux, en oubliant que taglist est déjà lui-même un pointeur.

    Ce n'est jamais une bonne idée de cacher la "pointitude" des types dans un typedef (même si on t'as probablement appris l'inverse à l'école).

    Ensuite ne dupliques pas les déclaration dans les deux .c. Créé plutôt un .h que tu inclues dans les deux .c.

  3. #3
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int fct_parsing (taglist *listep)
    {
        texte_parser(&listep);
    ...
    }
    Là, tu envoie à la fonction non pas la valeur du pointeur, mais son adresse !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int texte_parser (taglist *listep)
    {
        listep = NULL;
    ...
    }
    Là, tu mets à NULL l'objet (le pointeur) passé en argument. C'est quoi l'intérêt ?

    Tu envoies un pointeur de pointeur, et la fonction attend un pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void afficherListe(taglist listep)
    Je n'ai pas regardé le reste, je n'ai rien compris à ce que tu veux faire...

  4. #4
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Pas mal de choses qui se mélangent.

    - D'abord, pourquoi avoir cette variable globale alors que tu la passes par la liste des paramètres aux fonctions (ce qui est bien) ?

    -
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    void afficherListe(taglist listep)....
    int fct_parsing (taglist *listep)....
    int texte_parser (taglist *listep)...
    Attention, dans ces fonctions, listep ne désigne pas la variable globale, mais le paramètre local qui a (aussi) pour nom listep

    - Le compilateur devrait faire des réflexions désagréables :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    taglist listep = NULL; // variable globale 
    int fct_parsing (char *listep); 
    int main()
    {
        fct_parsing(&listep);  
    // listep est un taglist donc &listed est un taglist * . 
    //  Or le prototype de fct_parsing annonce un char *
    - De plus ce prototype ne correspond pas à la définition de fct_parsing() dans parsing.c .

    - Dans la fonction fct_parsing(), on appelle texte_parser() avec pour argument &listep ce qui d'après la définition de cette fonction est un taglist ** . Or la fonction texte_parser() attend un taglist *.

    - Globalement, on ne procède pas de cette façon. Il faut créer un .h contenant les définitions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct s_tag_
    {
        char name[512];
        char value[512];
        struct s_tag_ *nxt;
    }s_tag; 
     
    typedef s_tag* taglist; // type des listes chainées (je veux qu'il soit globale)
    extern taglist listep;
    int fct_parsing (char *listep); // en corrigeant ce prototype.
    void afficherListe(taglist listep);
    Faire un #include de ce .h dans main.c et parsing.c (et supprimer les déclarations qui correspondent).
    Comme cela, on est sûr que tous les modules utilisent bien les mêmes définitions.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  5. #5
    Membre à l'essai
    Inscrit en
    Mars 2010
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 23
    Points : 21
    Points
    21
    Par défaut
    Salut,
    merci pour vos réponses mais :

    @ matafan :
    ok, mais pourquoi l'affichage se passe bien à l'interieur de la fonction qui rempli la liste chainées (texte_parser), par contre dans l'autre fonction (fct_parsing) il aura un crash et un erreur dans le début de l'affichage

    @ jeroman :
    [listep = NULL;]
    => c'est pour l'insialiser, sinon des valeurs bizarre seront affectées à l'entête de la liste chainée

    @ diogene :
    j'ai fait une erreur dans le prototype de fct_parsing
    le voila, c'est pas char* mais taglist
    => [int fct_parsing (taglist *listep);]

    @ tous :
    qu'est ce que j'écrit exactement dan le .h pour les typedef ?

  6. #6
    Membre à l'essai
    Inscrit en
    Mars 2010
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Mars 2010
    Messages : 23
    Points : 21
    Points
    21
    Par défaut Let's start over.. ;)
    Ok, j'ai fait une confusion entre les variable globales et les variables local de meme nom..

    dans la nouvelle version j'ai évité l'utilisation des variable globales, aussi j'ai créée un .h pour les définnition des types ("typedef.h")

    mon code contient des appels imbrquées des fonctions, chaque fonction doit retourner TRUE ou FALSE (pas d'échage de variables par "return") c.a.d que les modification sur les variables seront effectués par des passafes par référence.

    mon problème c'est lorsque j'affiche le continue de la variables (listes chainées) par une fonction appelante, passée en référence à une autre fonction (appelée), le continue (qui était correcte dans la fonction appelé de remplissage des listes chainées) sera erroné, et l'exécution fait un crash

    voici le code :

    typedef.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    #ifndef TYPEDEF_H_INCLUDED
    #define TYPEDEF_H_INCLUDED
     
    typedef struct s_tag_
    {
        char name[512];
        char value[512];
        struct s_tag_ *nxt;
    }s_tag; 
     
    typedef s_tag* taglist;
     
    #endif // TYPEDEF_H_INCLUDED
    parsing.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "typedef.h"
    #define TRUE 1
    #define FALSE 0
    
    /// la fonction d'affichage ///
    void afficherListe(taglist listep)
    {
        
        //s_tag *tmp = listep;
        while(listep != NULL)
        {
            printf("name: %s\nvalue: %s\n", listep->name, listep->value);
            listep = listep->nxt;
        }
    }
    
    
    int texte_parser (taglist *listep)
    {
        listep = NULL;
        /* 
    ...des traitements sur un fichier pour récupérer des valeurs "tagnames et tagvalues"... */
        ajouterEnFin(tagnames, tagvalues, &listep); // fonction de remplissage dans la liste chainée
        afficherListe(listep); // ici l'affichage est parfait !! 
         :ccool:
        return 0;
    }
    
    int fct_parsing (taglist *listep)
    {
        texte_parser(&listep);
        afficherListe(listep); // ici l'affichage crash !! :cry:
        return 0;
    }
    main.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    #include <stdio.h>
    #include <stdlib.h>
    #include "typedef.h"
    #define TRUE 1
    #define FALSE 0
     
    int fct_parsing (char *listep);
    void afficherListe(taglist listep);
     
    int main()
    {
        taglist listep = NULL;
        fct_parsing(&listep);
        afficherListe(listep); // affichage = meme pour ce qui ce passe dans fct_parsing
        return 0;
    }
    Help !

  7. #7
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par amo-said Voir le message
    mon problème c'est lorsque j'affiche le continue de la variables (listes chainées) par une fonction appelante, passée en référence à une autre fonction (appelée), le continue (qui était correcte dans la fonction appelé de remplissage des listes chainées) sera erroné, et l'exécution fait un crash
    Le code présente encore la plupart des erreurs déjà signalées par matafan, jeroman et diogene (notamment les confusions entre taglist, taglist* et taglist**). Tant que tu ne corrigeras les erreurs signalées, ton code ne sera pas correct.

  8. #8
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    1- mettre les prototypes des fonctions fct_parsing() et afficherListe() dans typedef.h et les supprimer de main.c

    2- mettre les #define TRUE 1 et #define FALSE 0 dans typedef.h et les supprimer de main.c et parsing.c

    3- dans main.c, ceci est incorrect.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int fct_parsing (char *listep);
    ....
        fct_parsing(&listep);
    et de plus incompatible avec la définition de la fonction dans parsing.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int fct_parsing (taglist *listep)
    {....
    erreur déjà mentionnée dans mon précédent post

    4- Si on regarde le fonctionnement du code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        taglist listep = NULL;
        fct_parsing(&listep);
    est logique : fct_parsing() doit pouvoir modifier listep, donc on passe son adresse.
    Le prototype de fct_parsing() doit donc être
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int fct_parsing (taglist *listep);

    Voyons fct_parsing() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int fct_parsing (taglist *listep)
    {
        texte_parser(&listep);
        afficherListe(listep);
    texte_parser() doit pouvoir modifier le listep dans main(). Ici, dans cette fonction, listep est justement l'adresse du listep de main(). Donc on doit le passer à la fonction.
    Par contre, afficherListe() n'a pas besoin de l'adresse du listep de main(), mais de sa valeur.
    Alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int fct_parsing (taglist *listep)
    {
        texte_parser(listep);
        afficherListe(*listep);
    et les prototypes sont donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int texte_parser (taglist *listep);
    void afficherListe(taglist listep);
    5- Ce qui est sûr, c'est qu'on ne peut avoir la fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int texte_parser (taglist *listep)
    qui commence par
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

Discussions similaires

  1. Comment ajouter des séries dans des graphes sur des feuilles variables
    Par Molomarcopolo dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 06/07/2012, 16h26
  2. Réponses: 4
    Dernier message: 02/04/2008, 17h51
  3. Réponses: 3
    Dernier message: 13/09/2007, 18h11
  4. des vector, des typedef et des fonctions.
    Par hpfx dans le forum SL & STL
    Réponses: 3
    Dernier message: 13/07/2007, 17h22
  5. Réponses: 3
    Dernier message: 23/01/2007, 08h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo