2009-02-26 12 views
22

Ancora una volta con i vettori. Spero di non essere troppo fastidioso. Ho una struttura come questa:Vettori, strutture e std :: trova

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

Così ho creato un vettore:

std::vector<monster> monsters; 

Ma ora non so come cercare attraverso il vettore. Voglio trovare un ID del mostro all'interno del vettore.

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

Ma ovviamente non funziona. Voglio eseguire l'iterazione solo tramite l'elemento .id della struct e non so come farlo. L'aiuto è molto apprezzato. Grazie !

risposta

33

std::find_if:

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

O scrivere il proprio oggetto funzione se non si dispone di spinta. Sarebbe simile a questa

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

utilizzando boost, perfetto! –

+0

Mi chiedo, se ho '{int, int}', posso lanciarlo su 'long' e usare la ricerca normale allora? –

+1

Qual è il significato di "bot" in bot.monsters.begin()? –

13

è necessario scrivere la propria ricerca predicato:

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

Risposta piacevole, ma c'è un errore di battitura nel costruttore. Dovrebbe essere ':' non ';' –

+0

Oltre a scrivere il tuo predicato di ricerca, devi usare 'std :: find_if' invece di' std :: find'. –

7

Date un'occhiata al modello std::find, il terzo parametro particolare:

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

Cos'è questo EqualityComparable? Sempre dalla documentazione:

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

Ora, il tuo tipo di mostro deve definire un tale operatore. Se non lo fai, il compilatore ne genera uno (come anche il ctor e il dtor di default) che fa un tipo di cosa memcmp che non funziona nel tuo caso. Così, per usare std::find prima definire una funzione di confronto/funtore che l'algoritmo può utilizzare per abbinare il vostro currentMonster cioè qualcosa sulla falsariga di:

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

Funziona? Non ho avuto successo perché una definizione di operatore all'interno di una struttura può avere solo 1 input –

+0

Lo stesso problema di Snoozer. -1, completa la risposta. –

7

come circa:

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

Qualcuno che vede questo mi può far capire cosa sta facendo?Nello specifico il [& cm = currentMonster] (const mostro & m) -> bool {return cm == m; }); – 2kreate

+2

Questo esempio utilizza una funzione lambda, che dipende da C++ 11. '[& cm = currentMonster]' lega la variabile 'currentMonster' dall'ambito chiamante ad un riferimento locale nel lambda, chiamato' cm'. Quindi '(const monster & m) -> bool' definisce la firma del lambda, prendendo un parametro di input,' m' e restituendo 'bool'. Il corpo della funzione lambda è '{return cm == m; } ', restituisce true se' cm' e 'm' si confrontano come uguali. –

+0

Infine so come associare correttamente le variabili locali a lambdas. –

1

o mettere i mostri una mappa invece di un vettore

o se essi devono essere in un vettore creare un indice mappa ossia la mappa di ID all'indice vettore

0

Questo è un comple campione basato sulla risposta di Johannes Schaub (versione 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; 
}