首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >cplusplus.com说std::字符串的过去端“不应该被取消引用”。

cplusplus.com说std::字符串的过去端“不应该被取消引用”。
EN

Stack Overflow用户
提问于 2014-01-11 08:33:51
回答 3查看 378关注 0票数 5

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

代码语言:javascript
复制
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。)

重写它就像

代码语言:javascript
复制
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;
        }
    }
} 

似乎不雅。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-11 08:46:26

所以我想知道为什么我的函数似乎通过了测试

不明确的行为并不意味着它不会做你想做的事。它可能会做你想做的事,只是出于错误的原因。我猜想,未定义的行为显示为获取\0字符,它不太可能等同于字符串中的其他字符。

以及如何以一种优雅的方式重写整件事,以避开fencepost问题。

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

代码语言:javascript
复制
if (it != str.end()) {
  ++it;
  while (it != str.end()) {
    /* compare *it and *(it-1) */
  }
}

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

代码语言:javascript
复制
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在内存中移动字符串,也能工作,这可能会导致迭代器中断。

票数 2
EN

Stack Overflow用户

发布于 2014-01-11 08:41:01

标准允许与过去的数组元素进行比较,不允许取消引用它。因此,您可以比较其地址,以验证循环是否应该结束,但不允许读取内容。由于迭代器大多是指针,所以这个规则也适用于字符串、向量、.

另外,请注意字符串的非序列版本::擦除返回迭代器到占用已删除元素的字符,您可以使用它作为新的循环迭代器。

票数 1
EN

Stack Overflow用户

发布于 2014-01-11 08:38:45

我认为最干净的解决方案是在字符串的末尾停止(字符串的最后一个字符),因为在这一点上,无论如何都不会执行进一步的操作。

因此,while (it != str.end())应该是while (it != str.end() && it != (str.end() - 1))

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21060256

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档