如何删除C ++字符串中所有出现的char


Answers:


171

基本上,replace将一个字符替换为另一个''字符不是一个字符。您正在寻找的是erase

看到这个问题回答同样的问题。在您的情况下:

#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());

或者,boost如果这是您的选择,请使用,例如:

#include <boost/algorithm/string.hpp>
boost::erase_all(str, "a");

所有这些都在参考 网站上有据可查。但是,如果您不了解这些功能,则可以轻松地手动执行以下操作:

std::string output;
output.reserve(str.size()); // optional, avoids buffer reallocations in the loop
for(size_t i = 0; i < str.size(); ++i)
  if(str[i] != 'a') output += str[i];

2
您提供的算法不是O(n^2)吗?
jww '16

@jww:我假设您正在谈论的是最后一个代码示例,并且n它是原始字符串长度。对于每个输入字符,我进行1个字符测试O(1),并附加0或1个字符。字符追加表示O(1)已保留足够的内存,或者O(current_length)分配了新的缓冲区。如果您output.reserve(str.size())在循环之前执行此操作,则此操作永远不会发生,并且会产生全局O(n)成本。否则,我认为代价是O(n . log(n) )由于STL容器重新分配策略而造成的。
Antoine

5
我需要#include <algorithm>
S Meaden

好答案。如果答案包含许多解决方案,那总是很好。对我来说,使用的解决方案for是最合适的。
德米特里·尼希波连科

@DmitryNichiporenko的答案不可能是最合适的。如果您有谓词或非空输出,则宁愿考虑:output.reserve(str.size()+ output.size()); std :: copy_if(str.begin(),str.end(),std :: back_inserter(output),[](char c){return predicate(c);});
jimifiki

10

该算法std::replace的工作原理每个元素在给定的顺序(因此它替换不同元素的元素,并不能取代它没有)。但是没有字符。如果要从序列中删除元素,则必须移动以下元素,并且std::replace不能这样工作。

您可以尝试使用std::removestd::erase)来实现这一点。

str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());

8

使用copy_if

#include <string>
#include <iostream>
#include <algorithm>
int main() {
    std::string s1 = "a1a2b3c4a5";
    char s2[256];
    std::copy_if(s1.begin(), s1.end(), s2, [](char c){return c!='a';});
    std::cout << s2 << std::endl;
    return 0;
}

3
string RemoveChar(string str, char c) 
{
   string result;
   for (size_t i = 0; i < str.size(); i++) 
   {
          char currentChar = str[i];
          if (currentChar != c)
              result += currentChar;
   }
       return result;
}

这就是我做的。

或者,您可以按照Antoine所述:

看到这个问题 回答同样的问题。在您的情况下:

#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());

1

此代码删除字符的重复,即,如果输入为aaaabbcc,则输出为abc。

cin >> s;
ans = "";
ans += s[0];
for(int i = 1;i < s.length();++i)
if(s[i] != s[i-1])
    ans += s[i];
cout << ans << endl;

1

如果您有一个predicate和/或一个非空output来填充过滤后的字符串,我会考虑:

output.reserve(str.size() + output.size());  
std::copy_if(str.cbegin(), 
             str.cend(), 
             std::back_inserter(output), 
             predicate});

在原始问题中,谓词是 [](char c){return c != 'a';}


0

根据其他答案,这里还有一个示例,其中我删除了给定字符串中的所有特殊字符:

#include <iostream>
#include <string>
#include <algorithm>

std::string chars(".,?!.:;_,!'\"-");

int main(int argc, char const *argv){

  std::string input("oi?");
  std::string output = eraseSpecialChars(input);   

 return 0;
}




std::string eraseSpecialChars(std::string str){

std::string newStr;
    newStr.assign(str);  

    for(int i = 0; i < str.length(); i++){
        for(int  j = 0; j < chars.length(); j++ ){
            if(str.at(i) == chars.at(j)){
                char c = str.at(i);
                newStr.erase(std::remove(newStr.begin(), newStr.end(), c), newStr.end());
            }
        }

    }      

return newStr; 
}

输入与输出:

Input:ra,..pha
Output:rapha

Input:ovo,
Output:ovo

Input:a.vo
Output:avo

Input:oi?
Output:oi

-1

我猜方法std:remove可以用,但是它给include带来了一些兼容性问题,所以我最终写了这个小函数:

string removeCharsFromString(const string str, char* charsToRemove )
{
    char c[str.length()+1]; // + terminating char
    const char *p = str.c_str();
    unsigned int z=0, size = str.length();
    unsigned int x;
    bool rem=false;

    for(x=0; x<size; x++)
    {
        rem = false;
        for (unsigned int i = 0; charsToRemove[i] != 0; i++)
        {
            if (charsToRemove[i] == p[x])
            {
                rem = true;
                break;
            }
        }
        if (rem == false) c[z++] = p[x];
    }

    c[z] = '\0';
    return string(c);
}

只是用作

myString = removeCharsFromString(myString,“ abc \ r”);

它将删除所有出现的给定字符列表。

随着循环在第一次匹配后返回,这也可能会更有效率,因此我们实际上进行的比较较少。


1
你猜对了。与其自行编写,不如更好地了解为什么不能使用标准C ++标头。
xtofl

好吧,这是xtofl的个人观点。使用第三代码实际上并不总会好,而实际上您不知道它的功能或性能,而不是编写您特别需要的代码。
Damien

1
我明白你的意思。谦卑让我选择了经过专业的全职图书馆作家而不是我自己的作品进行审查,测试和优化的版本。该标准库可视为必要的知识:它的功能以及其运行时的复杂性。
xtofl

除了字符串,这是C ++问题的C解决方案。我认为这不应该被否决。
猫头鹰

-1

这是我的方法:

std::string removeAll(std::string str, char c) {
    size_t offset = 0;
    size_t size = str.size();

    size_t i = 0;
    while (i < size - offset) {
        if (str[i + offset] == c) {
            offset++;
        }

        if (offset != 0) {
            str[i] = str[i + offset];
        }

        i++;
    }

    str.resize(size - offset);
    return str;
}

基本上,每当找到给定的char时,我都会提前偏移量并将char重新定位到正确的索引。我不知道这是正确还是有效,我从C ++开始(再次),对此我将不胜感激。


4
回顾四个月后的这个问题,我真的不知道为什么我不使用std :: erase或std :: replace。
里卡多·皮珀

-3
#include <string>
#include <algorithm>
std::string str = "YourString";
char chars[] = {'Y', 'S'};
str.erase (std::remove(str.begin(), str.end(), chars[i]), str.end());

将删除str中的大写字母Y和S,保留“替代”。

请注意,这remove是一种算法,需要<algorithm>包含标头。


是的,我认为他遗漏的数组字符存在隐式循环
RichardPlunkett
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.