如何在标准字符串中搜索/查找和替换?

时间:2022-02-05 16:48:04

Is there a way to replace all occurrences of a substring with another string in std::string?

有办法用std::string中的另一个字符串替换所有出现的子字符串吗?

For instance:

例如:

void SomeFunction(std::string& str)
{
   str = str.replace("hello", "world"); //< I'm looking for something nice like this
}

10 个解决方案

#1


65  

Why not implement your own replace?

为什么不实现自己的替换呢?

void myReplace(std::string& str,
               const std::string& oldStr,
               const std::string& newStr)
{
  std::string::size_type pos = 0u;
  while((pos = str.find(oldStr, pos)) != std::string::npos){
     str.replace(pos, oldStr.length(), newStr);
     pos += newStr.length();
  }
}

#2


137  

#include <boost/algorithm/string.hpp> // include Boost, a C++ library
...
std::string target("Would you like a foo of chocolate. Two foos of chocolate?");
boost::replace_all(target, "foo", "bar");

Here is the official documentation on replace_all.
Here is a presentation I've made in 2010 on Boost String Algorithms.

这是关于replace_all的官方文档。这是我在2010年做的关于Boost String算法的演示。

#3


17  

In C++11, you can do this as a one-liner with a call to regex_replace:

在c++ 11中,可以使用一行代码调用regex_replace:

#include <string>
#include <regex>

using std::string;

string do_replace( string const & in, string const & from, string const & to )
{
  return std::regex_replace( in, std::regex(from), to );
}

string test = "Remove all spaces";
std::cout << do_replace(test, " ", "") << std::endl;

output:

输出:

Removeallspaces

#4


13  

Why not return a modified string?

为什么不返回修改后的字符串呢?

std::string ReplaceString(std::string subject, const std::string& search,
                          const std::string& replace) {
    size_t pos = 0;
    while((pos = subject.find(search, pos)) != std::string::npos) {
         subject.replace(pos, search.length(), replace);
         pos += replace.length();
    }
    return subject;
}

If you need performance, here is an optimized function that modifies the input string, it does not create a copy of the string:

如果您需要性能,这里有一个优化函数来修改输入字符串,它不会创建字符串的副本:

void ReplaceStringInPlace(std::string& subject, const std::string& search,
                          const std::string& replace) {
    size_t pos = 0;
    while((pos = subject.find(search, pos)) != std::string::npos) {
         subject.replace(pos, search.length(), replace);
         pos += replace.length();
    }
}

Tests:

测试:

std::string input = "abc abc def";
std::cout << "Input string: " << input << std::endl;

std::cout << "ReplaceString() return value: " 
          << ReplaceString(input, "bc", "!!") << std::endl;
std::cout << "ReplaceString() input string not changed: " 
          << input << std::endl;

ReplaceStringInPlace(input, "bc", "??");
std::cout << "ReplaceStringInPlace() input string modified: " 
          << input << std::endl;

Output:

输出:

Input string: abc abc def
ReplaceString() return value: a!! a!! def
ReplaceString() input string not modified: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def

#5


6  

My templatized inline in-place find-and-replace:

我的模板内联就地查找和替换:

template<class T>
int inline findAndReplace(T& source, const T& find, const T& replace)
{
    int num=0;
    typename T::size_t fLen = find.size();
    typename T::size_t rLen = replace.size();
    for (T::size_t pos=0; (pos=source.find(find, pos))!=T::npos; pos+=rLen)
    {
        num++;
        source.replace(pos, fLen, replace);
    }
    return num;
}

It returns a count of the number of items substituted (for use if you want to successively run this, etc). To use it:

它返回替换项的数量(如果您想要连续运行该项,则用于使用)。使用它:

std::string str = "one two three";
int n = findAndReplace(str, "one", "1");

#6


3  

The easiest way (offering something near what you wrote) is to use Boost.Regex, specifically regex_replace.

最简单的方法(提供与您所写内容相近的内容)是使用Boost。正则表达式,特别是regex_replace。

std::string has built in find() and replace() methods, but they are more cumbersome to work with as they require dealing with indices and string lengths.

string已经内置了find()和replace()方法,但是由于它们需要处理索引和字符串长度,所以使用起来比较麻烦。

#7


3  

I believe this would work. It takes const char*'s as a parameter.

我相信这行得通。它以const char* s作为参数。

//params find and replace cannot be NULL
void FindAndReplace( std::string& source, const char* find, const char* replace )
{
   //ASSERT(find != NULL);
   //ASSERT(replace != NULL);
   size_t findLen = strlen(find);
   size_t replaceLen = strlen(replace);
   size_t pos = 0;

   //search for the next occurrence of find within source
   while ((pos = source.find(find, pos)) != std::string::npos)
   {
      //replace the found string with the replacement
      source.replace( pos, findLen, replace );

      //the next line keeps you from searching your replace string, 
      //so your could replace "hello" with "hello world" 
      //and not have it blow chunks.
      pos += replaceLen; 
   }
}

