【问题标题】:Using std::find To Choose An Item From A Vector使用 std::find 从向量中选择一个项目
【发布时间】:2012-11-01 05:25:57
【问题描述】:

我在让基于矢量的库存系统工作时遇到问题。我能够列出库存中的项目,但不能允许访问用户选择的项目。代码如下:

struct aItem
{
    string  itemName;
    int     damage;

    bool operator==(aItem other)
    {
        if (itemName == other.itemName)
            return true;
        else
            return false;
    }
};

int main()
{
    int selection = 0;


    aItem healingPotion;
    healingPotion.itemName = "Healing Potion";
    healingPotion.damage= 6;

    aItem fireballPotion;
    fireballPotion.itemName = "Potion of Fiery Balls";
    fireballPotion.damage = -2;

    aItem testPotion;
    testPotion.itemName = "I R NOT HERE";
    testPotion.damage = 9001;
    int choice = 0;
    vector<aItem> inventory;
    inventory.push_back(healingPotion);
    inventory.push_back(healingPotion);
    inventory.push_back(healingPotion);
    inventory.push_back(fireballPotion);

    cout << "This is a test game to use inventory items. Woo!" << endl;
    cout << "You're an injured fighter in a fight- real original, I know." << endl;
    cout << "1) Use an Item. 2) ...USE AN ITEM." << endl;

switch (selection)
    {
    case 1:
        cout << "Which item would you like to use?" << endl;
        int a = 1;
        for( vector<aItem>::size_type index = 0; index < inventory.size(); index++ ) 
        {

            cout << "Item " << a << ": " <<  inventory[index].itemName << endl;
            a+= 1;
        }
        cout << "MAKE YOUR CHOICE." << endl << "Choice: ";

        cin >> choice;

^^^^ 这条线以上的一切,都有效。我认为我的问题是 if 语句,但我无法弄清楚我的语法哪里出错了,或者是否有更好的方法来做我正在做的事情。

        if (find(inventory.begin(), inventory.at(choice), healingPotion.itemName) != inventory.end())
            cout << "You used a healing potion!";
        else
            cout << "FIERY BALLS OF JOY!";
        break;

    case 2:
        cout << "Such a jerk, you are." << endl;
            break;

    }

编辑:我认为我没有正确表示这一点。我需要让玩家的选择影响显示的消息。这是第一个 sn-p 的示例输出:

Item 1: Healing Potion
Item 2: Healing Potion
Item 3: Healing Potion
Item 4: Potion of Fiery Balls

MAKE YOUR CHOICE. 
Choice: 

从那里,玩家可以输入 1-4,我想要的是将数字(减 1,以反映从零开始的向量)传递给 find,然后它将确定(在这个小例如)如果库存[选择 - 1] 中的物品是治疗药水。如果是这样,显示“你使用了治疗药水!”如果不是,则显示“快乐的火球”。

【问题讨论】:

  • 不应该是if (find(inventory.begin(), inventory.end() , healingPotion.itemName) != inventory.end())??此外,inventory.at(choice) 将返回对该 vector 中特定对象值的引用,而不是对 iterator 的引用。
  • 你看到了什么失败?
  • 您的运营商应声明为:bool operator==(const aItem&amp; other) const
  • 1>----- 构建开始:项目:StructPractice,配置:调试 Win32 ------ 1> StructPractice.cpp 1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(3186): error C2678: binary '==' : no operator found which take a left-hand operand of type 'aItem' (或者没有可接受的转换)
  • @VladimirMarenus:对,因为左边不是const。看我的回答。

标签: c++ syntax if-statement vector find


【解决方案1】:

三个问题。

一、你的操作符应该声明为:

bool operator==(const aItem&amp; other) const

二,在这段代码中:

find(inventory.begin(), inventory.at(choice), healingPotion) != inventory.end())

您不是在搜索从begin()end() 的整个向量——您只是在从begin()at(choice) 进行搜索,其中at(choice) 指向您搜索的最后一个位置放。所以你要么应该这样做:

find(&inventory.at(0), &inventory.at(choice), healingPotion) != &inventory.at(choice))

或者这个……

find(inventory.begin(), inventory.end(), healingPotion.itemName) != inventory.end())

编辑 三,您正在尝试将苹果与橙子进行比较。您正在搜索 vectoraItem 对象以查找匹配的 aItem 对象,但您发送到 find 的参数不是 aItem 对象,它是 aItem 数据成员之一。

您应该搜索匹配的项目,如下所示:

find( inventory.begin(), inventory.end(), healingPotion ) != inventory.end() )
                                            ^^^^^^^^

在 C++03 中你可以提供一个仿函数:

#include <functional>
struct match_name : public std::unary_function<aItem, bool>
{
    match_name(const string& test) : test_(test) {}
    bool operator()(const aItem& rhs) const
    {
        return rhs.itemName == test_;
    }
private:
  std::string test_;
};

...然后使用find_if搜索匹配:

