如何查找和替换字符串

How to find and replace string?

本文关键字:替换 字符串 查找 何查找      更新时间:2023-10-16

如果s是一个std::string,那么有没有像下面这样的函数?

s.replace("text to replace", "new text");

替换第一个匹配项

使用 std::string::find 查找字符串的第一个匹配项toReplace .
使用 std::string::replace 将该匹配项替换为字符串 replaceWith

此函数执行以下操作:

void replace_first(
    std::string& s,
    std::string const& toReplace,
    std::string const& replaceWith
) {
    std::size_t pos = s.find(toReplace);
    if (pos == std::string::npos) return;
    s.replace(pos, toReplace.length(), replaceWith);
}

用法:

replace_first(s, "text to replace", "new text");

演示。

<小时 />

替换所有匹配项

使用 std::string 作为缓冲区定义此 O(n( 方法:

void replace_all(
    std::string& s,
    std::string const& toReplace,
    std::string const& replaceWith
) {
    std::string buf;
    std::size_t pos = 0;
    std::size_t prevPos;
    // Reserves rough estimate of final size of string.
    buf.reserve(s.size());
    while (true) {
        prevPos = pos;
        pos = s.find(toReplace, pos);
        if (pos == std::string::npos)
            break;
        buf.append(s, prevPos, pos - prevPos);
        buf += replaceWith;
        pos += toReplace.size();
    }
    buf.append(s, prevPos, s.size() - prevPos);
    s.swap(buf);
}

用法:

replace_all(s, "text to replace", "new text");

演示。

<小时 />

提高

或者,使用 boost::algorithm::replace_all

#include <boost/algorithm/string.hpp>
using boost::replace_all;

用法:

replace_all(s, "text to replace", "new text");

我们真的需要一个 Boost 库来完成看似如此简单的任务吗?

要替换子字符串的所有匹配项,请使用此函数:

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;
}

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

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();
    }
}

测试:

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 modified: " 
          << input << std::endl;
ReplaceStringInPlace(input, "bc", "??");
std::cout << "ReplaceStringInPlace() input string modified: " 
          << input << std::endl;

输出:

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

是的:replace_all 是提升字符串算法之一:

虽然它不是标准库,但它在标准库中有一些东西:

  1. 基于范围而不是迭代器对的更自然的表示法。这很好,因为您可以嵌套字符串操作(例如,replace_all嵌套在trim中(。对于标准库函数来说,这有点复杂。
  2. 完整性。这并不难"更好";标准库相当简陋。例如,boost 字符串算法使您可以显式控制字符串操作的执行方式(即就地或通过副本(。
#include <iostream>
#include <string>
using namespace std;
int main ()
{
    string str("one three two four");
    string str2("three");
    str.replace(str.find(str2),str2.length(),"five");
    cout << str << endl;
    return 0;
}

输出

one five two four

就像有人说的boost::replace_all

这里有一个虚拟的例子:

    #include <boost/algorithm/string/replace.hpp>
    std::string path("file.gz");
    boost::replace_all(path, ".gz", ".zip");

不完全是这样,但std::string有许多replace重载函数。

浏览此链接以查看每个解释,并提供有关它们如何使用的示例。

此外,string::find函数有多个版本(如下所示(,您可以将其与string::replace结合使用。

  • 找到
  • 查找
  • find_first_of
  • find_last_of
  • find_first_not_of
  • find_last_not_of

另外,请注意,<algorithm>中提供了多个版本的replace函数,您也可以使用(而不是string::replace(:

  • 取代
  • replace_if
  • replace_copy
  • replace_copy_if
// replaced text will be in buffer.
void Replace(char* buffer, const char* source, const char* oldStr,  const char* newStr)
{
    if(buffer==NULL || source == NULL || oldStr == NULL || newStr == NULL) return; 
    int slen = strlen(source);
    int olen = strlen(oldStr);
    int nlen = strlen(newStr);
    if(olen>slen) return;
    int ix=0;
    for(int i=0;i<slen;i++)
    {
        if(oldStr[0] == source[i])
        {
            bool found = true;
            for(int j=1;j<olen;j++)
            {
                if(source[i+j]!=oldStr[j])
                {
                    found = false;
                    break;
                }
            }
            if(found)
            {
                for(int j=0;j<nlen;j++)
                    buffer[ix++] = newStr[j];
                i+=(olen-1);
            }
            else
            {
                buffer[ix++] = source[i];
            }
        }
        else
        {
            buffer[ix++] = source[i];
        }
    }
}

这是我最终编写的版本,它替换了给定字符串中目标字符串的所有实例。适用于任何字符串类型。

template <typename T, typename U>
T &replace (
          T &str, 
    const U &from, 
    const U &to)
{
    size_t pos;
    size_t offset = 0;
    const size_t increment = to.size();
    while ((pos = str.find(from, offset)) != T::npos)
    {
        str.replace(pos, from.size(), to);
        offset = pos + increment;
    }
    return str;
}

例:

auto foo = "this is a test"s;
replace(foo, "is"s, "wis"s);
cout << foo;

输出:

thwis wis a test

请注意,即使搜索字符串出现在替换字符串中,这也可以正常工作。

void replace(char *str, char *strFnd, char *strRep)
{
    for (int i = 0; i < strlen(str); i++)
    {
        int npos = -1, j, k;
        if (str[i] == strFnd[0])
        {
            for (j = 1, k = i+1; j < strlen(strFnd); j++)
                if (str[k++] != strFnd[j])
                    break;
            npos = i;
        }
        if (npos != -1)
            for (j = 0, k = npos; j < strlen(strRep); j++)
                str[k++] = strRep[j];
    }
}
int main()
{
    char pst1[] = "There is a wrong message";
    char pfnd[] = "wrong";
    char prep[] = "right";
    cout << "nintial:" << pst1;
    replace(pst1, pfnd, prep);
    cout << "nfinal : " << pst1;
    return 0;
}
void replaceAll(std::string & data, const std::string &toSearch, const std::string &replaceStr)
{
    // Get the first occurrence
    size_t pos = data.find(toSearch);
    // Repeat till end is reached
    while( pos != std::string::npos)
    {
        // Replace this occurrence of Sub String
        data.replace(pos, toSearch.size(), replaceStr);
        // Get the next occurrence from the current position
        pos =data.find(toSearch, pos + replaceStr.size());
    }
}

更多 CPP 公用事业:https://github.com/Heyshubham/CPP-Utitlities/blob/master/src/MEString.cpp#L60

有没有像下面这样的功能?

另一种(除了使用不同答案中给出的boost和其他方法(可能的方法是使用如下所示的std::regex_replace

    std::string s{"my name is my name and not my name mysometext myto"}; //this is the original line
    
    std::string replaceThis = "my";
    std::string replaceWith = "your";
    
    std::regex pattern("\b" + replaceThis + "\b");
    
    std::string replacedLine = std::regex_replace(s, pattern, replaceWith);
    std::cout<<replacedLine<<std::endl;