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

Langage C++ Discussion :

passage d'un tableau de structure en paramètre d'une fonction


Sujet :

Langage C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 22
    Points : 12
    Points
    12
    Par défaut passage d'un tableau de structure en paramètre d'une fonction
    Bonjour à tous,

    J'ai un petit soucis que je n'arrive pas à résoudre seul.
    J'ai une structure:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        struct S_RailVirtuel
        {
            string idrail_virtuel;
            int position_h;
            int largeur;
            string type;
            string idtablette;
        };
    je veux créer un tableau avec cette structure. Seulement je ne connais pas sa taille lorsque je la créé.
    Je la passe en paramètre d'une fonction:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    S_RailVirtuel * aRailVirtuel=NULL;
    nbRailVirtuel = this->SelectRailVirtuelByIdtablette(&aRailVirtuel,idtablette);
    Voici la déclaration de cette fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int SelectRailVirtuelByIdtablette(S_RailVirtuel ** aRailVirtuel,string idtablette)
    Et une partie de son code:
    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
     
    if((nbEnregistrement = this->mysql_rob->Querry(requeteSQL.c_str(),&result)))
        {
            //création de la structure
            *aRailVirtuel = new S_RailVirtuel [nbEnregistrement] ;
     
            //parcours des lignes
            for(int cpt=0;cpt<nbEnregistrement;cpt++)
            {
                uneLigne = mysql_fetch_row(result);
                aRailVirtuel[cpt] = new  S_RailVirtuel;
                aRailVirtuel[cpt]->idrail_virtuel = uneLigne[0];     //idrail_virtuel
                aRailVirtuel[cpt]->position_h = atoi(uneLigne[1]);   //position_h
                aRailVirtuel[cpt]->largeur = atoi(uneLigne[2]);      //largeur
                aRailVirtuel[cpt]->type = uneLigne[3];               //type de RV
                aRailVirtuel[cpt]->idtablette = uneLigne[4];         //idtablette
            }
        }
        mysql_free_result(result);
        return nbEnregistrement;
    Tout se passe bien dans la fonction SelectRailVirtuelByIdtablette(), seulement lorsque je veux utiliser aRailVirtuel dans la fonction appelant, je ne peux accéder qu'à ma première ligne de mon tableau... dois-je utiliser une liste chaînée? Merci pour vos réponses

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 162
    Points
    17 162
    Par défaut
    Tu es en c++? utilise une classe avec un constructeur, ca ira mieux.

    On est bien d'accord que:
    *aRailVirtuel = new S_RailVirtuel [nbEnregistrement]; définit aRailVirtuel comme l'adresse d'un tableau de S_RailVirtuel.

    aRailVirtuel[cpt] = new S_RailVirtuel;, définit l'élément cpt de aRailVirtuel comme l'adresse d'un nouveau S_RailVirtuel.

    Ce n'est pas du tout la même chose que aRailVirtuel[cpt] = S_RailVirtuel(...); (affectation via operator=(S_RailVirtuel const&) )
    ou encore Ce n'est pas du tout la même chose que (*aRailVirtuel)[cpt] = S_RailVirtuel(...); (affectation du pointé via operator=(S_RailVirtuel const&) )

    aRailVirtuel[cpt] est strictement équivalent à *(cpt+aRailVirtuel), qui du jeu des pointeurs est numériquement égal à "le pointé par l'adresse: cpt*sizeof (S_RailVirtuel*) + aRailVirtuel", c'est à dire cpt pointeur de S_RailVirtuel plus loin que aRailVirtuel.

    (*aRailVirtuel)[cpt] est au contraire équivalent à *(cpt + (*aRailVirtuel) ) c'est à dire "le pointé par l'adresse: cpt*sizeof (S_RailVirtuel) + *aRailVirtuel", c'est à dire cpt S_RailVirtuel plus loin que le pointé de aRailVirtuel

    En fait, ca marcherait mieux, de mon point de vue, avec un vector<*S_RailVirtuel>& en argument.

    De même, atoi devrait être remplacé par un istringstream et son operateur >>.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    Salut,

    Si tu travailles en C++, le plus facile est de travailler avec l'une des collection de la STL...

    L'équivalent d'un tableau d'éléments contigus est std::vectorSinon, ainsi que leternel l'as indiqué, meme les structures peuvent prendre un constructeur, ce qui est de nature à faciliter grandement le travail...

    Ta structure pourrait donc ressembler à quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        struct S_RailVirtuel
        {
            S_RailVirtuel(std::string const & id, int h, int l, std::string const & type,
                         std::string const & type, std::string const & tablette):
             idrail_virtuel(id), position_h(h),largeur(l),type(type),idtablette(tablette)
            { }
            string idrail_virtuel;
            int position_h;
            int largeur;
            string type;
            string idtablette;
        };
    Ton code d'appel pourrait donc ressembler à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    std::vector<S_RailVirtuel> tab;
    /* meme plus besoin de récupérer nbRailVirtuel car tu dispose de l'information 
     * via tab.size() ;)
     */
        SelectRailVirtuelByIdtablette(tab,idtablette);
    avec une fonction SelectRailVirtuelByIdtablette dont le prototype serait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void SelectRailVirtuelByIdtablette(std::vector<S_RailVirtuel> & tab, std::string const & idtablette)
    et un code remplicant le tableau qui prendrait la forme de
    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
     
    if((nbEnregistrement = this->mysql_rob->Querry(requeteSQL.c_str(),&result)))
        {
            //création de la structure
            *aRailVirtuel = new S_RailVirtuel [nbEnregistrement] ;
     
            //parcours des lignes
            for(int cpt=0;cpt<nbEnregistrement;cpt++)
            {
                uneLigne = mysql_fetch_row(result);
                S_RailVirtuel temp( uneLigne[0]  ,   //idrail_virtuel
                                    atoi(uneLigne[1]),   //position_h
                                    atoi(uneLigne[2]),      //largeur
                                    uneLigne[3],               //type de RV
                                    uneLigne[4] );        //idtablette
                tab.push_back(temp);
            }
        }
        mysql_free_result(result);
    C'est d'autant plus vrai que ton dernier code est en réalité faux, vu que l'idée est de faire en sorte que le pointeur aRailVirtuel fournit lors de l'appel prenne l'adresse du premier élément du tableau...

    Ton code corrigé devrait ressembler à quelque chose comme
    if((nbEnregistrement =
    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
    this->mysql_rob->Querry(requeteSQL.c_str(),&result)))
        {
            //création de la structure
            *aRailVirtuel = new S_RailVirtuel [nbEnregistrement] ; //ca, c'est bon
            for(int cpt=0;cpt<nbEnregistrement;cpt++)
            {
                uneLigne = mysql_fetch_row(result);
                /* tu as déjà nbEnregistrement éléments, il ne sert à rien d'en créer 
                 * d'autres ;)
                aRailVirtuel[cpt] = new  S_RailVirtuel;
                * par contre, tu doit accéder à "ce qui est pointé par" ce qui 
                * ce trouve à aRailVirtuel[cpt]
                */
                *aRailVirtuel[cpt]->idrail_virtuel = uneLigne[0];     //idrail_virtuel
                *aRailVirtuel[cpt]->position_h = atoi(uneLigne[1]);   //position_h
                *aRailVirtuel[cpt]->largeur = atoi(uneLigne[2]);      //largeur
                *aRailVirtuel[cpt]->type = uneLigne[3];               //type de RV
                *aRailVirtuel[cpt]->idtablette = uneLigne[4];         //idtablette
            }
        }
        mysql_free_result(result);
        return nbEnregistrement;
    Une autre solution consisterait à transmettre une référence sur un pointeur "simple", car la référence permet de garder la même syntaxe et agit comme un alias pur et simple de l'argument transmis...

    Le prototype de la fonction serait donc poche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int SelectRailVirtuelByIdtablette(S_RailVirtuel *& aRailVirtuel,string idtablette)
    et le code correspondant ressemblerait à
    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
     
    if((nbEnregistrement = this->mysql_rob->Querry(requeteSQL.c_str(),&result)))
        {
            //création de la structure
            aRailVirtuel = new S_RailVirtuel [nbEnregistrement] ;
     
            //parcours des lignes
            for(int cpt=0;cpt<nbEnregistrement;cpt++)
            {
                uneLigne = mysql_fetch_row(result);
                aRailVirtuel[cpt]->idrail_virtuel = uneLigne[0];     //idrail_virtuel
                aRailVirtuel[cpt]->position_h = atoi(uneLigne[1]);   //position_h
                aRailVirtuel[cpt]->largeur = atoi(uneLigne[2]);      //largeur
                aRailVirtuel[cpt]->type = uneLigne[3];               //type de RV
                aRailVirtuel[cpt]->idtablette = uneLigne[4];         //idtablette
            }
        }
        mysql_free_result(result);
        return nbEnregistrement;
    mais la solution préférée est vraiment celle qui utilise std::vector car elle te dégage de la responsabilité de la gestion dynamique de la mémoire
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 22
    Points : 12
    Points
    12
    Par défaut
    Whoua merci a vous deux pour la qualité de vos réponses!
    Par soucis de rapidité, je préfère corriger le code existant par le passage de référence sur pointeur mais effectivement les vecteurs me semblent bien plus appropriés. Ca sera pour la prochaine fois
    Encore merci!

  5. #5
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 195
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 195
    Points : 17 162
    Points
    17 162
    Par défaut
    C'est plus rapide de prendre un vecteur, parce que tu auras plein d'endroit ou ne pas gérer la mémoire.

    Ici, ta fonction alloue le résultat, mais comment es-tu certains que son appeleur la libérera?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 09/03/2014, 23h10
  2. Réponses: 8
    Dernier message: 17/09/2008, 12h11
  3. Réponses: 6
    Dernier message: 24/07/2006, 15h22
  4. structure en paramètre d'une fonction
    Par Tex-Twil dans le forum C
    Réponses: 6
    Dernier message: 29/03/2006, 21h42
  5. Tableau de structures en parametre d'une fonction
    Par -No Comment- dans le forum C
    Réponses: 19
    Dernier message: 29/03/2006, 15h00

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