c++ - 如何遍历结构中的向量?
问题描述
我正在为学校创建各种数字自动售货机,但遇到了问题。我创建了一个Items
用于自动售货的结构。然后我创建了一个名为的结构Machine
,其中包含一个vector<Items>
. 我想创建一个迭代vector<Item>
并显示项目的 for 循环,但出现以下错误:
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'
如果这是一个多余或愚蠢的问题,我深表歉意。这里也是有问题的代码:
#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;
}
该函数test
是我试图迭代Machine
结构中的矢量菜单的地方。
我是相当新的,所以如果有人有时间并且可以 ELI5 我做错了什么,那将是惊人的。
解决方案
为了在用户定义类型中使用基于范围的 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(); }
};
否则,您需要将迭代对象直接提供给循环。这意味着,在您的情况下,为了进行最小的更改:
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;
}
}
其他一些注意事项:
该
initItem
函数不是您在 C++(或任何其他面向对象的编程语言)中通常使用的方式。那是构造函数的工作。为了更改对象中成员的值,将使用 setter (member) 函数。一个好的开始是:class Item { private: std::string name; double price; unsigned int quantity; unsigned int amountInCart; bool addedToCart; public: // constructor Item(std::string name, double price, unsigned int quantity, unsigned int amountInCart, bool addedToCart) : name{ name } // or name{ std::move(name) } when you learn about the move-semantics , price{ price} , quantity{ quantity } , amountInCart{ amountInCart } , addedToCart{ addedToCart } {} // ... getter and setter functions };
您现在创建一个对象,例如:
Item cake{ "Cake", 3.00, 5, 0, false };
- 请不要练习
using namespace std;
。有关更多信息,请参见此处:为什么“使用命名空间 std;” 被认为是不好的做法? - 我已将对象传递给通过合格引用传递
Machine
的函数test
(也在基于范围的循环中,对象)。当数据在任何范围内都不可修改时,您应该像这样传递参数,以避免不必要的复制(creadits @Klaus) :。进一步阅读:在 C++ 中通过值传递还是通过常量引用传递更好?Item
const
推荐阅读
- python - 将屏幕截图添加到从机器人框架到 Azure Pipelines 测试选项卡的 XUNIT 测试结果
- javascript - 如果分数是 0.6(不是 0.5)或更大,我如何四舍五入?
- python - 用熊猫中的 80% 替换超过 80% 的值
- html - 如何更改 Laravel 中的图标?
- security - 微服务架构中具有 userId 字段的数据库组织
- flutter - WidgetsBindingObserver 是否适用于无状态小部件?
- c++ - 如何在 C++ 中将数字拆分为数字
- javascript - 如何欺骗反应路由器认为`/`是挂载目录?
- python - 如何在 Ray 中使用全局变量
- java - 数据未更改时如何从 Firebase 检索数据