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 :

Iterator & template


Sujet :

C++

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 17
    Points : 7
    Points
    7
    Par défaut Iterator & template
    Bonjour!

    J'aurais une petite question pratique.

    Lorsque j'utilise un Itérateur de vecteur comme celui ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    IterateurVec<char *> it(Admin);
    
    	do{
    		if((char *)it!=NULL)
    		{
    			if(strncmp((char *)it, loginPass, 61)==0) //Si on a une correspondance
    			{
    				*tu=typeUtilisateur(nomUtilisateur);
    				strncpy(currentUser, nomUtilisateur, 30);
    				return 1;
    			}
    		}
    	}while(++it);
    Lors de l'instance de cet itérateur, suis je dans le vrai si je dis que cet itérateur alloue de la mémoire pour pouvoir stocker Admin(qui ici est un vecteur de char*)?

    Le fait est que lorsque j'utilise cet itérateur, la fonction se passe sans souci et ensuite je dois lancer un menu qui me lache un segmentation fault. Le core dumped survient pendant la ligne de code qui est en gras ci dessous:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    menu::menu(char *opt[], int nbElemC)
    {
    	nbElem=nbElemC;
    	for(int i=0; i<nbElem; i++)
    	{	
    		
    		nom[i]=new char[strlen(opt[i])+1];
    		
    		strcpy(nom[i], opt[i]);
    	}
    }
    Lorsque je n'utilise pas l'itérateur plus haut, le menu se lance sans problème. Mais avec l'utilisation de l'itérateur, le segmentation fault survient.

    Dois-je libérer la mémoire alloué par l'itérateur pour pouvoir lancer mon menu? Si oui, comment faire?

    Merci d'avance.

    Edit: Je sais que le char*, c'est moins beau que le string. Donc d'avance désolé

  2. #2
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Bonjour,
    Est-ce que "vecteur de char" et IterateurVec désigne les std::vector + itérateur de la bibliothèque standard ou des classes persos ?

  3. #3
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Salut

    D'où sortent ces itérateurs, c'est de la STL ? Pardon d'avance, je vais être un peu cru, mais ça c'est n'importe quoi :

    Et on le retrouve ailleurs dans le code. Tu fais un cast C-Style sans aucun check sur un type qui n'est à priori pas convertible dans le type cible. Pour moi ton code à un comportement indéterminé.

    Ce code a du sens :

    Lorsqu'il est utilisé à bon escient. Vas donc un peu lire la doc sur les itérateurs

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 17
    Points : 7
    Points
    7
    Par défaut
    Bon pour préciser, ce sont des templates vecteurs perso. Pas de la bibliothèque standard (obligation scolaire)

    Et la fonction de l'itérateur marche.

    Le problème réside dans le fait que j'ai un segmentation fault dans l'instanciation de mon menu quand j'utilise l'itérateur.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 17
    Points : 7
    Points
    7
    Par défaut
    Je vous met la définition de la class Vecteur et de l'iterateur de Vecteur

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    #include <stdlib.h>
     
    #include <iostream>
     
    #include <string.h>
    #include <stdio.h>
     
     
    #include "Carte.h"
     
     
    template <class T>class IterateurVec;
     
     
    #ifndef DEF_MYVECTOR
     
    #define DEF_MYVECTOR
     
    	template<class T> class MyVector
     
    	{
     
    		protected:
     
    			T *data;
     
    			int *vecPlace;
     
    			int nbrElem;
    			int nbElemPos;
     
    		public:
     
    			MyVector(int n=10);
     
    			~MyVector();
     
     
     
    			void setElement(int indice, const T &valeur);
     
    			bool setElement(const T &valeur);
     
     
     
    			T getElement(int indice)const;
    			int getNbElem()const;
     
    			int getNbElemPos();
     
     
    			void affiche(void)const;
     
     
     
    			bool indiceValide(int indice)const;
     
    			bool estOccupe(int indice)const;
     
    			T retireElement(int indice);
     
     
     
    			void operator+(const T &o);
     
    			friend class IterateurVec<T>;
     
    	};
     
    #endif
     
    #ifndef ITERATEUR_VEC
    #define ITERATEUR_VEC
     
    	template <class T>class IterateurVec
    	{
    		protected:
    			MyVector<T>& pObj;
    			T* pData;
    			int nbElem, pos;
    		public:
    			IterateurVec(MyVector<T>& obj):pObj(obj), pData(obj.data), nbElem(obj.getNbElemPos()), pos(0) {};
     
    			void reset()
    			{ 
    				pData=pObj.data; 
    				nbElem=pObj.getNbElemPos();
    				pos=0;
    			}
     
     
    			int operator++()
    			{
    				if(pos<nbElem)
    				{
    					pData++;
    					pos++;
    					return 1;
    				}
    				else
    					return 0;
    			}
    			operator T()const{return *pData;}
    			T& operator&(){return *pData;}
    	};
     
    #endif

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 17
    Points : 7
    Points
    7
    Par défaut
    Personne ne peut m'aiguiller sur le pourquoi du segmentation fault à cet endroit?

    Le seg fault, c'est bien relié à la mémoire? Vu que le problème survient lorque j'essaye d'allouer un new char...

    Personne n'a une idée de comment contrer cette erreur?

  7. #7
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Le problème survient aussi quand (même ligne) tu tentes d'accéder à opt[i]. Es-tu certain du contenu de ce tableau? De la validité des pointeurs? Que les chaines n'ont pas été désallouées et remplacées par n'importe quoi, avec un \0 terminal manquant?
    As tu essayé d'obtenir + d'info avec un logiciel comme valgrind (ça ne fait pas le café, mais ça aide souvent...)

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 17
    Points : 7
    Points
    7
    Par défaut
    Merci de ta réponse.

    Le truc c'est que je suis parti sur un menu plus simple qui n'utilise pas allocation comme ça j'espère ne plus avoir le problème.

  9. #9
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Dans beaucoup de cas la solution d'un bug d'allocation dynamique est...d'éviter l'allocation dynamique. EDIT: pour plus de clarté je précise: allocation dynamique à la main
    Pour l'avenir (autres TP, ou boulot, sans la contrainte no STL), rappelle-toi que pour les tableaux à longueur variable les std::vector font la gestion de mémoire pour toi ==> rien de tel pour éviter les soucis de gestion dynamique de mémoire

  10. #10
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 17
    Points : 7
    Points
    7
    Par défaut
    Oui de fait mais ils aiment bien NE PAS utiliser les fonctions déja disponible pour tout le monde

    Faut faire avec

  11. #11
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 159
    Points
    3 159
    Par défaut
    Citation Envoyé par fex79 Voir le message
    Personne ne peut m'aiguiller sur le pourquoi du segmentation fault à cet endroit?
    Le seg fault, c'est bien relié à la mémoire? Vu que le problème survient lorque j'essaye d'allouer un new char...
    Personne n'a une idée de comment contrer cette erreur?
    Tu as résolu le problème ? Comment finalement ? En général, un segfault s'identifie assez facilement en lançant un coup de débugger.

    Je persiste à te déconseiller les cast C-Style, c'est se créer des ennuis.

  12. #12
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 17
    Points : 7
    Points
    7
    Par défaut
    Je l'ai pas résolu...

    J'ai juste contourner le problème, au lieu d'utiliser un menu qui demande une allocation de mémoire, j'ai fait un menu plus simple...

    Mais si tu me déconseilles le cast (char*) comment puis-je caster correctement alors dans cette fonction?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    IterateurVec<char *> it(Admin);
     
    	do{
    		if((char *)it!=NULL)
    		{
    			if(strncmp((char *)it, loginPass, 61)==0) //Si on a une correspondance
    			{
    				*tu=typeUtilisateur(nomUtilisateur);
    				strncpy(currentUser, nomUtilisateur, 30);
    				return 1;
    			}
    		}
    	}while(++it);
    Pcq on m'a toujours dit de faire comme ça...

  13. #13
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Je persiste à te déconseiller les cast C-Style, c'est se créer des ennuis.
    Il y est obligé dans ce cas malheureusement.
    C'est vraiment flippant, mais le seul moyen pour accéder aux données pointé par l'itérateur est d'utiliser... l'opérateur de cast fourni avec

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    template <class T>class IterateurVec
    {
    protected:
       T* pData;
    //...
    public:
       operator T() const {return *pData;}
    };
    Citation Envoyé par fex79
    Mais si tu me déconseilles le cast (char*) comment puis-je caster correctement alors dans cette fonction?
    D'habitude, par convention on déréference un itérateur pour accéder à la donnée pointée par l'itérateur (en utilisant la même syntaxe que pour les pointeurs justement pour indiquer le lien de parenté entre le concept d'itérateur et de pointeur)

    Donc un itérateur classique s'utiliserait comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    do{
       if((*it) !=NULL)
       {
          if(strncmp(*it, loginPass, 61)==0) //Si on a une correspondance
         {
        ...
    Bon là, clairement dans ta boite fex79 ils ont fait plus original, car utiliser un opérateur de cast (qui est quand même une feature relativement obscure du langage) pour accéder à un itérateur c'est pas banal

  14. #14
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Décembre 2011
    Messages : 17
    Points : 7
    Points
    7
    Par défaut
    Merci pour ces précisions!

    J'ai quand même l'impressions que ces cast m'apportent quelques soucis.

    Penses tu que mes seg fault seraient dû à ces cast?

  15. #15
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Salut,
    A mon avis, le problème est peut être lié à l'itérateur, au cast, mais cela n'a rien d'évident. Je soupçonne opt[i] de n'être plus valide et de retourner une longueur complètement improbable (ou d'adresser une zone non adressable).
    Le code que tu nous propose 'sent' les problèmes. L'allocation dynamique est très difficile à gérer et rien que de voir des chaines de caractères à la 'C' m'inquiète.

    Puisque tu ne peux utiliser la STL (va dire à ton prof que je pense que c'est complètement débile), à mon avis, commence par :
    => "Réimplémenter" une version simple mais suffisante pour toi de std::string et oublie les const char*. L'important est de bien comprendre le RAII et en particulier la nécessité de bien gérer la copie : cf Gérer ses ressources de manière robuste en C++ par Aurélien Regat-Barrel et Présentation des pointeurs intelligents en C++ par Loïc Joly
    => Idem avec les vecteurs. N'hésite pas à regarder comment la STL fait pour t'en inspirer librement. (au passage ta classe n'implémente pas la copie ce qui peut être très problématique)
    => Cherche à bannir les allocations dynamiques explicites aux profits d'enveloppes RAII dédiées.
    => Suis au plus près le fonctionnement des itérateurs de la STL. Ce sera moins surprenant pour tout le monde.
    En particulier :
    ton opérateur ++ n'est pas usuel.
    tu devrais utiliser * pour accéder à l'élément et non un opérateur de conversion
    reset n'a pas de sens
    Un opérateur == (et !=) devrait exister pour comparer
    On devrait obtenir un itérateur de début et de fin sur un vecteur à partir du vecteur. Le constructeur de l'itérateur en donnant en argument un vecteur n'a pas de sens.

    (tu as trop de membre dans ta classe, les attributs devraient être privés et non protégés)

  16. #16
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    ton opérateur ++ n'est pas usuel.
    tu devrais utiliser * pour accéder à l'élément et non un opérateur de conversion
    reset n'a pas de sens
    Un opérateur == (et !=) devrait exister pour comparer
    On devrait obtenir un itérateur de début et de fin sur un vecteur à partir du vecteur. Le constructeur de l'itérateur en donnant en argument un vecteur n'a pas de sens.
    En fait, son interface fait sens en tant que...reprise approximative de celle des iterateurs java (je le sais, je travaille le plus souvent en java). L'itérateur en java ne représente pas une borne, mais le processus entier d'itération: on l'initialise avec la liste (généralement c'est la classe de collection qui sert de factory, l'itérateur est référencé par l'interface Iterator), il offre des fonctions membres pour avancer dans l'itération, vérifier si elle est finie ou non, et récupérer la valeur.
    Ceci dit, à rome on fait comme les romains, en en C++ comme en C++...question d'efficacité.

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

Discussions similaires

  1. Déclaration d'iterator dans template
    Par artefactman dans le forum C++
    Réponses: 2
    Dernier message: 10/06/2012, 12h36
  2. Iterator et Template
    Par loman02 dans le forum Langage
    Réponses: 5
    Dernier message: 27/03/2008, 16h02
  3. Map::iterator et template
    Par kast_or dans le forum Langage
    Réponses: 3
    Dernier message: 28/11/2006, 20h15
  4. Erreur Gcc, template et iterator
    Par aidos dans le forum Langage
    Réponses: 7
    Dernier message: 14/03/2006, 10h04
  5. Template et iterator.
    Par tibtib17 dans le forum Langage
    Réponses: 5
    Dernier message: 29/07/2005, 15h06

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