用另一个字符串替换字符串的一部分

时间:2010-08-05 19:06:13

标签: c++ string replace substring std

在C ++中是否可以用另一个字符串替换部分字符串?

基本上,我想这样做:

QString string("hello $name");
string.replace("$name", "Somename");

但我想使用标准C ++库。

15 个答案:

答案 0 :(得分:257)

有一个函数可以在字符串中找到一个子字符串(find),还有一个用另一个字符串(replace)替换字符串中特定范围的函数,所以你可以将它们组合起来得到你想要的效果:

bool replace(std::string& str, const std::string& from, const std::string& to) {
    size_t start_pos = str.find(from);
    if(start_pos == std::string::npos)
        return false;
    str.replace(start_pos, from.length(), to);
    return true;
}

std::string string("hello $name");
replace(string, "$name", "Somename");

在回复评论时,我认为replaceAll可能看起来像这样:

void replaceAll(std::string& str, const std::string& from, const std::string& to) {
    if(from.empty())
        return;
    size_t start_pos = 0;
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
    }
}

答案 1 :(得分:72)

使用C ++ 11,您可以使用std::regex,如下所示:

    std::string string("hello $name");
    string = std::regex_replace(string, std::regex("\\$name"), "Somename");

转义转义字符需要双反斜杠。

答案 2 :(得分:17)

std::stringreplace方法,您正在寻找什么?

你可以尝试:

s.replace(s.find("$name"), sizeof("$name") - 1, "Somename");

我没有尝试过,只需阅读find()replace()上的文档。

答案 3 :(得分:8)

要返回新字符串,请使用:

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

答案 4 :(得分:6)

是的,你可以这样做,但你必须找到带有字符串的find()成员的第一个字符串的位置,然后用它的replace()成员替换。

string s("hello $name");
size_type pos = s.find( "$name" );
if ( pos != string::npos ) {
   s.replace( pos, 5, "somename" );   // 5 = length( $name )
}

如果您打算使用标准库,您应该真正掌握一本书The C++ Standard Library的副本,其中涵盖了所有这些内容。

答案 5 :(得分:4)

我通常使用这个:

std::string& replace(std::string& s, const std::string& from, const std::string& to)
{
    if(!from.empty())
        for(size_t pos = 0; (pos = s.find(from, pos)) != std::string::npos; pos += to.size())
            s.replace(pos, from.size(), to);
    return s;
}

它反复调用std::string::find()来查找搜索到的字符串的其他匹配项,直到std::string::find()找不到任何内容。由于std::string::find()返回匹配的位置,因此我们没有使迭代器无效的问题。

答案 6 :(得分:4)

这听起来像一个选项

string.replace(string.find("%s"), string("%s").size(), "Something");

