2009-02-26 5 views
22

Wieder ich mit Vektoren. Ich hoffe ich bin nicht zu nervig. Ich habe eine Struktur wie folgt aus:Vektoren, Strukturen und Std :: finden

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

Also habe ich einen Vektor:

std::vector<monster> monsters; 

Aber jetzt weiß ich nicht, wie durch den Vektor zu suchen. Ich möchte eine ID des Monsters innerhalb des Vektors finden.

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

Aber offensichtlich funktioniert es nicht. Ich möchte nur durch das .id-Element der Struktur iterieren, und ich weiß nicht, wie ich das machen soll. Hilfe wird sehr geschätzt. Vielen Dank !

Antwort

33

std::find_if:

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

Oder schreiben Sie Ihre eigene Funktion Objekt, wenn Sie Boost nicht haben. aussehen würde wie diese

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

mit Boost, Perfekt! –

+0

Ich frage mich, wenn ich '{int, int}' habe, könnte ich es auf 'long' umwandeln und dann normalen Fund verwenden? –

+1

Was bedeutet "bot" in bot.monsters.begin()? –

13

Sie benötigen eine eigene Such Prädikat schreiben:

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

Schöne Antwort, aber es gibt einen Tippfehler im Konstruktor. Es sollte ":" nicht ";" –

+0

Zusätzlich zum eigenen Suchprädikat müssen Sie 'std :: find_if' anstelle von' std :: find' verwenden. –

7

Werfen Sie einen Blick auf die std::find Vorlage, den dritten Parameter besonders:

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

Was ist das EqualityComparable? Nochmals aus der Dokumentation:

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

Nun muss Ihr Typ Monster einen solchen Operator definieren. Wenn Sie nicht der Compiler erzeugt einen für Sie (wie auch die Standard-Ctor und der Dtor), die eine memcmp Art von Sache, die in Ihrem Fall nicht funktioniert. So verwenden std::find zunächst eine Vergleichsfunktion/Funktors definieren, dass der Algorithmus Ihre currentMonster also etwas entlang der Linien von verwenden können, zum Spiel:

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

Funktioniert das? Ich hatte keinen Erfolg, weil eine Operatordefinition innerhalb einer Struktur nur 1 Eingabe haben kann –

+0

Das gleiche Problem wie Snoozer. -1, bitte vervollständige die Antwort. –

7

wie etwa:

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

Könnte jemand, der dies sieht, mich durch das führen, was es tut?Speziell das [& cm = aktuelleMonster] (const monster & m) -> bool {zurück cm == m; }); – 2kreate

+2

Dieses Beispiel verwendet eine Lambda-Funktion, die von C++ 11 abhängt. '[& cm = currentMonster]' bindet die Variable 'currentMonster' aus dem aufrufenden Bereich an eine lokale Referenz im Lambda, genannt 'cm'. Dann definiert '(const monster & m) -> bool' die Signatur des Lambda, indem es einen Eingabeparameter' m' nimmt und 'bool' zurückgibt. Der Körper der Lambda-Funktion ist '{return cm == m; } ', Rückgabe von True, wenn" cm "und" m "als gleichwertig verglichen werden. –

+0

Endlich weiß ich, wie man lokale Variablen richtig an Lambdas bindet. –

1

oder setzen die Monster in Dies ist ein comple eine Karte anstelle eines Vektors

oder wenn sie in einem Vektor erstellen einen Index Karte dh Karte ID Vektorindex

0

sein muss Das Sample basiert auf der Antwort von Johannes Schaub (Boost-Version).

#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; 
}