Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Qt] Tableaux de pointeurs de structures...

Je ne m'en sors pas...

Sujet résolu
    31 mai 2008 à 21:39:24

    [Edit : J'ai trouvé, je m'impressionne, quelle puissance, j'avais mis un delete sur le pointeur, évidemment il est assez difficile d'accéder à un élément supprimé dans un tableau... merci quand même ^^ ]

    Bonzouar...

    J'fais encore une fois appel à vous, pour des tableaux de pointeurs de structure cette fois, c'est la première fois que je fais un truc pareil, et ça se voit au résultat que ça donne (un joli plantage du programme).
    J'utilise Qt, vector pour les tableaux (j'ai lu le tutoriel de Nanoc sur std::vector).
    Tout compile mais le programme plante (la fameuse "opération non conforme" que mène chaque jour Windows).

    Je vous explique vite fait le but, j'ai une fenêtre qui est censée gérer les fichiers à inclure pour générer le code correspondant. Pour ça, on a un "tableau" (pas vraiment un tableau, mais un layout grille quoi) avec des lignes qui s'ajoutent quand on appuie sur le bouton "Ajouter".
    Chaque ligne contient un CheckBox de sélection (pour pouvoir supprimer les lignes sélectionnées, pas encore opérationnel) + un champ de texte pour le nom, + une ComboBox avec deux choix (interne ou externe, sachant que interne correspond à "fichier.h" et externe à <fichier>)

    Alors le code...

    Le header intéressant :
    #ifndef DEF_INCLUSIONS
    #define DEF_INCLUSIONS
    
    #include <QtGui>
    #include <vector>
    #include "global.h"
    
    
    class Inclusions : public QWidget
    {
        Q_OBJECT  
        
        public:
        Inclusions();
        QString getNom(int numero);
        
        public slots:
        void creernew();
        
        private:
        struct Inclus; //Structure pour les fichiers à inclure.
        std::vector<Inclus*> tableInclus; //Tableau de pointeurs de fichiers à inclure.
        
        QPushButton *ok, *creer, *supprimer;
        QGroupBox *tableau;
        QGridLayout *LAYtableau; //Pour ranger les boutons des différents fichiers
        QGroupBox *boutons;
        QHBoxLayout *LAYboutons; //Pour ranger les boutons de la fenêtre
        QVBoxLayout *LAYvertical; //Pour organiser les deux groupbox
        QLabel *lselect, *lnom, *ltype; //1ere ligne du tableau, indique ce que représentent les widgets.
        int derniereLigne; //Dernière ligne du tableau (0 par défaut)
    };
    
    #endif
    


    Ensuite, le fichier cpp correspondant (j'ai enlevé le constructeur, qui ne concerne pas le problème) :
    #include "inclusions.h"
    #include "global.h"
    
    
    
    struct Inclusions::Inclus
    {
           //Boutons : Chaque fichier a un coche de sélection, une barre de nom et un choix de type.
           QCheckBox *iselect;
           QLineEdit *inom;
           QComboBox *itype; //Avec choix interne/externe. Par défaut externe.
           
           //Variables
           QString nom; //"" par défaut
           bool selected; //False par défaut
           bool interne; //False par défaut
    //Si le fichier est interne, on rajoute .h et on entoure de " "
    //Sinon, il est externe, et on entoure de < >
    };
    
    
    QString Inclusions::getNom(int numero)
    {
            return (tableInclus[numero]->nom);
    }
    
    void Inclusions::creernew()
    {
         Inclus* pointeur = NULL;
         pointeur = new Inclus;
         pointeur->iselect = new QCheckBox;
         pointeur->inom = new QLineEdit;
         pointeur->itype = new QComboBox;
            pointeur->itype->setEditable(false);
            pointeur->itype->addItem("Externe");
            pointeur->itype->addItem("Interne");
         pointeur->nom = "Helloworld"; //J'initialise à "Helloworld" pour tester.
         pointeur->interne = false;
         pointeur->selected = false;
         LAYtableau->addWidget(pointeur->iselect, derniereLigne+1,0);
         LAYtableau->addWidget(pointeur->inom, derniereLigne+1,1);
         LAYtableau->addWidget(pointeur->itype, derniereLigne+1,2);
         
         tableInclus.push_back(pointeur);
         delete pointeur;
    /* J'avais essayé en ajoutant directement un pointeur dans le tableau et en le modifiant, mais ça ne compilait pas
         tableInclus[derniereLigne]->nom = "";
         tableInclus[derniereLigne]->interne = false;
         tableInclus[derniereLigne]->selected = false;
         
         tableInclus[derniereLigne]->iselect = new QCheckBox;
         tableInclus[derniereLigne]->inom = new QLineEdit;
         tableInclus[derniereLigne]->itype = new QComboBox;
             tableInclus[derniereLigne]->itype->setEditable(false); //currentText() pour get.
             tableInclus[derniereLigne]->itype->addItem("Externe");
             tableInclus[derniereLigne]->itype->addItem("Interne");
         
         LAYtableau->addWidget(tableInclus[derniereLigne]->iselect, derniereLigne+1, 0);
         LAYtableau->addWidget(tableInclus[derniereLigne]->inom, derniereLigne+1, 1);
         LAYtableau->addWidget(tableInclus[derniereLigne]->itype, derniereLigne+1, 2);
    */
         derniereLigne ++;
    }
    


    Tout ça, ça marche à priori, puisque les lignes se rajoutent comme prévu, même si j'ai bien peur que le tableau ne prenne pas le pointeur correctement, puisque sans détruire le pointeur et sans le tableau, on obtient le même résultat.

    Je crée dans un autre fichier (qui n'a aucun rapport avec le problème) l'objet FInclude de classe Inclusions.
    Le problème se pose quand je teste dans ce fichier le code suivant (codecpp est un QString):
    codecpp += FInclude.getNom(1);
    

    (C'est juste un code de test hein, je fais en sorte que le tableau contienne assez d'éléments pour pouvoir utiliser la case 1)
    Normalement, ça devrait ajouter le nom ("Helloworld") dans codecpp, mais non, ça plante :euh:
    En même temps je manque d'expérience avec les pointeurs et les tableaux, je gère sûrement mal ça quelque part, mais je ne suis pas capable de comprendre où ça cloche...

    Si y'avait éventuellement moyen de faire autrement qu'avec un tableau de pointeurs de structures, ça m'arrangerait, c'est un peu trop complexe pour moi, cette histoire ! ^^

    Si vous voulez compiler pour constater, essayer des choses, je donne le code complet en secret :

    main.cpp :
    #include <QtGui>
    #include "fenetre.h"
    #include "dialogue.h"
    #include "inclusions.h"
    
    
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        Fenetre principale;
        principale.show();
        
        return app.exec();
    }
    


    fenetre.h :
    /**************************************
     ** Fenêtre principale du générateur **
     **************************************/
     
    #ifndef DEF_FENETRE
    #define DEF_FENETRE
    
    #include <QtGui>
    #include "inclusions.h"
    
    
    class Fenetre : public QWidget
    {
          Q_OBJECT
          
          public:
          Fenetre();
          
          public slots:
          void generer();
          void menuIn();
          
          private:
          Inclusions FInclude;
          //Toutes sortes de choses widgetesques
          QGroupBox *m_defClasse, *m_options, *m_commentaires, *m_boutons;
          QPushButton *m_quitter, *m_generer, *m_menuinclude, *m_menuattributs;
          QCheckBox *m_inclusions, *m_constructeur, *m_destructeur;
          QLabel *m_nom, *m_classeMere, *m_auteur, *m_date, *m_description;
          QDateEdit *m_idate;
          QLineEdit *m_iauteur, *m_inom, *m_imere;
          QTextEdit *m_idescription;
          
          //Layouts
          QVBoxLayout *m_vertical, *m_LAYoptions;
          QHBoxLayout *m_horizontal;
          QGridLayout *m_LAYdef, *m_LAYcommentaires;
    };
    
    #endif
    


    fenetre.cpp :
    #include "fenetre.h"
    #include "dialogue.h"
    #include "inclusions.h"
    #include "global.h"
    
    
    Fenetre::Fenetre() : QWidget()
    {    
         //PushButtons
         m_quitter = new QPushButton("Quitter");
         m_generer = new QPushButton("Générer !");
         m_menuinclude = new QPushButton("Inclusions...");
         m_menuattributs = new QPushButton("Attributs...");
         
         //CheckBoxes
         m_inclusions = new QCheckBox("Protéger contre les &inclusions multiples");
         m_constructeur = new QCheckBox("Générer un &constructeur par défaut");
         m_destructeur = new QCheckBox("Générer un &destructeur par défaut");
         
         //Labels
         m_nom = new QLabel("Nom de la classe :");
         m_classeMere = new QLabel("Classe mère :");
         m_auteur = new QLabel("Auteur :");
         m_date = new QLabel("Date de création :");
         m_description = new QLabel("Description :");
         
         //Inputs
         m_idate = new QDateEdit;
         m_iauteur = new QLineEdit;
         m_inom = new QLineEdit;
         m_imere = new QLineEdit;
         m_idescription = new QTextEdit;
         m_idescription->setFixedSize(150,60);
         
         //GroupBoxes
         m_boutons = new QGroupBox;
            m_boutons->setFlat(true);
            m_horizontal = new QHBoxLayout;
               m_horizontal->addWidget(m_generer);
               m_horizontal->addWidget(m_quitter);
               m_horizontal->addWidget(m_menuinclude);
               m_horizontal->addWidget(m_menuattributs);
            m_boutons->setLayout(m_horizontal);
         
         m_defClasse = new QGroupBox("Définition de la classe");
            m_LAYdef = new QGridLayout;
               m_LAYdef->addWidget(m_nom, 0, 0);
               m_LAYdef->addWidget(m_classeMere, 1, 0);
               m_LAYdef->addWidget(m_inom, 0, 1, 1, 3); //3 cases de largeur
               m_LAYdef->addWidget(m_imere, 1, 1, 1, 3); //Idem
            m_defClasse->setLayout(m_LAYdef); //C'est dans la boîte !
         
         m_options = new QGroupBox("Options");
            m_LAYoptions = new QVBoxLayout;
               m_LAYoptions->addWidget(m_inclusions);
               m_LAYoptions->addWidget(m_constructeur);
               m_LAYoptions->addWidget(m_destructeur);
            m_options->setLayout(m_LAYoptions); //C'est dans la boîte !
               
         m_commentaires = new QGroupBox("Commentaires");
            m_commentaires->setCheckable(true);
            m_LAYcommentaires = new QGridLayout;
               m_LAYcommentaires->addWidget(m_auteur, 0, 0);
               m_LAYcommentaires->addWidget(m_date, 1, 0);
               m_LAYcommentaires->addWidget(m_description, 2, 0);
               m_LAYcommentaires->addWidget(m_iauteur, 0, 1, 1, 3); //Largeur = 3
               m_LAYcommentaires->addWidget(m_idate, 1, 1, 1, 3); //Idem
               m_LAYcommentaires->addWidget(m_idescription, 2, 1, 1, 3); //Itou
            m_commentaires->setLayout(m_LAYcommentaires); //C'est dans la boîîîte !
         
         //Layout vertical principal
         m_vertical = new QVBoxLayout(this);
            m_vertical->addWidget(m_defClasse);
            m_vertical->addWidget(m_options);
            m_vertical->addWidget(m_commentaires);
            m_vertical->addWidget(m_boutons);
            
            
         //Connexions signal/slot
         QObject::connect(m_quitter, SIGNAL(clicked()), qApp, SLOT(quit()));
         QObject::connect(m_generer, SIGNAL(clicked()), this, SLOT(generer()));
         QObject::connect(m_menuinclude, SIGNAL(clicked()), this, SLOT(menuIn()));
    }
    
    //Slot, gère les erreurs de génération, la génération du code, l'ouverture de la fenêtre de code.
    void Fenetre::generer()
    {
         bool dejafait = false;
         bool touvabien = true; //Change en false si une erreur intervient (on ne génèrera alors pas)
         QString codeh = "", codecpp = "";
         
         if ((m_inom->text().isEmpty()) == true) //Si la classe n'a pas de nom
         {
            touvabien = false;
            QMessageBox::warning(this, "Erreur", "Donnez un nom à la classe");
         }
         
         if (touvabien)
         {//On génère le code (utiliser bool isChecked() pour les cases cochables, text() pour les inputs)
            
            //On génère les commentaires
            if (m_commentaires->isChecked() == true) //Si on ajoute des commentaires
            {
                codeh += "/* \n";
                if ((m_iauteur->text().isEmpty()) == false) //Si un auteur est spécifié
                  codeh += "Auteur : " + m_iauteur->text() + "\n";
                codeh += "Date de création : " + (m_idate->date()).toString() + "\n";
                if ((m_idescription->toPlainText().isEmpty()) == false) //Si une description est donnée
                  codeh += "Description :\n" + m_idescription->toPlainText() + "\n";
                codeh += "*/\n\n";
            }
            
            //On génère ensuite la protection contre les inclusions multiples
            if (m_inclusions->isChecked() == true) //Si la case est cochée, bien sûr
            {
                codeh += "#ifndef DEF_" + (m_inom->text().toUpper()) + "\n";
                codeh += "#define DEF_" + (m_inom->text().toUpper()) + "\n\n";
            }
            
            //On génère la classe proprement dite
            codeh += "class " + m_inom->text(); //class [Nom]
            if ((m_imere->text().isEmpty()) == false) //Si une classe mère est spécifiée
               codeh += " : public " + m_imere->text();
            codeh += "\n{\n"; //Ici, on est après l'accolade d'ouverture de la classe
            
            codeh += "    public:\n";
            if ((m_constructeur->isChecked() == true)) //Si on veut un constructeur
               codeh += "    " + m_inom->text() + "();\n";
            if ((m_destructeur->isChecked() == true)) //Si on veut un destructeur
               codeh += "    ~" + m_inom->text() + "();\n";
            codeh += "\n\n";
            codeh += "    protected:\n\n\n";
            codeh += "    private:\n\n\n";
            codeh += "};";
            if ((m_inclusions->isChecked() == true)) //Si on a une protection, on fait un endif
               codeh += "\n\n#endif";
            
            //Cpp
            codecpp += "#include \"" + m_inom->text() + ".h\"\n\n\n";
            if ((m_constructeur->isChecked() == true)){
               codecpp += m_inom->text() + "::" + m_inom->text() + "()";
               if ((m_imere->text().isEmpty()) == false)
                  codecpp += " : " + m_imere->text() + "()";
               codecpp += "\n{\n\n}";}
            codecpp += FInclude.getNom(1); //Mettre cette ligne en commentaire pour que le programme marche
            
            static Dialogue resultat(codeh, codecpp);
            resultat.modifier(codeh, codecpp);
            resultat.show();
            
            dejafait = true;
         }//Fin de la génération
    }
    
    void Fenetre::menuIn()
    {
         FInclude.show();
    }
    


    dialogue.h :
    /*********************************
     ** Fenêtre secondaire de texte **
     *********************************/
     
    #ifndef DEF_DIALOGUE
    #define DEF_DIALOGUE
    
    #include <QtGui>
    
    
    class Dialogue : public QWidget
    {
          public:
          Dialogue(QString codeh, QString codecpp); //Constructeur
          void modifier(QString codeh, QString codecpp);
          
          private:
          QWidget *m_pageh, *m_pagecpp;
          QTabWidget *m_onglets;
          QPushButton *m_fermerh, *m_fermercpp, *m_copierh, *m_copiercpp;
          QTextEdit *m_codeh, *m_codecpp;
          QGridLayout *m_layouth, *m_layoutcpp;
    };
    
    #endif
    


    dialogue.cpp :
    #include "dialogue.h"
    #include "fenetre.h"
    
    
    Dialogue::Dialogue(QString codeh, QString codecpp) : QWidget()
    {
       m_onglets = new QTabWidget(this);
       m_onglets->setFixedSize(250, 600);
       
       m_fermerh = new QPushButton("Fermer");
       m_fermercpp = new QPushButton("Fermer");
       m_pageh = new QWidget;
       m_pagecpp = new QWidget;
       
       //Header
       m_copierh = new QPushButton("Copier");
       
       m_codeh = new QTextEdit;
       m_codeh->setFixedSize(220, 510);
       m_codeh->setText(codeh);
       m_codeh->setReadOnly(true);
       
       m_layouth = new QGridLayout;
          m_layouth->addWidget(m_codeh, 0, 0, 1, 2);
          m_layouth->addWidget(m_copierh, 1, 0);
          m_layouth->addWidget(m_fermerh, 1, 1);
       
       m_pageh->setLayout(m_layouth);
       
       //Cpp
       m_copiercpp = new QPushButton("Copier");
       
       m_codecpp = new QTextEdit;
       m_codecpp->setFixedSize(220, 510);
       m_codecpp->setText(codecpp);
       m_codecpp->setReadOnly(true);
       
       m_layoutcpp = new QGridLayout;
          m_layoutcpp->addWidget(m_codecpp, 0, 0, 1, 2);
          m_layoutcpp->addWidget(m_copiercpp, 1, 0);
          m_layoutcpp->addWidget(m_fermercpp, 1, 1);
       
       m_pagecpp->setLayout(m_layoutcpp);
       
       m_onglets->addTab(m_pageh, "Header");
       m_onglets->addTab(m_pagecpp, "Cpp");
       
       //Signaux
       QObject::connect(m_fermerh, SIGNAL(clicked()), this, SLOT(close()));
       QObject::connect(m_fermercpp, SIGNAL(clicked()), this, SLOT(close()));
       QObject::connect(m_copierh, SIGNAL(clicked()), m_codeh, SLOT(selectAll()));
       QObject::connect(m_copierh, SIGNAL(clicked()), m_codeh, SLOT(copy()));
       QObject::connect(m_copiercpp, SIGNAL(clicked()), m_codecpp, SLOT(selectAll()));
       QObject::connect(m_copiercpp, SIGNAL(clicked()), m_codecpp, SLOT(copy()));
    }
    
    void Dialogue::modifier(QString codeh, QString codecpp)
    {
         m_codeh->clear();
         m_codeh->setText(codeh);
         m_codeh->update();
         
         m_codecpp->clear();
         m_codecpp->setText(codecpp);
         m_codecpp->update();
    }
    


    inclusions.h :
    /* 
    ********************************
    ** Gère la liste d'inclusions **
    ********************************
    */
    
    #ifndef DEF_INCLUSIONS
    #define DEF_INCLUSIONS
    
    #include <QtGui>
    #include <vector>
    #include "global.h"
    
    
    class Inclusions : public QWidget
    {
        Q_OBJECT  
        
        public:
        Inclusions();
        bool getType(int numero);
        QString getNom(int numero);
        
        public slots:
        void creernew();
        //void supprimerdel();
        
        private:
        struct Inclus; //Structure pour les fichiers à inclure.
        std::vector<Inclus*> tableInclus; //Tableau de pointeurs de fichiers à inclure. On utilisera new.
        
        QPushButton *ok, *creer, *supprimer;
        QGroupBox *tableau;
        QGridLayout *LAYtableau; //Pour ranger les boutons des différents fichiers
        QGroupBox *boutons;
        QHBoxLayout *LAYboutons; //Pour ranger les boutons de la fenêtre
        QVBoxLayout *LAYvertical; //Pour organiser les deux groupbox
        QLabel *lselect, *lnom, *ltype; //1ere ligne du tableau, indique ce que représentent les widgets.
        int derniereLigne; //Dernière ligne du tableau (0 par défaut)
    };
    
    #endif
    


    inclusions.cpp
    #include "inclusions.h"
    #include "global.h"
    
    
    
    struct Inclusions::Inclus
    {
           //Boutons : Chaque fichier a un coche de sélection, une barre de nom et un choix de type.
           QCheckBox *iselect;
           QLineEdit *inom;
           QComboBox *itype; //Avec choix interne/externe. Par défaut externe.
           
           //Variables
           QString nom; //"" par défaut
           bool selected; //False par défaut
           bool interne; //False par défaut
    //Si le fichier est interne, on rajoute .h et on entoure de " "
    //Sinon, il est externe, et on entoure de < >
    };
    
    
    QString Inclusions::getNom(int numero)
    {
            return tableInclus[numero]->nom;
    }
    
    Inclusions::Inclusions() : QWidget()
    {
        derniereLigne = 0;
        ok = new QPushButton("Terminer");
        creer = new QPushButton("Ajouter");
        supprimer = new QPushButton("Supprimer");
        lselect = new QLabel("Choix");
        lnom = new QLabel("Nom du fichier");
        ltype = new QLabel("Type");
        
        boutons = new QGroupBox;
           LAYboutons = new QHBoxLayout;
              LAYboutons->addWidget(ok);
              LAYboutons->addWidget(creer);
              LAYboutons->addWidget(supprimer);
           boutons->setLayout(LAYboutons);
           
        tableau = new QGroupBox;
           LAYtableau = new QGridLayout;
              LAYtableau->addWidget(lselect, 0, 0);
              LAYtableau->addWidget(lnom, 0, 1);
              LAYtableau->addWidget(ltype, 0, 2);
           tableau->setLayout(LAYtableau);
        
        LAYvertical = new QVBoxLayout;
           LAYvertical->addWidget(tableau);
           LAYvertical->addWidget(boutons);
        this->setLayout(LAYvertical);
        
        QObject::connect(ok, SIGNAL(clicked()), this, SLOT(close()));
        QObject::connect(creer, SIGNAL(clicked()), this, SLOT(creernew()));
        //QObject::connect(supprimer, SIGNAL(clicked()), this, SLOT(supprimerdel()));
    }
    
    void Inclusions::creernew()
    {
         Inclus* pointeur = NULL;
         pointeur = new Inclus;
         pointeur->iselect = new QCheckBox;
         pointeur->inom = new QLineEdit;
         pointeur->itype = new QComboBox;
            pointeur->itype->setEditable(false);
            pointeur->itype->addItem("Externe");
            pointeur->itype->addItem("Interne");
         pointeur->nom = "Ninouim";
         pointeur->interne = false;
         pointeur->selected = false;
         LAYtableau->addWidget(pointeur->iselect, derniereLigne+1,0);
         LAYtableau->addWidget(pointeur->inom, derniereLigne+1,1);
         LAYtableau->addWidget(pointeur->itype, derniereLigne+1,2);
         
         tableInclus.push_back(pointeur);
         delete pointeur;
         /*
         tableInclus[derniereLigne]->nom = "";
         tableInclus[derniereLigne]->interne = false;
         tableInclus[derniereLigne]->selected = false;
         
         tableInclus[derniereLigne]->iselect = new QCheckBox;
         tableInclus[derniereLigne]->inom = new QLineEdit;
         tableInclus[derniereLigne]->itype = new QComboBox;
             tableInclus[derniereLigne]->itype->setEditable(false); //currentText() pour get.
             tableInclus[derniereLigne]->itype->addItem("Externe");
             tableInclus[derniereLigne]->itype->addItem("Interne");
         
         LAYtableau->addWidget(tableInclus[derniereLigne]->iselect, derniereLigne+1, 0);
         LAYtableau->addWidget(tableInclus[derniereLigne]->inom, derniereLigne+1, 1);
         LAYtableau->addWidget(tableInclus[derniereLigne]->itype, derniereLigne+1, 2);
         */
         derniereLigne ++;
    }
    



    Voilà, j'ai sûrement mal compris quelque chose, le problème est peut être évident, mais je ne le vois pas, merci d'avance :)
    • Partager sur Facebook
    • Partager sur Twitter

    [Qt] Tableaux de pointeurs de structures...

    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
    • Editeur
    • Markdown