2009-02-26 5 views
22

Encore moi avec des vecteurs. J'espère que je ne suis pas trop ennuyeux. J'ai un struct comme ceci:Vecteurs, structs et std :: trouver

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

Je créé un vecteur:

std::vector<monster> monsters; 

Mais maintenant, je ne sais pas comment effectuer une recherche 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, cela ne fonctionne pas. Je veux itérer seulement à travers l'élément .id de la structure, et je ne sais pas comment faire cela. L'aide est grandement appréciée. Merci !

Répondre

33

std::find_if:

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

Ou écrire votre propre objet fonction si vous n'avez pas boost. Ressembleraient cette

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)); 
+0

en utilisant boost, parfait! –

+0

Je me demande, si j'ai '{int, int}', puis-je le convertir en 'long' et utiliser normal find alors? –

+1

Quelle est la signification de "bot" dans bot.monsters.begin()? –

13

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)); 
+0

Bonne réponse, mais il y a une faute de frappe dans le constructeur. Ce devrait être ':' pas ';' –

+0

En plus d'écrire votre propre prédicat de recherche, vous devez utiliser 'std :: find_if' à la place de' std :: find'. –

7

Jetez un coup d'oeil au modèle std::find, le troisième paramètre particulier:

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

Qu'est-ce que ce EqualityComparable? Encore une fois à partir 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 génère un pour vous (comme le ctor et le dtor par défaut), ce qui fait une sorte de chose qui ne marche pas dans votre cas. Donc, pour utiliser std::find d'abord définir une fonction de comparaison/foncteur que l'algorithme peut utiliser pour correspondre à votre currentMonster-à-dire quelque chose le long des lignes de:

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

Est-ce que cela fonctionne? Je n'ai pas eu de succès car une définition d'opérateur à l'intérieur d'une structure ne peut avoir qu'une seule entrée –

+0

Même problème que Snoozer. -1, veuillez compléter la réponse. –

7

Que diriez-vous:

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

Est-ce que quelqu'un qui voit ça me dirait ce que ça fait?Plus précisément, le [& cm = currentMonster] (monstre const & m) -> bool {return cm == m; }); – 2kreate

+2

Cet exemple utilise une fonction lambda, qui dépend de C++ 11. '[& cm = currentMonster]' lie la variable 'currentMonster' de la portée appelante à une référence locale dans le lambda, appelée' cm'. Alors '(const monster & m) -> bool' définit la signature du lambda, en prenant un paramètre d'entrée,' m', et en retournant 'bool'. Le corps de la fonction lambda est '{return cm == m; } ', retourne vrai si' cm' et 'm' se comparent comme égaux. –

+0

Enfin, je sais comment lier correctement les variables locales à lambdas. –

1

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

ou si elles doivent être dans un vecteur créer une carte d'index par exemple d'ID à l'index vectoriel

0

Ceci est un complé échantillon 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; 
}