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

SL & STL C++ Discussion :

[STL] Personnalisation avec find_if


Sujet :

SL & STL C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 21
    Par défaut [STL] Personnalisation avec find_if
    Bonjour,

    Voila je cherche à utiliser l'algorithme find_if de la STL pour pouvoir rechercher un objet dans un vecteur selon mes propres critères, ce vecteur contenant un type complexe, tandis que pour ma recherche seul un membre est évalué.

    J'ai trouvé un exemple sur internet, du style :
    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
    // returns true if n is an odd number
    int IsOdd( int n)
    {
        return n % 2 ;
    }
     
    void main()
    {
        const int ARRAY_SIZE = 8 ;
        int IntArray[ARRAY_SIZE] = { 1, 2, 3, 4, 4, 5, 6, 7 } ;
        int *location ;   // stores the position of the first
                          // element that is an odd number
        int i ;
     
            // print content of IntArray
        cout << "IntArray { " ;
        for(i = 0; i < ARRAY_SIZE; i++)
            cout << IntArray[i] << ", " ;
        cout << " }" << endl ;
     
        // Find the first element in the range [first, last -1 ]
        // that is an odd number
        location = find_if(IntArray, IntArray + ARRAY_SIZE, IsOdd) ;
     
        //print the location of the first element
        // that is an odd number
        if (location != IntArray + ARRAY_SIZE)  // first odd element found
            cout << "First odd element " << *location
                 << " is at location " << location - IntArray << endl;
        else         // no odd numbers in the range
            cout << "The sequence does not contain any odd numbers"
                 << endl ;
        }
    }
    Mais mon problème est que le critère de recherche est variable (en fait, je compare un des membres des objets contenus dans le vecteur à une valeur). Pour être plus précis, j'ai une classe account, avec parmis ses membres un "string username". Je veux donc une fonction qui trouve dans le vecteur l'objet account dont le nom d'utilisateur est "jojo" ou encore "lovecpp".
    J'ai donc essayé de faire une classe et de bidouiller en utilisant l'opérateur () :
    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
     
             /**
             *classe account_finder
             *classe permettant la recherche d'un compte particulier dans la liste.
             *Est passée en tant que predicate à l'algorithme find_if
             */
            class account_finder
            {
                protected:
                    string nom_recherche; //le nom d'utilisateur à rechercher
     
                public:
                    explicit account_finder(const string& nom_recherche);
     
                    int operator()(const account& autre) const;
     
                    virtual ~account_finder();
            };
     
            account_finder::account_finder(const string& nom_recherche)
            {
                this->nom_recherche = nom_recherche;
            }
     
            int account_finder::operator()(const account& autre) const
            {
                cout << "account_finder() appele avec " << nom_recherche << " _compare_to_ " << autre.get_username() << endl;
                return nom_recherche.compare(autre.get_username());
            }
     
            account_finder::~account_finder()
            {
            }
    où account est une classe avec dans ses membres string username

    et j'appelle l'algorithme find_if comme ce qui suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<account>::iterator compte = find_if(comptes.begin(), comptes.end(), account_finder(nom_utilisateur));
    où comptes est mon vecteur : vector<account>

    Or le cout << "account_finder().." ne s'affiche même pas, et compte prend la valeur comptes.end(). Quand j'affiche la taille du vecteur, elle est bien supérieur à 0...

    Je suis obligé d'utiliser une fonction classique ? Ou alors c'est le type du paramètre (const account&) de mon opérateur() qui ne va pas ?
    Merci pour vos réponses.

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Il n'y a pas l'air d'y avoir d'erreur. Tu ne peux pas faire une exécution pas à pas pour voir pourquoi la recherche ne passe par là où elle devrait ?

  3. #3
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Il suffit de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct id_accounts
    {
      bool operator() (const account& first, const account& second)
      { 
        return first.username == second.username;
      }
    };
     
    // ...
     
    it = std::find_if(v.begin(), v.end(), std::bind2nd(id_accounts(),"username cherché"));
    Pour fixer un argument, tu peux utiliser std::bind2nd ou std::bind1st, mais Boost.Bind est plus poussé.

    Cependant, aucune erreur apparente dans ton code.

  4. #4
    Membre confirmé Avatar de b Oo
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 179
    Par défaut
    Salut,
    personnellement je retournerai un booléen plutôt qu'un int même si ça ne change rien dans l'exécution du programme. Cela permet juste de mieux comprendre ce que fait une fonction.

    Alp ton exemple montre la partie moins intéressante d'un foncteur, tu crées un foncteur et tu bind son 2ème argument.
    L'autre partie serait :
    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
     
    class Toto
    {
        private :
           std::string message;
     
        public :
           Toto(const std::string & mess):message(mess)
           {}
           bool compare(const Toto & t) const
           {
               return message == t.message;
           }
           inline friend bool compare(const Toto & t1, const Toto & t2);
    };
     
    inline bool compare(const Toto & t1, const Toto & t2)
    {
       return t1.message == t2.message;
    }
     
     
    int main()
    {
       vector<Toto> tab;
       tab.push_back(Toto("Ton Mess"));
       tab.push_back(Toto("Ton Mess2"));
     
       vector<Toto>::iterator it = find_if(tab.begin(), tab.end(), boost::bind(&Toto::compare, _1, Toto("Ton mess")));
     
       vector<Toto>::iterator it2 = find_if(tab.begin(), tab.end(), boost::bind(compare, _1, Toto("Ton mess")));
     
       return 0;
    }
    Nous pouvons faire la même chose avec la STL mais la syntaxe est un peu plus longue. Je pourrai te le mettre si cela t'intéresse, mais avant il faudra que je regarde si ça compile.

  5. #5
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    Comment ça la moins intéressante ?
    De plus, dans ton exemple, tu as mélangé le foncteur à deux arguments dont on bind le premier, et le foncteur qui prend un argument en constructeur et l'autre dans l'opérateur ().

    Dans le code de lovejava, soit on fait comme il a fait (1 argument pour le constructeur, l'autre pour () ), soit le foncteur à deux arguments et on bind l'un des deux.

  6. #6
    Membre confirmé Avatar de b Oo
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 179
    Par défaut
    Ben disons que tu bind juste un argument pour le passer dans des fonctions qui prennent moins d'arguments.
    Et la cela permet de binder directement une méthode, ce qui est plutôt pratique.
    En admettant qu'il ait créé l'opérateur ==, cela permet de ne pas créer un foncteur juste pour çà.

    De plus ton bind2nd prend un string, alors qu'il attend un account.

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 21
    Par défaut
    merci pour vos réponses.
    Alp je vais essayer ta technique pour voir si ça marche mieux, mais bon ça me chiffonne cette histoire...

    Sinon pour le pas à pas à vrai dire j'utilise pas très souvent de debugger donc je sais pas très bien m'en servir... j'ai ajouté quelques cout, qui confirment ce que je disais (la taille du vecteur = 1 juste avant l'appel à find_if)

    en faisant une fonction avec même type de retour/paramètre int test_cmp_(const account& a_comparer), là ça marche...
    jvais essayer de faire un pas à pas quand même

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 21
    Par défaut
    hum au temps pour moi l'erreur est vraiment tout conne

    comme le code source commence à être conséquent j'ai pas fait attention mais c'était juste une histoire de namespaces -_-" la définition d'account_finder et de la fonction l'utilisant était faite dans deux modules différents, ayant chacun une classe account déclarée dans des namespace différent...find_if ne devait pas trouver l'opérateur correspondant...là j'ai fais les modif et ça marche nickel...la chaleur on va dire ^^

    bref merci pour votre aide. @++

  9. #9
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut

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

Discussions similaires

  1. pb dans la stl::list avec size
    Par DEVfan dans le forum SL & STL
    Réponses: 6
    Dernier message: 10/01/2007, 18h35
  2. STL : problème avec un iterateur
    Par fabienpot dans le forum SL & STL
    Réponses: 4
    Dernier message: 06/09/2006, 09h06
  3. [STL]Problème avec map
    Par mambo dans le forum SL & STL
    Réponses: 11
    Dernier message: 27/07/2006, 15h39
  4. Probleme avec la STL(vector) avec code C
    Par Benjy dans le forum SL & STL
    Réponses: 12
    Dernier message: 06/04/2006, 12h54
  5. conteneur de la STL (problème avec DLL et COM)
    Par moldavi dans le forum MFC
    Réponses: 8
    Dernier message: 25/07/2005, 22h43

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