如何从矢量中删除具有给定名称的玩家
How to erase a player with a given name from a vector
我在尝试从向量中删除字符串时看到一些严重的错误消息。我正在尝试使用 erase-remove 习惯用法,但它不起作用。这里有一些片段来展示我的困境。
team.players.erase( remove(team.players.begin(), team.players.end(),
player_name), team.players.end());
team.players 在此结构中声明:
struct team
{
string name;
player captain;
vector<player> players;
};
矢量 team.players 在程序运行时动态填充,并且在某些时候用户可以选择通过菜单删除播放器。
if (select_option == PRINT_TEAM) print_team(team);
if (select_option == CHANGE_TEAM_NAME) change_team_name(team);
if (select_option == CHANGE_CAPTAIN) change_captain(team);
if (select_option == ADD_PLAYER) add_player(team);
if (select_option == REMOVE_PLAYER) remove_player(team);
if (select_option == QUIT) exit(0);
但是,在我尝试编译我的程序 (clang++) 时,我在函数被调用之前很久就遇到了这些错误。以下是错误:
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/algorithm:865:22: error: invalid operands to binary expression ('player' and 'const std::__1::basic_string<char>')
if (*__first == __value_)
~~~~~~~~ ^ ~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/algorithm:2125:22: note:
in instantiation of function template specialization
'std::__1::find<std::__1::__wrap_iter<player *>, std::__1::basic_string<char> >'
requested here
__first = _VSTD::find(__first, __last, __value_);
^
program2.cpp:172:25: note: in instantiation of function template specialization
'std::__1::remove<std::__1::__wrap_iter<player *>, std::__1::basic_string<char>
>' requested here
team.players.erase( remove(team.players.begin(), team.players.end(),
^
2 errors generated.
知道如何解决这个问题吗?
错误信息非常隐蔽,尤其是对于初学者,但似乎编译器无法找到一个 operator==
实现来比较你的 player
class 的实例std::string
个对象。
也许您真正想要的是使用 std::remove_if
,指定一个自定义条件,在该条件下您将玩家的名字与 std::string
存储要删除的名字进行比较。
您可以使用 lambda 表达这个自定义条件,例如:
team.players.erase(
std::remove_if(
team.players.begin(),
team.players.end(),
[&player_name](const player& p) {
return p.name == player_name;
}),
team.players.end()
);
你想要 std::remove_if
,而不是 std::remove
。您将必须提供一个函数,该函数需要播放器(const 引用以避免复制)和 returns bool.
例如(假设 player
有一个字符串成员 name
)
team.players.erase(
remove_if(
team.players.begin(),
team.players.end(),
[&player_name](const player & p) { return p.name == player_name }),
team.players.end());
问题是 std::remove()
函数使用 bool operator==()
将 std::vector<player>
的元素与类型为 std::string
的 player_name
变量进行比较.
这就是 std::remove()
识别矢量的哪些元素应该擦除(或者,更好的是,移动到容器的末尾)的方式。
然而,没有bool operator==(const player& p, const std::string& name)
定义,这并不奇怪,因为你必须自己做。更好的方法,在这种情况下,恕我直言,使用 std::remove_if()
而不是 std::remove()
,因为 std::remove_if()
接受一个 一元函数 (一个接受一个参数的函数和 returning bool),它调用它是为了确定是否应该删除该元素。
team.players.erase(remove_if(team.players.begin(), team.players.end(),
[&player_name](const auto& player) { return player.name == player_name; });
(注意:我假设 player
class/struct 有一个类型为 std::string
的成员 name
。
如果您想尝试 operator==()
方法,您必须定义
像这样:
bool operator==(const player& p, const std::string& name) {
return p.name == name;
}
bool operator==(const std::string& name, const player& p) {
return p.name == name;
// Or, to be more general, you could use
// return operator==(p, name);
// here (to call the operator==() version with switched arguments)
}
(是的,你应该 return 两个版本,因为 - 通常 - 使用 ==
的比较应该是对称的)。
我在尝试从向量中删除字符串时看到一些严重的错误消息。我正在尝试使用 erase-remove 习惯用法,但它不起作用。这里有一些片段来展示我的困境。
team.players.erase( remove(team.players.begin(), team.players.end(),
player_name), team.players.end());
team.players 在此结构中声明:
struct team
{
string name;
player captain;
vector<player> players;
};
矢量 team.players 在程序运行时动态填充,并且在某些时候用户可以选择通过菜单删除播放器。
if (select_option == PRINT_TEAM) print_team(team);
if (select_option == CHANGE_TEAM_NAME) change_team_name(team);
if (select_option == CHANGE_CAPTAIN) change_captain(team);
if (select_option == ADD_PLAYER) add_player(team);
if (select_option == REMOVE_PLAYER) remove_player(team);
if (select_option == QUIT) exit(0);
但是,在我尝试编译我的程序 (clang++) 时,我在函数被调用之前很久就遇到了这些错误。以下是错误:
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/algorithm:865:22: error: invalid operands to binary expression ('player' and 'const std::__1::basic_string<char>')
if (*__first == __value_)
~~~~~~~~ ^ ~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/algorithm:2125:22: note:
in instantiation of function template specialization
'std::__1::find<std::__1::__wrap_iter<player *>, std::__1::basic_string<char> >'
requested here
__first = _VSTD::find(__first, __last, __value_);
^
program2.cpp:172:25: note: in instantiation of function template specialization
'std::__1::remove<std::__1::__wrap_iter<player *>, std::__1::basic_string<char>
>' requested here
team.players.erase( remove(team.players.begin(), team.players.end(),
^
2 errors generated.
知道如何解决这个问题吗?
错误信息非常隐蔽,尤其是对于初学者,但似乎编译器无法找到一个 operator==
实现来比较你的 player
class 的实例std::string
个对象。
也许您真正想要的是使用 std::remove_if
,指定一个自定义条件,在该条件下您将玩家的名字与 std::string
存储要删除的名字进行比较。
您可以使用 lambda 表达这个自定义条件,例如:
team.players.erase(
std::remove_if(
team.players.begin(),
team.players.end(),
[&player_name](const player& p) {
return p.name == player_name;
}),
team.players.end()
);
你想要 std::remove_if
,而不是 std::remove
。您将必须提供一个函数,该函数需要播放器(const 引用以避免复制)和 returns bool.
例如(假设 player
有一个字符串成员 name
)
team.players.erase(
remove_if(
team.players.begin(),
team.players.end(),
[&player_name](const player & p) { return p.name == player_name }),
team.players.end());
问题是 std::remove()
函数使用 bool operator==()
将 std::vector<player>
的元素与类型为 std::string
的 player_name
变量进行比较.
这就是 std::remove()
识别矢量的哪些元素应该擦除(或者,更好的是,移动到容器的末尾)的方式。
然而,没有bool operator==(const player& p, const std::string& name)
定义,这并不奇怪,因为你必须自己做。更好的方法,在这种情况下,恕我直言,使用 std::remove_if()
而不是 std::remove()
,因为 std::remove_if()
接受一个 一元函数 (一个接受一个参数的函数和 returning bool),它调用它是为了确定是否应该删除该元素。
team.players.erase(remove_if(team.players.begin(), team.players.end(),
[&player_name](const auto& player) { return player.name == player_name; });
(注意:我假设 player
class/struct 有一个类型为 std::string
的成员 name
。
如果您想尝试 operator==()
方法,您必须定义
像这样:
bool operator==(const player& p, const std::string& name) {
return p.name == name;
}
bool operator==(const std::string& name, const player& p) {
return p.name == name;
// Or, to be more general, you could use
// return operator==(p, name);
// here (to call the operator==() version with switched arguments)
}
(是的,你应该 return 两个版本,因为 - 通常 - 使用 ==
的比较应该是对称的)。