#8


1  

// Replace all occurrences of searchStr in str with replacer
// Each match is replaced only once to prevent an infinite loop
// The algorithm iterates once over the input and only concatenates 
// to the output, so it should be reasonably efficient
std::string replace(const std::string& str, const std::string& searchStr, 
    const std::string& replacer)
{
    // Prevent an infinite loop if the input is empty
    if (searchStr == "") {
        return str;
    }

    std::string result = "";
    size_t pos = 0;
    size_t pos2 = str.find(searchStr, pos);

    while (pos2 != std::string::npos) {
        result += str.substr(pos, pos2-pos) + replacer;
        pos = pos2 + searchStr.length();
        pos2 = str.find(searchStr, pos);
    }

    result += str.substr(pos, str.length()-pos);
    return result;
}

#9


0  

#include <iostream>
#include <string>

#include <boost/algorithm/string.hpp>
#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>

using namespace boost::algorithm;
using namespace std;
using namespace boost;

void highlighter(string terms, string text) {

    char_separator<char> sep(" ");
    tokenizer<char_separator<char> > tokens(terms, sep);

    BOOST_FOREACH(string term, tokens) {
        boost::replace_all(text, term, "<b>" + term + "</b>");
    }   
    cout << text << endl;
}

int main(int argc, char **argv)
{
    cout << "Search term highlighter" << endl;
    string text("I love boost library, and this is a test of boost library!");
    highlighter("love boost", text);
}

I love boost library, and this is a test of boost library!

我喜欢boost库,这是boost库的测试!

#10


0  

#include <string>

using std::string;

void myReplace(string& str,
               const string& oldStr,
               const string& newStr) {
  if (oldStr.empty()) {
    return;
  }

  for (size_t pos = 0; (pos = str.find(oldStr, pos)) != string::npos;) {
    str.replace(pos, oldStr.length(), newStr);
    pos += newStr.length();
  }
}

The check for oldStr being empty is important. If for whatever reason that parameter is empty you will get stuck in an infinite loop.

检查oldStr是否为空很重要。如果由于某种原因该参数为空,您将陷入无限循环。

But yeah use the tried and tested C++11 or Boost solution if you can.

但是如果可以的话,可以使用经过测试的c++ 11或者Boost解决方案。

#1


65  

Why not implement your own replace?

为什么不实现自己的替换呢?

void myReplace(std::string& str,
               const std::string& oldStr,
               const std::string& newStr)
{
  std::string::size_type pos = 0u;
  while((pos = str.find(oldStr, pos)) != std::string::npos){
     str.replace(pos, oldStr.length(), newStr);
     pos += newStr.length();
  }
}

#2


137  

#include <boost/algorithm/string.hpp> // include Boost, a C++ library
...
std::string target("Would you like a foo of chocolate. Two foos of chocolate?");
boost::replace_all(target, "foo", "bar");

Here is the official documentation on replace_all.
Here is a presentation I've made in 2010 on Boost String Algorithms.

这是关于replace_all的官方文档。这是我在2010年做的关于Boost String算法的演示。

#3


17  

In C++11, you can do this as a one-liner with a call to regex_replace:

在c++ 11中,可以使用一行代码调用regex_replace:

#include <string>
#include <regex>

using std::string;

string do_replace( string const & in, string const & from, string const & to )
{
  return std::regex_replace( in, std::regex(from), to );
}

string test = "Remove all spaces";
std::cout << do_replace(test, " ", "") << std::endl;

output:

输出:

Removeallspaces

#4


13  

Why not return a modified string?

为什么不返回修改后的字符串呢?

std::string ReplaceString(std::string subject, const std::string& search,
                          const std::string& replace) {
    size_t pos = 0;
    while((pos = subject.find(search, pos)) != std::string::npos) {
         subject.replace(pos, search.length(), replace);
         pos += replace.length();
    }
    return subject;
}

If you need performance, here is an optimized function that modifies the input string, it does not create a copy of the string:

如果您需要性能,这里有一个优化函数来修改输入字符串,它不会创建字符串的副本:

void ReplaceStringInPlace(std::string& subject, const std::string& search,
                          const std::string& replace) {
    size_t pos = 0;
    while((pos = subject.find(search, pos)) != std::string::npos) {
         subject.replace(pos, search.length(), replace);
         pos += replace.length();
    }
}

Tests:

测试:

std::string input = "abc abc def";
std::cout << "Input string: " << input << std::endl;

std::cout << "ReplaceString() return value: " 
          << ReplaceString(input, "bc", "!!") << std::endl;