find_if( inventory.begin(), inventory.end(), match_name(healingPotion.itemName) ) // ...

在 C++11 中,您可以使用闭包来简化这种混乱:

string test = healingPotion.itemName;
if( find_if( inventory.begin(), inventory.end(), [&test](const aItem& rhs)
{
    return test == rhs.itemName;
}) == inventory.end() )
{
  // not found
}

【讨论】:

  • 当我使用该答案时,我得到以下信息: 1>c:\users\dmarr\documents\csharper\dallas\cplusplus\structpractice\structpractice\structpractice.cpp(75): error C2782: '_InIt std::find(_InIt,_InIt,const _Ty &)' : 模板参数 '_InIt' 不明确 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(3215) :见'std::find' 1> 的声明可以是 'aItem' 1> 或 'std::_Vector_iterator<_myvec>' 1> with 1> [ 1> _Myvec=std::_Vector_val<:_simple_types>> 1>]
  • vector::at 返回一个引用,而不是一个迭代器。怎么可以作为find的第二个参数?
  • @BenjaminLindley:正如最初写的那样,它不能。查看我的编辑。
  • @JohnDibling 几乎!新错误:错误 C2678:二进制“==”:未找到采用“aItem”类型的左侧操作数的运算符(或没有可接受的转换)//但我在结构中定义了它,除非它在谈论某事否则...
  • @VladimirMarenus:你定义错了。请参阅我的第一点。
【解决方案2】:

要添加到 John Dibling 的答案,最后一部分是您正在寻找一个名称,而不是 aItem。

所以它要么需要:

find(inventory.begin(), inventory.end(), healingPotion) != inventory.end();

其中 operator== 定义为:

bool operator==(const aItem& other) const
{
   return itemName == other.itemName;
}

或者你需要让你的 operator== 接受一个字符串:

find(inventory.begin(), inventory.end(), healingPotion.itemName) != inventory.end();

其中 operator== 定义为:

bool operator==(const std::string& name) const
{
   return itemName == name;
}

【讨论】:

  • 感谢您的帮助! ...但我认为这偏离了我的初衷 - 请查看我的编辑。
  • 那么只要验证输入值对于向量的大小,直接抓取第n个值。如果您要查找特定的偏移量,则无需搜索向量。
  • 然而,仅仅因为inventory[3]现在是一种治疗药水,并不意味着它会是下次选择inventory[3]的时候——这些都是消耗品。
【解决方案3】:

代替:

case 1:
        cout << "Which item would you like to use?" << endl;
        int a = 1;
        for( vector<aItem>::size_type index = 0; index < inventory.size(); index++ ) 
        {

            cout << "Item " << a << ": " <<  inventory[index].itemName << endl;
            a+= 1;
        }
        cout << "MAKE YOUR CHOICE." << endl << "Choice: ";

        cin >> choice;
        if (find(inventory.begin(), inventory.at(choice), healingPotion.itemName) != inventory.end())
            cout << "You used a healing potion!";
        else
            cout << "FIERY BALLS OF JOY!";
        break;

    case 2:
        cout << "Such a jerk, you are." << endl;
            break;

    }

我没有意识到向量的奇妙之处之一是能够直接访问值 - Ryan Guthrie 在他的评论中提到了这一点,但我找到了一个更简单的“答案”。即:

case 1:
    cout << "Which item would you like to use?" << endl;
    //TODO: Learn what the hell the following line actually means.
    for( vector<aItem>::size_type index = 0; index < inventory.size(); index++ ) 
    {
        //Makes a numerical list.
        cout << "Item " << index + 1 << ": " <<  inventory[index].itemName << endl;
        a+= 1;
    }
    cout << "MAKE YOUR CHOICE." << endl << "Choice: ";

    cin >> choice;
    //Cannot define this outside of the statement, or it'll initialize to -1
    invVecPos = (choice - 1);

    //This checks for an invalid response. TODO: Add in non-int checks. 
    if ((invVecPos) >= inventory.size())
    {
        cout << "Choice out of bounds. Stop being a dick." << endl;
    }
    //If the choice is valid, proceed.
    else
    {
        //checking for a certain item type.
        if(inventory[invVecPos].itemType == "ITEM_HEALTHPOT")
        {
            cout << "You used a healing potion!" << endl;
            //this erases the potion, and automagically moves everything up a tick.
            inventory.erase (inventory.begin() + (invVecPos));
        }

        else if(inventory[invVecPos].itemType == "ITEM_FIREPOT")
        {
            cout << "FIERY BALLS OF JOY!" << endl;
        }

        else
        {
            //error-handling! Whee!
            cout << "Invalid Item type" << endl;
        }
    }


    break;
case 2:
    cout << "Why do you have to be so difficult? Pick 1!" << endl;
    break;

谢谢你,Ryan - 在你的推动下,我能够在别处寻找我需要的代码! “已修复”的代码被大量注释,因此遇到问题的任何其他人都应该能够收集他们需要的内容!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-23
    • 1970-01-01
    • 2010-10-10
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多