stl中字符串中的擦除关键字的工作?

Posted

技术标签:

【中文标题】stl中字符串中的擦除关键字的工作?【英文标题】:Working of erase keyword in string in stl? 【发布时间】:2018-08-17 15:41:42 【问题描述】:

我编写了这段代码来从字符串中删除辅音,但我的答案不正确。那么我应该在这段代码中进行哪些更改以使其正常工作。此外,当我从无序集中删除空格字符(即最后一个元素)时,输出对我来说是意料之外的。所以请帮助我理解这段代码发生了什么?

#include<bits/stdc++.h>
using namespace std;

int main() 
   unordered_set<char> a='a','e','i','o','O','u','U','A','E','I',' ';

   string s="what are you doing";

   string ::iterator it;
   for(it=s.begin();it!=s.end();it++)
      if(a.find(*it)==a.end())
         s.erase(it);
       

    cout<<s;
    return 0;

【问题讨论】:

您在循环时更改了字符串,这不起作用,因为您使迭代器无效。 @πάνταῥεῖ 实际上std::string::erase doc 并没有说它使迭代器无效en.cppreference.com/w/cpp/string/basic_string/erase hmm 建议:谨慎使用#include&lt;bits/stdc++.h&gt; (explanation) 和using namespace std; (explanation)。使用两者时要更加小心,因为它们会放大彼此的一些最坏影响。 为什么要否决并关闭请求? OP 创建了minimal reproducible example 并提供了足够的信息恕我直言。 【参考方案1】:

您的代码有问题,当您删除符号时

s.erase(it);

然后通过循环增加它,你跳过一个符号,也可能越过字符串的末尾。修复代码的可能解决方案:

for(it=s.begin();it!=s.end();)
   if(a.find(*it)==a.end())
      it = s.erase(it);
   else
      ++it;
 

注意1:通常在 STL 容器中,当迭代器擦除元素时,该迭代器无效。尽管std::string::erase() 的文档并没有说任何迭代器都无效,但这里可能不是这种情况。无论如何,我提供的代码在任何情况下都适用于任何容器,也可以解决您的问题。

但最好使用erase-remove 成语使用std::remove_if()

   s.erase( std::remove_if( s.begin(), s.end(), [a] ( char c ) return a.count(c) == 0;  ), s.end() );

注意2:包含“bits/stdc++.h”不是一个好主意

live example

【讨论】:

一定是cppreference失败,例如end()迭代器肯定失效了.... @user463035818 对,尚不清楚it 是否失效。看起来值得在 SO 中提出另一个问题。 remove/erase-idiom 具有线性的最坏情况复杂性。对于另一种方法,它是二次的。因此,使用它是不明智的,关于迭代器是否失效的讨论有点没有实际意义。请注意,字符串的结尾发生了变化。由于字符串是连续的,因此前一个迭代器的副本超出了范围的末尾,显然是无效的。

以上是关于stl中字符串中的擦除关键字的工作?的主要内容,如果未能解决你的问题,请参考以下文章

C ++中的擦除插入习语?

反射中泛型的擦除赋值

图像物镜 c 上的擦除功能

迭代器 - c ++ 11中没有匹配的擦除函数

AndroidJava泛型的擦除

java泛型--泛型的擦除