如何遍历结构中的向量?

cap*_*pyt 3 c++ struct iterator loops stdvector

我正在为学校创建各种数字自动售货机,但遇到了问题。我创建了一个Items自动售货结构。然后,我创建了一个名为的结构Machine,其中包含一个vector<Items>。我想创建一个for循环,该循环遍历vector<Item>并显示项目,但出现以下错误:

C:\Users\Nate\Desktop>g++ structversion.cpp -o structversion.exe -std=c++11
structversion.cpp: In function 'int test(Machine)':
structversion.cpp:29:20: error: 'begin' was not declared in this scope
   for (Item item : machine) {
                    ^
structversion.cpp:29:20: note: suggested alternatives:
In file included from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/string:51:0,
                 from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/locale_classes.h:40,
                 from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/ios_base.h:41,
                 from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ios:42,
                 from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ostream:38,
                 from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/iostream:39,
                 from structversion.cpp:1:
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/range_access.h:87:5: note:   'std::begin'
     begin(_Tp (&__arr)[_Nm])
     ^
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/range_access.h:87:5: note:   'std::begin'
structversion.cpp:29:20: error: 'end' was not declared in this scope
   for (Item item : machine) {
                    ^
structversion.cpp:29:20: note: suggested alternatives:
In file included from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/string:51:0,
                 from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/locale_classes.h:40,
                 from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/ios_base.h:41,
                 from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ios:42,
                 from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/ostream:38,
                 from C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/iostream:39,
                 from structversion.cpp:1:
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/range_access.h:97:5: note:   'std::end'
     end(_Tp (&__arr)[_Nm])
     ^
C:/TDM-GCC-64/lib/gcc/x86_64-w64-mingw32/5.1.0/include/c++/bits/range_access.h:97:5: note:   'std::end'
Run Code Online (Sandbox Code Playgroud)

抱歉,这是一个多余或愚蠢的问题。这也是有争议的代码:

#include <iostream>
#include <vector>
#include <string>
using namespace std;

struct Item 
{
    string name;
    double price;
    unsigned int quantity;
    unsigned int amountInCart;
    bool addedToCart;
};

struct Machine { vector<Item> menu; };

void initItem(Item& i, string name, double price, unsigned int quantity,
    unsigned int amountInCart, bool addedToCart) 
{
    i.name = name;
    i.price = price;
    i.quantity = quantity;
    i.amountInCart = amountInCart;
    i.addedToCart = addedToCart;
}

test(Machine machine)
{
    for (Item i : machine) {
        cout << "item = " << i.name;
    }
}

main()
{
    Item cake;
    Item fruit;
    Item chips;
    Item soda;
    Item juice;

    initItem(cake, "Cake", 3.00, 5, 0, false);
    initItem(fruit, "Fruit", 4.20, 15, 0, false);
    initItem(chips, "Chips", 1.00, 6, 0, false);
    initItem(soda, "Soda", 1.50, 7, 0, false);
    initItem(juice, "Juice", 1.90, 10, 0, false);

    Machine machine;
    machine.menu.push_back(cake);
    machine.menu.push_back(fruit);
    machine.menu.push_back(chips);
    machine.menu.push_back(soda);
    machine.menu.push_back(juice);

    test(machine);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该函数test是我尝试遍历该Machine结构内的矢量菜单的地方。

我很新,所以如果有人有时间并且可以ELI5我做错了,那将是惊人的。

JeJ*_*eJo 5

为了在用户定义的类型中使用基于范围的for循环,您需要定义begin()end()迭代器。这意味着Machine需要具有以下成员函数,这些成员函数返回成员容器的迭代器。请参见在线直播

struct Machine
{
    vector<Item> menu;
    auto begin() { return menu.begin(); } // auto return requires C++14
    auto end()   { return menu.end();   }

    // or in C++11, you provide the correct return type
    // decltype(menu.begin()) begin() { return menu.begin(); }
    // decltype(menu.end())   end()   { return menu.end();   }
};
Run Code Online (Sandbox Code Playgroud)

否则,您需要直接向循环提供迭代对象。在您的情况下,这意味着为了进行最小的更改:

void test(Machine const& machine) // pass by `const-ref` as the machine is read-only inside the function
{
    for (const Item& i : machine.menu) { // const& : same reason as above ^^
    //                   ^^^^^^^^^^^^ --> std::vector has iterators: begin(), end() 
        cout << "item = " << i.name;
    }
}
Run Code Online (Sandbox Code Playgroud)

其他注意事项:

  • initItem函数不是您通常在C ++(或任何其他面向对象的编程语言)中所采用的方法。那是构造函数的工作。为了更改对象中成员的值,将使用setter(成员)功能。一个好的开始将是:

    struct Machine
    {
        vector<Item> menu;
        auto begin() { return menu.begin(); } // auto return requires C++14
        auto end()   { return menu.end();   }
    
        // or in C++11, you provide the correct return type
        // decltype(menu.begin()) begin() { return menu.begin(); }
        // decltype(menu.end())   end()   { return menu.end();   }
    };
    
    Run Code Online (Sandbox Code Playgroud)

    您现在创建一个对象,如下所示:

    void test(Machine const& machine) // pass by `const-ref` as the machine is read-only inside the function
    {
        for (const Item& i : machine.menu) { // const& : same reason as above ^^
        //                   ^^^^^^^^^^^^ --> std::vector has iterators: begin(), end() 
            cout << "item = " << i.name;
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 请不要练习using namespace std;。有关更多信息,请参见此处:为什么“使用命名空间标准”;被认为是不良做法?
  • 我已将对象传递给合格引用所传递的Machine函数test(也在基于范围的循环中,Item对象)const。无论何时,数据在任何范围内都是不可修改的,您应该传递这样的参数,以便避免不必要的复制(creadits @Klaus:。供进一步阅读:在C ++中按值传递还是通过常量引用传递更好?