"AAABB"。 void remove_dups(std::string& str) { -6ren">
gpt4 book ai didi

c++ - cplusplus.com 说 std::string "shall not be dereferenced"的结尾

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:39:46 26 4
gpt4 key购买 nike

如果你能为我澄清一些困惑,我会很高兴。我正在编写一个函数来删除字符串中的重复字符,例如"AB --> "AAABB"。

void remove_dups(std::string& str) { 
std::string::iterator it = str.begin();
while (it != str.end()) {
if (*(it+1) == *it) {
str.erase(it+1);
} else {
++it;
}
}
}

我测试的时候好像能用。但是,我想知道,不应该有栅栏柱问题吗?当“it”是字符串的末尾时,if 语句查看不存在的下一个字符。根据 cplusplus.com,

尾后字符是一个理论字符,将跟在字符串中的最后一个字符之后。它不应被取消引用。 ( http://www.cplusplus.com/reference/string/string/end/ )

所以我想知道为什么我的函数似乎通过了测试,以及我如何以一种优雅的方式重写整个函数来解决 fencepost 问题。 (对我放轻松,伙计们。我是个 n00b。)

像这样重写

void remove_dups(std::string& str) { 
std::string::iterator it = str.begin();
while (it != str.end()) {
if ((it+1) != str.end() && *(it+1) == *it) {
str.erase(it+1);
} else {
++it;
}
}
}

看起来不优雅。

最佳答案

So I'm wondering why my function seems to pass the tests

未定义的行为并不意味着它不会做你想做的事。它可能完全按照您的意愿行事,只是出于错误的原因。我猜测未定义的行为本身表现为让你得到 \0 字符,这不太可能与你的字符串中的其他字符进行比较。

and how I can rewrite the whole thing in an elegant way to get around the fencepost issue

有很多选择,但我个人的喜好是

if (it != str.end()) {
++it;
while (it != str.end()) {
/* compare *it and *(it-1) */
}
}

但请注意,erase 必须移动元素。假设你总共删除了 20 个字符。您会将字符串的其余部分向后移动一个字符,即 20 次。如果您稍微修改算法,则不需要这样做:

void remove_dups(std::string& str) { 
std::string::iterator src = str.begin();
std::string::iterator dst = str.begin();
if (src != str.end()) {
++src;
++dst;
while (src != str.end()) {
if (*src != *(src-1)) {
*dst = *src;
++dst;
}
++src;
}
str.resize(dst - str.begin());
}
}

这种方法还有一个好处,即使 erase 在内存中移动字符串,它也能工作,这可能会导致迭代器中断。

关于c++ - cplusplus.com 说 std::string "shall not be dereferenced"的结尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21060256/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com