2009-02-26 17 views
22

もう一度ベクトルで私。私はあまりにも迷惑ではないことを願っています。ベクトル、構造体、およびstd :: find

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

は、だから私は、ベクター作成:

std::vector<monster> monsters; 

をしかし、今、私はベクトルを検索する方法がわからない私はこのような構造体を持っています。私はベクトル内のモンスターのIDを探したい。

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

しかし、明らかに動作しません。私は構造体の.id要素を介してのみ反復処理を行いたいが、それをどうやって行うのか分からない。ヘルプは非常に高く評価されます。ありがとう!

答えて

33

std::find_if

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

それとも、ブーストを持っていない場合は、独自の関数オブジェクトを書きます。この

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

boostを使用して、Perfect! –

+0

私が '{int、int}'を持っていれば、それを 'long'にキャストして通常のfindを使うことができますか? –

+1

bot.monsters.begin()の "bot"の意味は? –

13

独自の検索述語記述する必要があります。

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

正解ですが、コンストラクタに入力ミスがあります。それは ':'ではなく、 ';' –

+0

独自の検索述語を書くことに加えて、 'std :: find'の代わりに' std :: find_if'を使う必要があります。 –

7

ようになり、特に、三番目のパラメータをstd::findテンプレートを見てみましょう:

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

このEqualityComparableは何ですか?もう一度ドキュメントから:

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

あなたのタイプのモンスターは、このような演算子を定義する必要があります。コンパイラがあなたのために生成しない場合(デフォルトのctorとdtorのように)、memcmpという種類のものはあなたのケースでは動作しません。

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

これは機能しますか?構造体内の演算子の定義は1つしか入力できないので、私は成功しませんでした。 –

+0

Snoozerと同じ問題です。 -1、答えを記入してください。 –

7

方法について::だから、アルゴリズムはの線に沿ってあなたのcurrentMonsterすなわち何か一致させるために使用できることを第1のコンパレータ機能/ファンクタを定義std::findを使用する

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

これを見ている人は、自分が行っていることを通して私を歩くことができますか?具体的には、[&cm = currentMonster](const monster&m) - > bool {return cm == m; }); – 2kreate

+2

この例では、C++ 11に依存するラムダ関数を使用しています。 '[&cm = currentMonster]'は、変数 'currentMonster'を呼び出しスコープから、' cm'というラムダのローカル参照にバインドします。そして '(const monster&m) - > bool'はラムダのシグネチャを定義し、一つの入力パラメータmをとり、' bool'を返します。ラムダ関数の本体は '{return cm == m; 'cm'と' m'が等しいと比較すればtrueを返します。 –

+0

最後に、lambdaにローカル変数を正しくバインドする方法を知っています。 –

1

のかでモンスターを置きます代わりにベクトル

または彼らはベクトルでなければなりません場合はベクトルインデックス

0

へのIDのインデックスマップ、すなわちマップを作成するマップは、これはcompleですteサンプルはJohannes Schaub(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; 
}