Подтвердить что ты не робот

Векторы, структуры и std:: find

Снова меня с векторами. Надеюсь, я не слишком раздражаю. У меня есть такая структура:

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

Итак, я создал вектор:

std::vector<monster> monsters;

Но теперь я не знаю, как искать вектор. Я хочу найти идентификатор монстра внутри вектора.

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

Но, очевидно, это не сработает. Я хочу выполнять итерацию только через .id-элемент структуры, и я не знаю, как это сделать. Помощь очень ценится. Спасибо!

4b9b3361

Ответ 1

std::find_if:

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

Или напишите свой собственный объект функции, если у вас нет boost. Будет выглядеть так:

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

Ответ 2

Вам нужно написать собственный предикат поиска:

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

Ответ 3

как насчет:

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

Ответ 4

Взгляните на шаблон 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 вещь, которая не работает в вашем случае. Итак, чтобы использовать std::find, сначала определите функцию/функтор компаратора, которую алгоритм может использовать, чтобы соответствовать вашему currentMonster i.e, что-то вроде строк:

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

Ответ 5

или поместите монстров в карту вместо вектора

или если они должны быть в векторе, создайте карту индексов, то есть карту идентификатора к векторному индексу

Ответ 6

Это полный образец, основанный на ответе Йоханнеса Шауба (ускоренная версия).

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

Ответ 7

Вы можете написать функцию, как показано ниже:

monster* findMonster(DWORD currentMonster) {
    for (auto it = bot.monsters.begin(); it != bot.monsters.end(); it++) {
        if (it->id == currentMonster) {
            return &(*it);
        }
    }
    return NULL;
}

Возвращает указатель на сохраненный узел, если он найден в векторе, в противном случае возвращает NULL.

Обратите внимание, что return it; не будет работать напрямую.