web-dev-qa-db-fra.com

Vecteurs, structures et std :: find

Encore moi avec des vecteurs. J'espère que je ne suis pas trop énervant. J'ai une structure comme celle-ci:

struct monster 
{
    DWORD id;
    int x;
    int y;
    int distance;
    int HP;
};

J'ai donc créé un vecteur:

std::vector<monster> monsters;

Mais maintenant, je ne sais pas comment chercher dans le vecteur. Je veux trouver un identifiant du monstre à l'intérieur du vecteur. 

DWORD monster = 0xFFFAAA;
it = std::find(bot.monsters.begin(), bot.monsters.end(), currentMonster);

Mais évidemment ça ne marche pas. Je veux parcourir uniquement l'élément .id de la structure, et je ne sais pas comment faire cela. L'aide est grandement appréciée. Merci !

27
Ahmed

std::find_if :

it = std::find_if(bot.monsters.begin(), bot.monsters.end(), 
        boost::bind(&monster::id, _1) == currentMonster);

Ou écrivez votre propre objet de fonction si vous n'avez pas de boost. Ressemblerait à ceci

struct find_id : std::unary_function<monster, bool> {
    DWORD id;
    find_id(DWORD id):id(id) { }
    bool operator()(monster const& m) const {
        return m.id == id;
    }
};

it = std::find_if(bot.monsters.begin(), bot.monsters.end(), 
         find_id(currentMonster));
35

Vous devez écrire votre propre prédicat de recherche:

struct find_monster
{
    DWORD id;
    find_monster(DWORD id) : id(id) {}
    bool operator () ( const monster& m ) const
    {
        return m.id == id;
    }
};

it = std::find_if( monsters.begin(), monsters.end(), find_monster(monsterID));
16
Lazin

que diriez-vous:

std::find_if(monsters.begin(), 
             monsters.end(), 
             [&cm = currentMonster]
             (const monster& m) -> bool { return cm == m; }); 
10
Matthieu N.

Regardez le modèle std::find, le troisième paramètre en particulier:

template<class InputIterator, class EqualityComparable>
InputIterator find(InputIterator first, InputIterator last,
               const EqualityComparable& value);

Quelle est cette EqualityComparable? Encore une fois de la documentation:

A type is EqualityComparable if objects of that type can be 
compared for equality using operator==, and if operator== is 
an equivalence relation. 

Maintenant, votre monstre de type doit définir un tel opérateur. Si vous ne le faites pas, le compilateur en crée un pour vous (comme le ctor par défaut et le dtor), ce qui fait un type de chose memcmp qui ne fonctionne pas dans votre cas. Donc, pour utiliser std::find, définissez d’abord une fonction/un comparateur que l’algorithme peut utiliser pour faire correspondre votre currentMonster, c’est-à-dire quelque chose comme:

 struct monster {
  // members
  bool operator==(const monster& l, const monster& r) const
  {
     return l.id == r.id;
  }
 };
7
dirkgently

ou mettre les monstres dans une carte au lieu d'un vecteur

ou s'ils doivent être dans un vecteur créer une carte d'index

1
pm100

Ceci est un exemple complet basé sur la réponse de Johannes Schaub (version boost).

#include <algorithm>
#include <boost/bind.hpp>

struct monster 
{
    DWORD id;
    int x;
    int y;
    int distance;
    int HP;
};

int main ()
{
    std::vector<monster> monsters;

    monster newMonster;
    newMonster.id    = 1;
    newMonster.x     = 10;
    monsters.Push_back ( newMonster );

    newMonster.id    = 2;
    newMonster.x     = 20;
    monsters.Push_back ( newMonster );

    newMonster.id    = 2;
    newMonster.x     = 30;
    monsters.Push_back ( newMonster );

    DWORD monsterId = 2;

    std::vector< monster >::iterator it = std::find_if ( monsters.begin (), monsters.end (), 
        boost::bind ( &monster::id, _1 ) == monsterId );

    return 0;
}
0
Semjon Mössinger