你可以将它包装在一个函数中,但这个单行解决方案听起来是可以接受的。 问题是这只会改变第一次出现,你可能想要循环它,但它也允许你用相同的标记(%s

将几个变量插入到这个字符串中

答案 7 :(得分:3)

如果所有字符串都是std :: string,那么如果使用sizeof(),你会发现字符截止的奇怪问题,因为它意味着C字符串,而不是C ++字符串。修复方法是使用.size()的{​​{1}}类方法。

std::string

用内联替换sHaystack - 不需要在那里做一个=赋值。

使用示例:

sHaystack.replace(sHaystack.find(sNeedle), sNeedle.size(), sReplace);

答案 8 :(得分:2)

std::string replace(std::string base, const std::string from, const std::string to) {
    std::string SecureCopy = base;

    for (size_t start_pos = SecureCopy.find(from); start_pos != std::string::npos; start_pos = SecureCopy.find(from,start_pos))
    {
        SecureCopy.replace(start_pos, from.length(), to);
    }

    return SecureCopy;
}

答案 9 :(得分:1)

wstring myString = L"Hello $$ this is an example. By $$.";
wstring search = L"$$";
wstring replace = L"Tom";
for (int i = myString.find(search); i >= 0; i = myString.find(search))
    myString.replace(i, search.size(), replace);

答案 10 :(得分:1)

如果您想快速完成,可以使用双扫描方法。 伪代码:

  1. 首先解析。找到多少匹配的字符。
  2. 扩展字符串的长度。
  3. 第二次解析。当我们获得匹配时,从字符串的结尾开始,否则我们只是从第一个字符串中复制字符。
  4. 我不确定这是否可以针对就地算法进行优化。

    一个C ++ 11代码示例,但我只搜索一个字符。

    #include <string>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    void ReplaceString(string& subject, char search, const string& replace)
    {   
        size_t initSize = subject.size();
        int count = 0;
        for (auto c : subject) { 
            if (c == search) ++count;
        }
    
        size_t idx = subject.size()-1 + count * replace.size()-1;
        subject.resize(idx + 1, '\0');
    
        string reverseReplace{ replace };
        reverse(reverseReplace.begin(), reverseReplace.end());  
    
        char *end_ptr = &subject[initSize - 1];
        while (end_ptr >= &subject[0])
        {
            if (*end_ptr == search) {
                for (auto c : reverseReplace) {
                    subject[idx - 1] = c;
                    --idx;              
                }           
            }
            else {
                subject[idx - 1] = *end_ptr;
                --idx;
            }
            --end_ptr;
        }
    }
    
    int main()
    {
        string s{ "Mr John Smith" };
        ReplaceString(s, ' ', "%20");
        cout << s << "\n";
    
    }
    

答案 11 :(得分:0)

我刚刚学习C ++,但是编辑之前发布的一些代码,我可能会使用这样的东西。这使您可以灵活地替换1个或多个实例,还可以指定起点。

using namespace std;

// returns number of replacements made in string
long strReplace(string& str, const string& from, const string& to, size_t start = 0, long count = -1) {
    if (from.empty()) return 0;

    size_t startpos = str.find(from, start);
    long replaceCount = 0;

    while (startpos != string::npos){
        str.replace(startpos, from.length(), to);
        startpos += to.length();
        replaceCount++;

        if (count > 0 && replaceCount >= count) break;
        startpos = str.find(from, startpos);
    }

    return replaceCount;
}

答案 12 :(得分:0)

我自己的实现,考虑到只需要调整一次字符串的大小,然后可以进行替换。

template <typename T>
std::basic_string<T> replaceAll(const std::basic_string<T>& s, const T* from, const T* to)
{
    auto length = std::char_traits<T>::length;
    size_t toLen = length(to), fromLen = length(from), delta = toLen - fromLen;
    bool pass = false;
    std::string ns = s;

    size_t newLen = ns.length();

    for (bool estimate : { true, false })
    {
        size_t pos = 0;

        for (; (pos = ns.find(from, pos)) != std::string::npos; pos++)
        {
            if (estimate)
            {
                newLen += delta;
                pos += fromLen;
            }
            else
            {
                ns.replace(pos, fromLen, to);
                pos += delta;
            }
        }

        if (estimate)
            ns.resize(newLen);
    }

    return ns;
}

用法例如:

std::string dirSuite = replaceAll(replaceAll(relPath.parent_path().u8string(), "\\", "/"), ":", "");

答案 13 :(得分:0)

这可能更好用

void replace(string& input, const string& from, const string& to)
{
    while(true)
    {
        size_t startPosition = input.find(from);
        if(startPosition == string::npos)
            break;
        input.replace(startPosition, from.length(), to);
    }
}

答案 14 :(得分:0)

您可以使用此代码删除subtring,也可以替换,也可以删除多余的空白。 代码:

#include<bits/stdc++.h>
using namespace std ;
void removeSpaces(string &str)
{
   
    int n = str.length();

    int i = 0, j = -1;

    bool spaceFound = false;

    while (++j <= n && str[j] == ' ');

    while (j <= n)
    {
        if (str[j] != ' ')
        {
          
            if ((str[j] == '.' || str[j] == ',' ||
                 str[j] == '?') && i - 1 >= 0 &&
                 str[i - 1] == ' ')
                str[i - 1] = str[j++];

            else
                
                str[i++] = str[j++];

            
            spaceFound = false;
        }
        else if (str[j++] == ' ')
        {
            
            if (!spaceFound)
            {
                str[i++] = ' ';
                spaceFound = true;
            }
        }
    }

    if (i <= 1)
        str.erase(str.begin() + i, str.end());
    else
        str.erase(str.begin() + i - 1, str.end());
}
int main()
{
    string s;
    cin>>s;
    for(int i=s.find("WUB");i>=0;i=s.find("WUB"))
    {
        s.replace(i,3," ");
    }
    removeSpaces(s);
    cout<<s<<endl;

    return 0;
}