String erase() 给出核心转储
String erase() giving core dumped
我正在做代码战争的套路,我需要这样的东西:
当字符串中的字母出现两次时 - 将两者都删除。
我做过这样的事情:
std::string str2 = str;
for(int i=0;i<str2.size();i++){
for(int j=0;j<str2.size();j++){
if(std::tolower(str2[i]) == std::tolower(str2[j]) && j != i){
n++;
str2.erase(str2.begin() + i);
str2.erase(str2.begin() + j);
i--;
j--;
}
}
}
并被核心转储(这是由 str2.erase(str2.begin() + i);
引起的)。我知道这是我的记忆错误,但你能告诉我这有什么问题吗?我分析了一下,没有发现任何问题。
您正在从 str2
中删除两个字符。如果 i
小于 j
,这可能会导致第二次擦除访问到字符串末尾之后(即使不是,您也会擦除错误的字符)。
首先,我们可以观察到,当擦除发生时,我们总是 i<j
。
问题 1
现在,如果您先删除第一个字符,然后删除第二个字符,那么您就是在向移动目标射击:在删除第一个字符后,您需要调整到第二个字符的新位置:
str2.erase(str2.begin() + i);
str2.erase(str2.begin() + j-1); // because former j c[j] is now c[j-1]
另一个同样适用的变体是先删除第二个字符(不改变第一个字符的位置):
str2.erase(str2.begin() + j); // because j> i it has no impact on i
str2.erase(str2.begin() + i);
优化1
无关,但我们也可以利用我们在 i<j
上的推论来优化或循环并保存大量无用的比较:
for(int i=0;i<str2.size();i++) {
for(int j=i+1;j<str2.size();j++) {
...
}
}
优化 2
另一个问题是当 i
没有递增时,您在内循环中执行 i--
。这将产生两个结果,您将重做您已经做过的比较。所以只需删除这个减量,然后用 j=i+1
.
重新启动
问题 2(留作练习)
您的算法只会删除成对的字母。因此,如果一个字母出现超过 2 次,则只有前两个字母会被删除。所以你需要检查你的算法(注意不要在第一次出现时擦除几次;-))
我正在做代码战争的套路,我需要这样的东西:
当字符串中的字母出现两次时 - 将两者都删除。
我做过这样的事情:
std::string str2 = str;
for(int i=0;i<str2.size();i++){
for(int j=0;j<str2.size();j++){
if(std::tolower(str2[i]) == std::tolower(str2[j]) && j != i){
n++;
str2.erase(str2.begin() + i);
str2.erase(str2.begin() + j);
i--;
j--;
}
}
}
并被核心转储(这是由 str2.erase(str2.begin() + i);
引起的)。我知道这是我的记忆错误,但你能告诉我这有什么问题吗?我分析了一下,没有发现任何问题。
您正在从 str2
中删除两个字符。如果 i
小于 j
,这可能会导致第二次擦除访问到字符串末尾之后(即使不是,您也会擦除错误的字符)。
首先,我们可以观察到,当擦除发生时,我们总是 i<j
。
问题 1
现在,如果您先删除第一个字符,然后删除第二个字符,那么您就是在向移动目标射击:在删除第一个字符后,您需要调整到第二个字符的新位置:
str2.erase(str2.begin() + i);
str2.erase(str2.begin() + j-1); // because former j c[j] is now c[j-1]
另一个同样适用的变体是先删除第二个字符(不改变第一个字符的位置):
str2.erase(str2.begin() + j); // because j> i it has no impact on i
str2.erase(str2.begin() + i);
优化1
无关,但我们也可以利用我们在 i<j
上的推论来优化或循环并保存大量无用的比较:
for(int i=0;i<str2.size();i++) {
for(int j=i+1;j<str2.size();j++) {
...
}
}
优化 2
另一个问题是当 i
没有递增时,您在内循环中执行 i--
。这将产生两个结果,您将重做您已经做过的比较。所以只需删除这个减量,然后用 j=i+1
.
问题 2(留作练习)
您的算法只会删除成对的字母。因此,如果一个字母出现超过 2 次,则只有前两个字母会被删除。所以你需要检查你的算法(注意不要在第一次出现时擦除几次;-))