我想删除引用字符串传递的第一个和最后一个括号。不幸的是,我有条件地删除第一个和最后一个元素。
我无法理解为什么remove_if
没有按照我对迭代器的预期工作。
#include <iostream>
#include <algorithm>
using namespace std;
void print_wo_brackets(string& str){
auto detect_bracket = [](char x){ return(')' == x || '(' == x);};
if (!str.empty())
{
str.erase(std::remove_if(str.begin(), str.begin() + 1, detect_bracket));
}
if (!str.empty())
{
str.erase(std::remove_if(str.end()-1, str.end(), detect_bracket));
}
}
int main()
{
string str = "abc)";
cout << str << endl;
print_wo_brackets(str);
cout << str << endl;
string str2 = "(abc";
cout << str2 << endl;
print_wo_brackets(str2);
cout << str2 << endl;
return 0;
}
abc)
ac <- HERE I expect abc
(abc
abc
答案 0 :(得分:6)
如果remove_if返回end
迭代器,那么您将尝试擦除不存在的元素。您应该在两个地方使用erase
版本作为范围:
void print_wo_brackets(string& str){
auto detect_bracket = [](char x){ return(')' == x || '(' == x);};
if (!str.empty())
{
str.erase(std::remove_if(str.begin(), str.begin() + 1, detect_bracket), str.begin() + 1);
}
if (!str.empty())
{
str.erase(std::remove_if(str.end()-1, str.end(), detect_bracket), str.end());
}
}
答案 1 :(得分:4)
问题在于:
if (!str.empty())
{
str.erase(std::remove_if(str.begin(), str.begin() + 1, detect_bracket));
}
你无条件地擦除。
std::remove_if
将迭代器返回到“for removal”范围的开头。如果没有要删除的元素,则返回范围的结尾(在这种情况下为str.begin() + 1
)。因此,您删除了begin+1
元素,b
。
为了防止出现这个问题,你不应该做更多的事情:
if (!str.empty())
{
auto it = std::remove_if(str.begin(), str.begin() + 1, detect_bracket);
if(it != str.begin() + 1)
str.erase(it);
}
我假设您只想检查标准库和迭代器的行为,否则请检查:
if(str[0] == '(' || str[0] == ')')
str.erase(0);
更简单。
答案 2 :(得分:3)
替代:
#include <iostream>
#include <string>
std::string without_brackets(std::string str, char beg = '(', char end = ')') {
auto last = str.find_last_of(end);
auto first = str.find_first_of(beg);
if(last != std::string::npos) {
str.erase(str.begin()+last);
}
if(first != std::string::npos) {
str.erase(str.begin()+first);
}
return str;
}
using namespace std;
int main() {
cout << without_brackets("abc)") << endl
<< without_brackets("(abc") << endl
<< without_brackets("(abc)") << endl
<< without_brackets("abc") << endl;
return 0;
}
结果:
abc
abc
abc
abc
答案 3 :(得分:2)
如@PeteBecker的评论中所述,remove_if
不是正确的算法。由于您只想删除匹配的第一个和最后一个字符,因此更简单的方法是针对两个括号back()
和front()
(括号)测试(
和)
将是[
和]
)
void remove_surrounding(string& str, char left = '(', char right = ')')
{
if (!str.empty() && str.front() == left)
str.erase(str.begin());
if (!str.empty() && str.back() == right)
str.erase(str.end() - 1);
}
答案 4 :(得分:1)
所有你需要的是:
void print_wo_brackets(string& str){
str.erase(std::remove_if(str.begin(), str.end(),
[&](char &c) { return (c == ')' || c == '(') && (&c == str.data() || &c == (str.data() + str.size() - 1));}), str.end());
}
陈述:
str.erase(std::remove_if(str.end()-1, str.end(), detect_bracket));
你引起了未定义的行为。