如何在没有正则表达式的情况下在C++中实现有效的全字符串替换?

sak*_*atc 5 c++ string visual-c++

也许我忽略了一些显而易见的事情,但我想知道在C++中实现全字符串替换的最快方法是什么.起初我考虑简单地将空格连接到搜索词,但这不考虑字符串边界或标点符号.

这是我目前对(非全字)替换的抽象:

void Replace(wstring& input, wstring find, wstring replace_with) {
  if (find.empty() || find == replace_with || input.length() < find.length()) {
      return;
  }
  for (size_t pos = input.find(find); 
              pos != wstring::npos; 
              pos = input.find(find, pos)) {

      input.replace(pos, find.length(), replace_with);
      pos += replace_with.length();
  }
}
Run Code Online (Sandbox Code Playgroud)

如果我只考虑空格作为单词边界,我可以通过比较搜索字符串的开头和结尾与查找字符串来覆盖字符串边界,然后使用替换(L''+ find + L')来实现这一点. ') ....但我想知道是否有一个更优雅的解决方案,有效地包括标点符号.

让我们考虑一个词是被用空白或者标点符号隔开任何字符集(保持它的简单让我们说"#$%&'()*+, - ./最低-这恰好对应(c > 31 && c < 48)) .

在我的应用程序中,我必须在一个相当大的短字符串数组上调用此函数,其中可能包含各种Unicode,我不想拆分新单词.我还想避免包含任何外部库,但STL很好.

不使用正则表达式的目的是减少开销的承诺,以及适合于在大型数据集上执行此特定任务的快速函数的目标.

Cha*_*cox 3

我认为你可以做到这一点,既可以进行全字匹配,又可以高效地进行。关键是:

  • 使用“std::isalpha”检测“整个单词”边界,它应该适用于 Unicode 和任何语言环境。
  • 通过创建一个单独的“输出”字符串来进行“不合适的”替换,在处理结束时将其与“输入”交换,而不是在“输入”字符串本身上“就地”进行工作。

这是我对你的职能的看法:

#include <cctype> // isalpha
#include <ciso646> // or, not
#include <string> // wstring

using std::size_t;
using std::wstring;

/// @brief Do a "find and replace" on a string.
/// @note This function does "whole-word" matching.
/// @param[in,out] input_string The string to operate on.
/// @param[in] find_string The string to find in the input.
/// @param[in] replace_string The string to replace 'find_string'
///            with in the input.
void find_and_replace( wstring& input_string,
                       const wstring& find_string,
                       const wstring& replace_string )
{
  if( find_string.empty()
      or find_string == replace_string
      or input_string.length() < find_string.length() )
  {
    return;
  }

  wstring output_string;
  output_string.reserve( input_string.length() );
  size_t last_pos = 0u;
  for( size_t new_pos = input_string.find( find_string );
       new_pos != wstring::npos;
       new_pos = input_string.find( find_string, new_pos ) )
  {
    bool did_replace = false;
    if( ( new_pos == 0u
          or not std::isalpha( input_string.at( new_pos - 1u ) ) )
        and ( new_pos + find_string.length() == input_string.length()
              or not std::isalpha( input_string.at( new_pos + find_string.length() ) ) ) )
    {
      output_string.append( input_string, last_pos, new_pos - last_pos );
      output_string.append( replace_string );
      did_replace = true;
    }
    new_pos += find_string.length();
    if( did_replace )
    {
      last_pos = new_pos;
    }
  }
  output_string.append( input_string, last_pos,
                        input_string.length() - last_pos );

  input_string.swap( output_string );
}
Run Code Online (Sandbox Code Playgroud)

PS 我不确定“replace_all”在您最初的示例中试图完成什么,因此为了清楚起见,我将其从解决方案中删除了。

PPS 如果使用 Regex-es,这段代码会更加简洁。您可以依赖 C++ TR1 或 C++ 2011 功能吗?他们提供了一个标准的“正则表达式”库。