【问题标题】:Vectors, structs and std::find向量、结构和 std::find
【发布时间】:2010-10-10 01:15:31
【问题描述】:

又是向量。我希望我不会太烦人。我有一个这样的结构:

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 元素,我不知道该怎么做。非常感谢您的帮助。谢谢!

【问题讨论】:

  • 好问题,正是我需要的。一点也不烦人:)

标签: c++ data-structures find vector


【解决方案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));

【讨论】:

  • 使用提升,完美!
  • bot.monsters.begin()中的“bot”是什么意思?
  • 如果“it”的数据类型是什么??
  • 好在你举了一个没有 boost 的例子——我们从不在嵌入式系统中使用 boost,它是巨大的。我只是不明白你为什么从 std::unary_function 继承函子对象 - 看起来它可以工作,不是吗?感谢您的回答。
  • @Hiyper - 类型为 std::vector::iterator。或者你可以使用 auto it = std::find_if... 如果你使用的是 c++11
【解决方案2】:

怎么样:

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

【讨论】:

  • 看到这个的人可以告诉我它在做什么吗?特别是 [&cm = currentMonster](const monster& m) -> bool { return cm == m; });
  • 这个例子使用了一个 lambda 函数,它依赖于 C++11。 [&amp;cm = currentMonster] 将变量 currentMonster 从调用范围绑定到 lambda 中的本地引用,称为 cm。然后(const monster&amp; m) -&gt; bool 定义 lambda 的签名,接受一个输入参数m,并返回bool。 lambda 函数的主体是{ return cm == m; },如果cmm 比较相等,则返回true。
  • 我终于知道如何正确地将局部变量绑定到 lambdas。
  • 是否需要 -> bool 部分?无论哪种方式都可以编译,不是吗?
  • 末尾的{ return cm == m; } 需要在结构中定义operator==(参见@dirkgently 回答),如果没有operator==,则将return 语句更改为{ return cm.id == m.id; }
【解决方案3】:

您需要编写自己的搜索谓词:

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

【讨论】:

  • 不错的答案,但构造函数中有错字。它应该是 ':' 而不是 ';'
  • 除了编写自己的搜索谓词外,还需要使用std::find_if而不是std::find
【解决方案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,即类似于以下内容:

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

【讨论】:

  • 这行得通吗?我没有成功,因为结构内的运算符定义只能有 1 个输入
  • 与Snoozer 相同的问题。 -1,请完成答案。
  • 这个概念是正确的。这对我有用:bool operator==(const monster&amp; r) const { return id == r.id; }
【解决方案5】:

或将怪物放在地图而不是矢量中

或者如果它们必须在向量中,则创建索引映射,即 ID 映射到向量索引

【讨论】:

    【解决方案6】:

    这是一个基于 Johannes Schaub 答案的完整示例(增强版)。

    #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; 不能直接使用。

      【讨论】:

        猜你喜欢
        • 2010-10-09
        • 1970-01-01
        • 1970-01-01
        • 2011-05-15
        • 1970-01-01
        • 2014-02-27
        • 1970-01-01
        • 2018-05-16
        • 1970-01-01
        相关资源
        最近更新 更多