C++字符替换

8

什么是替换字符串中字符的最佳方法?

具体来说:

"This,Is A|Test" ----> "This_Is_A_Test"

我希望你能把所有的逗号、空格和“|”替换成下划线。(我可以使用Boost库。)

这是一个 std::string 类型的字符串,还是一个带有终止符“\0”的 char 类型数组? - PP.
6
我认为各种"replace_if"的答案,例如UncleBens的回答,都很不错。不过,总的来说:如果您想替换字符以获得安全用于文件名等用途的东西,您应该列出允许使用的字符,并替换其他所有字符,而不是反过来。这样,您就不会受到任何您没有考虑到的奇怪输入的影响。 - Rasmus Kaj
7个回答

16

您可以使用标准的replace_if算法,但谓词相当复杂(在当前的C++标准下内联表达,并且没有lambda)。

您可以编写自己的替换函数,或者使用boost字符串算法中的is_any_of,如下所示:

#include <algorithm>
#include <string>
#include <boost/algorithm/string/classification.hpp>
#include <iostream>

int main()
{
    std::string s("This,Is A|Test");
    std::replace_if(s.begin(), s.end(), boost::is_any_of(", |"), '_');
    std::cout << s << '\n';
}

11

9

正如其他答案所示,您可以使用各种replace方法。但是,这些方法的缺点是需要多次扫描字符串(每个字符扫描一次)。如果您关心速度,我建议自己编写替换方法:

void beautify(std::string &s) {
    int i;
    for (i = 0; i < s.length(); ++i) {
        switch (s[i]) {
        case ' ':
        case ',':
        case '|':
            s[i] = '_';
        }
    }
}

一行替换方法很好,但你的解决方案也很有效。 - user195488
一行替换肯定更好(我认为你至少需要几行),但效率不高。 - notnoop
我认为replace_if不会多次扫描字符串。 - Brian

3

编辑:正如Space_C0wb0y所说,replace_if肯定更好。下面是一些更简单的示例代码:

#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

bool isBad(char c)
{
 const string bad_chars = "|, ";
 return (bad_chars.find(c) != string::npos);
}

int main()
{
 string str = "This,Is A|Test";

 // Replace!
 replace_if(str.begin(),str.end(),isBad,'_');

 cout<<str<<endl; 
 return 0;
}

新的回答:

使用std::find_first_ofstd::replace函数进行替换操作。


2

boost::replace_all(s, old, new);


0

C++标准库也可以访问这些函数,而不需要使用BOOST。请参考C++参考手册。这是最好的方法吗?我想这取决于讨论。要替换多个/不同的字符,可能需要调用多次replace。

#include <string>
    string& replace( size_type index, size_type num, const string& str );
    string& replace( size_type index1, size_type num1, const string& str, size_type index2, size_type num2 );
    string& replace( size_type index, size_type num, const Char* str );
    string& replace( size_type index, size_type num1, const Char* str, size_type num2 );
    string& replace( size_type index, size_type num1, size_type num2, Char ch);

    string& replace( iterator start, iterator end, const string& str );
    string& replace( iterator start, iterator end, const Char* str );
    string& replace( iterator start, iterator end, const Char* str, size_type num );
    string& replace( iterator start, iterator end, size_type num, Char ch );
    string& replace( iterator start, iterator end, input_iterator start2, input_iterator end2 );

示例程序

// replacing in a string
#include <iostream>
#include <string>
using namespace std;

int main ()
{
  string base="this is a test string.";
  string str2="n example";
  string str3="sample phrase";
  string str4="useful.";

  // function versions used in the same order as described above:

  // Using positions:                 0123456789*123456789*12345
  string str=base;                // "this is a test string."
  str.replace(9,5,str2);          // "this is an example string."
  str.replace(19,6,str3,7,6);     // "this is an example phrase."
  str.replace(8,10,"just all",6); // "this is just a phrase."
  str.replace(8,6,"a short");     // "this is a short phrase."
  str.replace(22,1,3,'!');        // "this is a short phrase!!!"

  // Using iterators:                      0123456789*123456789*
  string::iterator it = str.begin();   //  ^
  str.replace(it,str.end()-3,str3);    // "sample phrase!!!"
  str.replace(it,it+6,"replace it",7); // "replace phrase!!!"
  it+=8;                               //          ^
  str.replace(it,it+6,"is cool");      // "replace is cool!!!"
  str.replace(it+4,str.end()-4,4,'o'); // "replace is cooool!!!"
  it+=3;                               //             ^
  str.replace(it,str.end(),str4.begin(),str4.end());
                                       // "replace is useful."
  cout << str << endl;
  return 0;
}

replace方法只替换一个字符(范围),而不是所有出现的内容,所以我认为它确实对这个任务没有太大帮助 :) - UncleBens
罗杰。这就是为什么我说它需要运行多次的原因。是否是最佳方法,取决于开发人员。 - user195488
实际上,您可能会让水更加浑浊。string::replace用于将单个范围替换为另一个字符串(或字符)。OP想要替换单个字符,因此您可以指向operator[]而不是重量级的replace方法,该方法允许您“替换”单个字符的值。 - UncleBens

0

当 Space_C0wb0y 发布他的答案时,我正在撰写这篇文章,他的回答是你问题的正确答案。这个方法有些复杂,但可以处理更多可能的替换。

(抱歉,未编译/测试)

class MyReplacer
{
  friend std::ostream& operator<<(std::ostream& os, const MyReplacer& Repl);
  public:
    MyReplacer(char c) : ch(c) {}
  private:
    char ch;
};

std::ostream& operator<<(std::ostream& os, const MyReplacer& Repl)
{
  switch (Repl.ch)
  {
    case '|':
    case ' ':
    case ',': os << '_'; break;
    default: os << Repl.ch;
  }
  return os;
}


std::ostringstream oss;
std::copy(str.begin(), str.end(), std::ostream_iterator<MyReplacer>(oss));
std::string result = oss.str();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接