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 :

Problème avec le conteneur vector


Sujet :

C++

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2011
    Messages : 11
    Points : 7
    Points
    7
    Par défaut Problème avec le conteneur vector
    Bonsoir, je désire créé un petit programme en C++ permettant de gérer des matrices mathématiques dans le but de le fournir à mon IUT pour qu'on puisse éventuellement en faire une sorte de dossier pédagogique.

    Les classes Matrix et Lignes ont été implémentées et fonctionnent parfaitement.

    Le problème intervient dans la partie user. En effet pour contenir toutes les matrices que l'user aura créé durant la session, j'utilise un vecteur (à titre pédagogique encore une fois), mais le soucis vient de la fonction push_back(), elle semble modifier les attributs des matrices que je lui envoie, pas toujours, mais souvent :

    Exemple :

    Code C++ : 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
    vector<Matrix> vecMatrices;
     
    Matrix mat(1,1); // Création d'une matrice de 1 ligne et de 1 colonne.
    Matrix mat1(1,1);
    Matrix mat2(1,1);
     
    mat.setLigne(1, "1"); // A la ligne 1, la matrice a pour valeur : 1.
    mat1.setLigne(1, "2"); // A la ligne 1, la matrice a pour valeur : 2.
    mat2.setLigne(1, "3");
     
    mat.afficher();
    mat1.afficher();
    mat2.afficher();
     
    cout << "A" << endl; // Cette lettre permettra de bien distinguer les affichages.
     
    vecMatrices.push_back(mat); // Ajout des matrices.
    vecMatrices.push_back(mat1);
    vecMatrices.push_back(mat2);
     
    for(vector<Matrix>::const_iterator it = vecMatrices.begin() ; it < vecMatrices.end() ; it++)
    {
        (*it).afficher();
    }
     
    cout << "B" << endl; // Idem

    Affichage console :

    Code Console : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    1
     
    2
     
    3
     
    A
     
    1.49838e-038
     
    1.49838e-038
     
    3
     
    B

    Voilà, on peut émettre une hypothèse comme quoi ce seraient les constructeurs de copies des classes qui seraient responsables de ce problème, je vous les donne au cas où le problème viendrait de là :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Matrix::Matrix(const Matrix &matrix)
    {
        m_lignes = new Ligne[matrix.m_nbLignes];
        m_nbChiffresColonnes = new unsigned int[matrix.m_nbColonnes];
     
        m_nbLignes = matrix.m_nbLignes;
        m_nbColonnes = matrix.m_nbColonnes;
     
        for(unsigned int i = 0 ; i < m_nbLignes ; i++) m_lignes[i] = matrix.m_lignes[i];
        for(unsigned int i = 0 ; i < m_nbColonnes ; i++) m_nbChiffresColonnes[i] = matrix.m_nbChiffresColonnes[i];
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Ligne::Ligne(const Ligne &L) : m_nbValeur(L.m_nbValeur)
    {
        m_cellules = new float[m_nbValeur];
     
        for(unsigned int i = 0 ; i < m_nbValeur ; i++)
        {
            m_cellules[i] = L.m_cellules[i];
            cout << "1 " << m_cellules[i];
            cout << "2 " << L.m_cellules[i];
        }
    }
    Merci beaucoup !!!

    EDIT :

    Cela me semblerait étonnant que cela soit dû aux constructeur de copies, je viens de faire un test et pourtant cela fonctionne très bien :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    vector<Matrix> vecMatrices;
     
    Matrix mat(3,3);
     
    mat.setLigne(1, "1,2,3");
    mat.setLigne(2, "-1,-3,-5");
    mat.setLigne(3, "1.2,0.66,-0.2");
     
    Matrix mat1(mat);
     
    mat.afficher();
    mat1.afficher();
    Affichage console :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    1    2      3
    -1  -3    -5
    1.2 0.66 -0.2
     
    1    2      3
    -1  -3    -5
    1.2 0.66 -0.2

  2. #2
    Membre éclairé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    426
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 426
    Points : 827
    Points
    827
    Par défaut
    Boujours,

    1)Es-tu certain que ça ne vient pas de la fonction 'afficher()' ( tu ne donne pas le code de celle-ci )?

    2)Pourquoi ne pas utiliser 'vector<Matrix*> vecMatrices;' plutôt que 'vector<Matrix> vecMatrices;'. Les fait d'envoyer des objets de taille différente dans un 'vector' ne risque-t-il pas poser problème?
    La, http://www.cplusplus.com/reference/stl/vector/ ils disent :
    Vector containers are implemented as dynamic arrays; Just as regular arrays, vector containers have their elements stored in contiguous storage locations, which means that their elements can be accessed not only using iterators but also using offsets on regular pointers to elements.
    Bye

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2011
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    Ta deuxième remarque me semble être la solution !

    C'est impossible que la fonction afficher() soit responsable, voici son prototype :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void afficher() const; // <--- La méthode de modifie pas l'objet.
    vector<Matrix*> est un vecteur contenant des adresses de Matrix je suppose, de cette manière, plus de problème avec la taille ?

  4. #4
    Membre éclairé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    426
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 426
    Points : 827
    Points
    827
    Par défaut
    Oui, et en plus, il me semble plus élégant d'utiliser une vector de pointeur plutôt qu'un vector de matrices de tailles variables.
    Tiens moi au courant si ça marche...
    Bon code.

  5. #5
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2011
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    OK, je vais essayer cela tout de suite, et je suis certain que c'est la solution.
    Merci beaucoup, t'es peut-être pas un expert, mais tu as su me répondre ^^ !

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2011
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    Hum... c'est bien ce qu'il me semblait, il faut que je trouve une autre façon de faire du coup.
    Vu que mon vecteur pointe sur des matrices, cette commande devient problématique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    push_back(&creerMatrice(nbMatrices));
    La fonction creerMatrice() retourne une matrice construite (donc &creerMatrice() retourne son adresse). Cela fonctionne mais du coup le destructeur est instantanément appelé et donc mon vecteur ne pointe plus vers la nouvelle matrice. Comment faire ?

    Voici la fonction creerMatrice() au cas où :

    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
    Matrix creerMatrice(const int n)
    {
        int nbLigne;
        int nbColonne;
        cout << endl;
        cout << " Matrice " << n+1 << " :" <<  endl;
        cout << " Nombre de lignes : "; cin >> nbLigne; cin.ignore();
        cout << " Nombre de colonnes : "; cin >> nbColonne; cin.ignore();
     
        Matrix matriceRes(nbLigne, nbColonne);
     
        for(int i = 1 ; i <= nbLigne ; i++)
        {
            string valeurs;
            cout << " Entrez les valeurs de la ligne " << i << " sous la forme 'x,y,z' : "; getline(cin, valeurs);
            matriceRes.setLigne(i, valeurs);
        }
     
        return matriceRes;
    }

  7. #7
    Membre éclairé

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    426
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 426
    Points : 827
    Points
    827
    Par défaut
    Moi je tenterai quelque chose comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void creerMatrice(const int n, Matrix& m)
    { ... }
    que tu utilise comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Matrix matrice = new Matrix(1, 1);
    ...
    creerMatrice ( nbr, matrice );
    ...
    Tu fourni une matrice à cette fonction en argument, et elle est modifiée par la fonction ( modif du nombre de lignes, de colonnes, des valeurs ). Comme elle est transmise par référence, elle n'est pas détruite à la fin de la fonction...

  8. #8
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    A vu de nez, sans avoir rien lu, je dirais que le problème est peut-être dans l'opérateur= : http://cpp.developpez.com/faq/cpp/in...orme_canonique

    Citation Envoyé par bertry Voir le message
    2)Pourquoi ne pas utiliser 'vector<Matrix*> vecMatrices;' plutôt que 'vector<Matrix> vecMatrices;'. Les fait d'envoyer des objets de taille différente dans un 'vector' ne risque-t-il pas poser problème?
    Ca dépend de ce qu'on appelle poser problème. Le code qui gère un vector de Matrix est correct. Deux objets Matrix différents ont la même taille (au sens sizeof), quelle que soit la taille de la matrice.

    Le problème potentiel vient plutôt des performances : Pour mettre des valeurs dans un vector, ou pour augmenter sa taille, ce dernier doit les copier. Or un objet Matrice est lourd à copier (en C++0x, qui gère la notion de déplacement, ce problème peut disparaître, mais il faut définir d'autres fonctions pour la matrice, un constructeur de déplacement et un opérateur d'affectation par déplacement).

    Dont il peut à cause de ça être intéressant de mettre autre chose que des Matrices directement. Les pointeurs nus sur les matrices peuvent poser les problèmes liés aux pointeurs nus. Mais des pointeurs intelligents peuvent résoudre ces problèmes.

    Par contre, je n'ai pas encore compris à quoi pourrait servir ce vector<Matrice>...
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  9. #9
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2011
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    Le soucis, c'est que l'user peut créer autant de matrices qu'il le veut, donc à chaque fois que l'on créera une matrice, en faite ça modifiera la dernière.

    Une autre solution serait de stocker les matrices dans un fichier (donc adieu le vecteur) et quand je veux afficher les matrices, je parcoure le contenu du fichier. Cela me permettrait en plus de pouvoir sauvegarder une session, et permettre à l'user de revenir sur son travail sans recréer les matrices. Quand penses-tu ?

    Sinon, utiliser un autre conteneur un peu plus puissant ?

    Jolyloic : Avait pas vu ton post fort intéressant (bien que je n'aie pas tout compris ^^). Je ne sais pas ce que c'est qu'un opérateur d'affectation de déplacement et cela n'est pas au programme actuellement donc vaut mieux oublier cette idée (d'autant plus que l'intérêt semble être une question de performance, donc c'est pas spécialement nécessaire pour le moment).
    Le vecteur de Matrix permettrait de contenir les matrices que l'user crée durant le programme, il peut ainsi traiter celle qu'il veut, ou par exemple traiter deux matrices ensemble (+,-,*, par exemple).
    Je vais tester l'opérateur d'affectation, c'est peut être lui qui coince

  10. #10
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Je vais reposer ma question : A quoi sert de garder en mémoire toutes les matrices que l'utilisateur aura pu créer ? S'il souhaite en garder quelques unes, grand bien lui fasse, à lui de gérer ça. Mais pourquoi vouloir imposer ça, à part pour faire exploser la mémoire même pour le programme utilisateur le plus simple ?

    Au fait, l'operator=, ça donne quoi (histoire de savoir si j'avais vu juste) ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  11. #11
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2011
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2011
    Messages : 11
    Points : 7
    Points
    7
    Par défaut
    Désolé... mais ... tu avais vu juste !!!
    C'était effectivement l'opérateur d'affectation (non pas de Matrix mais) de Ligne qui faisait tout foireter .

    Je suis super content, merci beaucoup à vous deux !

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

Discussions similaires

  1. [ogre] Problème avec un conteneur vector
    Par Invité dans le forum C++
    Réponses: 6
    Dernier message: 05/11/2011, 22h49
  2. problème avec les conteneurs STL
    Par burak dans le forum SL & STL
    Réponses: 7
    Dernier message: 19/04/2009, 17h43
  3. Problème avec la classe Vector.
    Par kaelem dans le forum Langage
    Réponses: 10
    Dernier message: 28/12/2006, 09h19
  4. [gsoap] Problème avec les std::vector
    Par LePhasme dans le forum SL & STL
    Réponses: 1
    Dernier message: 25/04/2006, 11h46

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