std::cout << "ReplaceString() input string not changed: " 
          << input << std::endl;

ReplaceStringInPlace(input, "bc", "??");
std::cout << "ReplaceStringInPlace() input string modified: " 
          << input << std::endl;

Output:

输出:

Input string: abc abc def
ReplaceString() return value: a!! a!! def
ReplaceString() input string not modified: abc abc def
ReplaceStringInPlace() input string modified: a?? a?? def

#5


6  

My templatized inline in-place find-and-replace:

我的模板内联就地查找和替换:

template<class T>
int inline findAndReplace(T& source, const T& find, const T& replace)
{
    int num=0;
    typename T::size_t fLen = find.size();
    typename T::size_t rLen = replace.size();
    for (T::size_t pos=0; (pos=source.find(find, pos))!=T::npos; pos+=rLen)
    {
        num++;
        source.replace(pos, fLen, replace);
    }
    return num;
}

It returns a count of the number of items substituted (for use if you want to successively run this, etc). To use it:

它返回替换项的数量(如果您想要连续运行该项,则用于使用)。使用它:

std::string str = "one two three";
int n = findAndReplace(str, "one", "1");

#6


3  

The easiest way (offering something near what you wrote) is to use Boost.Regex, specifically regex_replace.

最简单的方法(提供与您所写内容相近的内容)是使用Boost。正则表达式,特别是regex_replace。

std::string has built in find() and replace() methods, but they are more cumbersome to work with as they require dealing with indices and string lengths.

string已经内置了find()和replace()方法,但是由于它们需要处理索引和字符串长度,所以使用起来比较麻烦。

#7


3  

I believe this would work. It takes const char*'s as a parameter.

我相信这行得通。它以const char* s作为参数。

//params find and replace cannot be NULL
void FindAndReplace( std::string& source, const char* find, const char* replace )
{
   //ASSERT(find != NULL);
   //ASSERT(replace != NULL);
   size_t findLen = strlen(find);
   size_t replaceLen = strlen(replace);
   size_t pos = 0;

   //search for the next occurrence of find within source
   while ((pos = source.find(find, pos)) != std::string::npos)
   {
      //replace the found string with the replacement
      source.replace( pos, findLen, replace );

      //the next line keeps you from searching your replace string, 
      //so your could replace "hello" with "hello world" 
      //and not have it blow chunks.
      pos += replaceLen; 
   }
}

#8


1  

// Replace all occurrences of searchStr in str with replacer
// Each match is replaced only once to prevent an infinite loop
// The algorithm iterates once over the input and only concatenates 
// to the output, so it should be reasonably efficient
std::string replace(const std::string& str, const std::string& searchStr, 
    const std::string& replacer)
{
    // Prevent an infinite loop if the input is empty
    if (searchStr == "") {
        return str;
    }

    std::string result = "";
    size_t pos = 0;
    size_t pos2 = str.find(searchStr, pos);

    while (pos2 != std::string::npos) {
        result += str.substr(pos, pos2-pos) + replacer;
        pos = pos2 + searchStr.length();
        pos2 = str.find(searchStr, pos);
    }

    result += str.substr(pos, str.length()-pos);
    return result;
}

#9


0  

#include <iostream>
#include <string>

#include <boost/algorithm/string.hpp>
#include <boost/tokenizer.hpp>
#include <boost/foreach.hpp>

using namespace boost::algorithm;
using namespace std;
using namespace boost;

void highlighter(string terms, string text) {

    char_separator<char> sep(" ");
    tokenizer<char_separator<char> > tokens(terms, sep);

    BOOST_FOREACH(string term, tokens) {
        boost::replace_all(text, term, "<b>" + term + "</b>");
    }   
    cout << text << endl;
}

int main(int argc, char **argv)
{
    cout << "Search term highlighter" << endl;
    string text("I love boost library, and this is a test of boost library!");
    highlighter("love boost", text);
}

I love boost library, and this is a test of boost library!

我喜欢boost库,这是boost库的测试!

#10


0  

#include <string>

using std::string;

void myReplace(string& str,
               const string& oldStr,
               const string& newStr) {
  if (oldStr.empty()) {
    return;
  }

  for (size_t pos = 0; (pos = str.find(oldStr, pos)) != string::npos;) {
    str.replace(pos, oldStr.length(), newStr);
    pos += newStr.length();
  }
}

The check for oldStr being empty is important. If for whatever reason that parameter is empty you will get stuck in an infinite loop.

检查oldStr是否为空很重要。如果由于某种原因该参数为空,您将陷入无限循环。

But yeah use the tried and tested C++11 or Boost solution if you can.

但是如果可以的话,可以使用经过测试的c++ 11或者Boost解决方案。