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 :

Manipulation de structure


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 18
    Par défaut Manipulation de structure
    Bonsoir, j'illustre mon problème dans l'exemple suivant:

    (t_prototype est un typedef de ma strucure, elle contient un int age)

    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
    #include "fichier.h"
    #include <stdio.h>
     
    void fonction_2(QUE RECEVOIR ??)
    {
    exemple->age = 42;
    }
     
    void fonction_1(t_prototype *ptr)
    {
    fonction_2(QUE LUI ENVOYER ??);
    }
     
    int   main()
    {
    t_prototype exemple;
     
    fonction_1(&exemple);
    printf("%i, exemple.age");
    }
    Merci de m'indiquer si il y un moyen autre que d'envoyer la structure elle même !

  2. #2
    Membre émérite Avatar de SofEvans
    Homme Profil pro
    Développeur C
    Inscrit en
    Mars 2009
    Messages
    1 082
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur C

    Informations forums :
    Inscription : Mars 2009
    Messages : 1 082
    Par défaut
    Non, tu dois envoyer la structure, et si on se fie au code present dans la fonction, tu dois envoyer un pointeur vers la structure, exactement comme avec fonction1.

    Sinon, tu peux mettre ta variable exemple en variable global.
    Tu n'aura donc plus a la passer par argument.
    Cependant, faire de cette maniere est extrement nefaste et mauvais.
    Il vaut mieux passer la structure par argument.

  3. #3
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void fonction_2(t_prototype * exemple)
    {
        exemple->age = 42;
    }
     
    void fonction_1(t_prototype * ptr)
    {
        fonction_2(ptr);
    }
    Merci de m'indiquer si il y un moyen autre que d'envoyer la structure elle même !
    Mais là on n'envoie pas la structure ! Juste son adresse. Ou bien tu veux parler de ceci : (?)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void fonction_2(int * p_age)
    {
        *p_age = 42;
    }
     
    void fonction_1(t_prototype * ptr)
    {
        fonction_2( &(ptr->age) );
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%i, exemple.age");
    C'est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("%i", exemple.age);

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 18
    Par défaut
    Ok ! Merci beaucoup, c'est vrai que ca semble logique^^ oui je sais qu'on envoie l'adresse, mais vue que ca fonctionnait pas je voulais savoir si on était obligé d'envoyer la structure...

    Seulement imaginons qu'il ne s'agisse pas d'un "int" mais d'un "char **", on récupérera un "char * **tab" ? Ça peu paraitre question/réponse mais avoir 3'*' consécutives devant un type c'est quelque chose que je n'ai encore jamais vu...

  5. #5
    Expert confirmé
    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
    Par défaut
    J'ai un bug de "previous declaration" sur la ligne de "fonction_2(&exemple);"
    Je ne vois pas pourquoi, à moins qu'une déclaration différente de fonction_2 existe dans fichier.h.

    Par contre, ce code ne fait pas ce que tu veux :

    Dans main, tu appelles fonction_1(exemple) et tu envois ainsi une copie de la structure exemple (du main)

    Dans fonction_1, une nouvelle variable exemple est créée et reçoit la copie (de la structure exemple du main)
    Tu envois l'adresse de cette nouvelle variable à fonction_2 qui en modifie un champ. Puis tu quittes fonction_1 et cette variable exemple (modifiée par fonction_2) est détruite et tu reviens au main.

    La variable exemple du main est restée inchangée.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 18
    Par défaut
    Oui je sais mais j'utilise en fait un pointeur sur fonction qui retourne une structure en remplaçant les nouvelles valeurs chaque fois que la fonction vers laquelle je pointe est retournée, je voulais en fait juste creer un exemple illustrant un problème technique, cela dit c'est sympa de me l'avoir préciser^^

    Sinon tu as raison c'était un problème de mon .h, j'ai édité le post dès que je m'en suis appercut mais un peu trop tard, désolé !

    Cela dit j'aimerais bien avoir une réponse par rapport à ce que m'a dit Melem, ca m'intéresse beaucoup ! j'aimerais bien maîtriser la manipulation d'adresses, je vois beaucoup de gens recréer des types à chaque fois qu'ils changent de fonction mais je trouve ça pas très propre bien que plus lisible...

    Donc, pourrais je ainsi avoir ...?

    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
     
    void fonction_2(char ***p_double_tab)
    {
    int y;
    int x;
     
    y = 0;
    x = 0;
    *p_double_tab[y][x] = 'A';
    }
     
    void fonction_1(t_prototype *ptr)
    {
        fonction_2(&(ptr->double_tab));
    }
     
    int   main()
    {
    t_prototype exemple;
     
    fonction_1(&exemple);
    }

  7. #7
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Pour nous fixer les idées, nous allons juste parler d'adresses de variable mais bien entendu, une adresse n'est pas forcément associée à une variable ...

    - Une variable de type char * est une variable qui contient l'adresse d'un char.
    - Une variable de type char ** est une variable qui contient l'adresse d'une variable de type char *.
    - Une variable de type char *** est une variable qui contient l'adresse d'une variable de type char **.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char c;
    char * p = &c;
    char ** q = &p;
    char *** r = &q;
    *(*(*r)) = '+'; // Les parenthèses sont facultatives
    putchar(c); // Affiche : +
    Donc, pourrais je ainsi avoir ... ?
    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
    void fonction_2(char ***p_double_tab)
    {
        int y;
        int x;
     
        y = 0;
        x = 0;
        *p_double_tab[y][x] = 'A';
    }
     
    void fonction_1(t_prototype *ptr)
    {
        fonction_2(&(ptr->double_tab));
    }
     
    int   main()
    {
        t_prototype exemple;
     
        fonction_1(&exemple);
    }
    Le prototype de fonction_1 est correct. Le prototype de fonction_2 n'est correct que si double_tab est de type char **. Si double_tab par contre est un tableau "à deux dimensions" comme on le dit dans les autres langages (et qu'on utilise parfois aussi en C), alors le prototype de fonction_2 n'est pas correct. Pas la peine de faire intervenir des fonctions pour donner des explications :

    Soit le tableau double_tab :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char double_tab[10][20];
    double_tab est un tableau de 10 éléments, chaque élément étant un tableau de 20 char. Son type est char [10][20] (cliquez ici si vous ne comprenez pas).

    Soit p_double_tab le pointeur qui va contenir l'adresse de double_tab. p_double_tab est donc de type "pointeur sur char [10][20]" et (*p_double_tab) de type "char [10][20]". Pour déclarer p_double_tab, il faut donc écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char (*p_double_tab) [10][20];
    Le type de p_double_tab est donc char (*) [10][20] et non char ***.

    D'ailleurs, en langage C, c'est rare de vouloir passer l'adresse d'un tableau à une fonction, il suffit de passer l'adresse de son premier élément (différence entre adresse d'un tableau et adresse de son premier élément). Comme un tableau, lorsqu'il n'est pas en unique argument de l'opérateur sizeof ou de l'opérateur & ("adresse de"), est automatiquement converti par le compilateur en l'adresse de son premier élément, l'opérateur & s'utilise donc vraiment très rarement sur un tableau.

    Soit donc p le pointeur qui va pointer sur le premier élément de double_tab. Les éléments de double_tab sont tous des tableaux de 20 char. Le type de p est donc "pointeur sur tableau de 20 char" soit char (*) [20].

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char double_tab[10][20];
    char double_tab_2[12][20];
    char (*p) [20];
     
    p = double_tab; // <=> p = &( double_tab[0] );
    p = double_tab_2; // Correct aussi, tu peux facilement vérifier.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    18
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 18
    Par défaut
    C'est bien un char **, merci pour ce gros rappel !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Manipulation des structures
    Par FstDsi dans le forum Débuter
    Réponses: 7
    Dernier message: 22/07/2009, 19h34
  2. Réponses: 9
    Dernier message: 24/12/2008, 09h21
  3. Atelier de manipulation de structures booléennes
    Par Noutch dans le forum NetBeans
    Réponses: 2
    Dernier message: 13/09/2007, 14h58
  4. fonction c pour manipuler la structure date
    Par thomas_b dans le forum Windows
    Réponses: 4
    Dernier message: 28/07/2004, 16h28

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