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

时间:2020-12-31 07:10:16

Is it possible in C++ to replace part of a string with another string?

在c++中有可能用另一个字符串替换字符串的一部分吗?

Basically, I would like to do this:

基本上,我想这样做:

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

But I would like to use the Standard C++ libraries.

但是我想使用标准的c++库。

13 个解决方案

#1


232  

There's a function to find a substring within a string (find), and a function to replace a particular range in a string with another string (replace), so you can combine those to get the effect you want:

有一个函数可以在字符串中查找子字符串(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");

In response to a comment, I think replaceAll would probably look something like this:

在回复评论时,我认为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'
    }
}

#2


54  

With C++11 you can use std::regex like so:

使用c++ 11,您可以使用std::regex如下:

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

The double backslash is required for escaping an escape character.

转义字符需要双反斜杠。

#3


15  

std::string has a replace method, is that what you are looking for?

string有一个replace方法,这就是你要找的吗?

You could try:

你可以试试:

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

I haven't tried myself, just read the documentation on find() and replace().

我还没有尝试,只是阅读了关于find()和replace()的文档。

#4


7  

To have the new string returned use this:

要返回新的字符串,请使用以下命令:

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 modified: " 
          << 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  

Yes, you can do it, but you have to find the position of the first string with string's find() member, and then replace with it's replace() member.

是的,您可以这样做,但是您必须使用string的find()成员查找第一个字符串的位置,然后使用它的replace()成员进行替换。

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

If you are planning on using the Standard Library, you should really get hold of a copy of the book The C++ Standard Library which covers all this stuff very well.

如果您打算使用标准库,那么您确实应该获得一本c++标准库的书,它很好地涵盖了所有这些内容。

#6


4  

This sounds like an option

这听起来像是一个选择

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

. replace(string.find(“% s”),字符串(“% s”).size(),“东西”);

You could wrap this in a function but this one-line solution sounds acceptable. The problem is that this will change the first occurence only, you might want to loop over it, but it also allows you to insert several variables into this string with the same token (%s)

你可以把它封装在一个函数中,但是这一行的解决方案听起来是可以接受的。问题是这只会改变第一次出现的情况,您可能希望对它进行循环,但是它也允许您使用相同的标记(%s)将多个变量插入到这个字符串中

#7


3  

If all strings are std::string, you'll find strange problems with the cutoff of characters if using sizeof() because it's meant for C strings, not C++ strings. The fix is to use the .size() class method of std::string.

如果所有字符串都是std::string,那么如果使用sizeof(),您会发现字符截断的奇怪问题,因为它是针对C字符串而不是c++字符串。修正方法是使用std::string的.size()类方法。

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

That replaces sHaystack inline -- no need to do an = assignment back on that.

这样就可以将sHaystack替换为内联——不需要再做一个=赋值。

Example usage:

使用示例:

std::string sHaystack = "This is %XXX% test.";
std::string sNeedle = "%XXX%";
std::string sReplace = "my special";
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
std::cout << sHaystack << std::endl;

#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  

I use generally this:

我通常使用:

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

It repeatedly calls std::string::find() to locate other occurrences of the searched for string until std::string::find() doesn't find anything. Because std::string::find() returns the position of the match we don't have the problem of invalidating iterators.

它反复调用std::string::find()来查找搜索字符串中其他出现的位置,直到std:::string: find()没有找到任何东西为止。因为std::string::find()返回匹配项的位置,所以我们没有无效迭代器的问题。

#10


1  

If you want to do it quickly you can use a two scan approach. Pseudo code:

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

  1. first parse. find how many matching chars.
  2. 首先解析。找出匹配的字符数。
  3. expand the length of the string.
  4. 展开字符串的长度。
  5. second parse. Start from the end of the string when we get a match we replace, else we just copy the chars from the first string.
  6. 第二个解析。从字符串的末尾开始当我们替换匹配时,否则我们就从第一个字符串中复制chars。

I am not sure if this can be optimized to an in-place algo.

我不确定这是否可以优化为一个到位的algo。

And a C++11 code example but I only search for one char.

还有一个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  

I'm just now learning C++, but editing some of the code previously posted, I'd probably use something like this. This gives you the flexibility to replace 1 or multiple instances, and also lets you specify the start point.

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

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  

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

#13


-2  

Why not just use a variable? It's way easier to maintain.
str name = "Adam"; str foo = "Hello " + name;

为什么不用变量呢?它更容易维护。str name =“亚当”;str foo = "Hello " + name;

#1


232  

There's a function to find a substring within a string (find), and a function to replace a particular range in a string with another string (replace), so you can combine those to get the effect you want:

有一个函数可以在字符串中查找子字符串(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");

In response to a comment, I think replaceAll would probably look something like this:

在回复评论时,我认为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'
    }
}

#2


54  

With C++11 you can use std::regex like so:

使用c++ 11,您可以使用std::regex如下:

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

The double backslash is required for escaping an escape character.

转义字符需要双反斜杠。

#3


15  

std::string has a replace method, is that what you are looking for?

string有一个replace方法,这就是你要找的吗?

You could try:

你可以试试:

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

I haven't tried myself, just read the documentation on find() and replace().

我还没有尝试,只是阅读了关于find()和replace()的文档。

#4


7  

To have the new string returned use this:

要返回新的字符串,请使用以下命令:

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 modified: " 
          << 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  

Yes, you can do it, but you have to find the position of the first string with string's find() member, and then replace with it's replace() member.

是的,您可以这样做,但是您必须使用string的find()成员查找第一个字符串的位置,然后使用它的replace()成员进行替换。

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

If you are planning on using the Standard Library, you should really get hold of a copy of the book The C++ Standard Library which covers all this stuff very well.

如果您打算使用标准库,那么您确实应该获得一本c++标准库的书,它很好地涵盖了所有这些内容。

#6


4  

This sounds like an option

这听起来像是一个选择

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

. replace(string.find(“% s”),字符串(“% s”).size(),“东西”);

You could wrap this in a function but this one-line solution sounds acceptable. The problem is that this will change the first occurence only, you might want to loop over it, but it also allows you to insert several variables into this string with the same token (%s)

你可以把它封装在一个函数中,但是这一行的解决方案听起来是可以接受的。问题是这只会改变第一次出现的情况,您可能希望对它进行循环,但是它也允许您使用相同的标记(%s)将多个变量插入到这个字符串中

#7


3  

If all strings are std::string, you'll find strange problems with the cutoff of characters if using sizeof() because it's meant for C strings, not C++ strings. The fix is to use the .size() class method of std::string.

如果所有字符串都是std::string,那么如果使用sizeof(),您会发现字符截断的奇怪问题,因为它是针对C字符串而不是c++字符串。修正方法是使用std::string的.size()类方法。

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

That replaces sHaystack inline -- no need to do an = assignment back on that.

这样就可以将sHaystack替换为内联——不需要再做一个=赋值。

Example usage:

使用示例:

std::string sHaystack = "This is %XXX% test.";
std::string sNeedle = "%XXX%";
std::string sReplace = "my special";
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
std::cout << sHaystack << std::endl;

#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  

I use generally this:

我通常使用:

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

It repeatedly calls std::string::find() to locate other occurrences of the searched for string until std::string::find() doesn't find anything. Because std::string::find() returns the position of the match we don't have the problem of invalidating iterators.

它反复调用std::string::find()来查找搜索字符串中其他出现的位置,直到std:::string: find()没有找到任何东西为止。因为std::string::find()返回匹配项的位置,所以我们没有无效迭代器的问题。

#10


1  

If you want to do it quickly you can use a two scan approach. Pseudo code:

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

  1. first parse. find how many matching chars.
  2. 首先解析。找出匹配的字符数。
  3. expand the length of the string.
  4. 展开字符串的长度。
  5. second parse. Start from the end of the string when we get a match we replace, else we just copy the chars from the first string.
  6. 第二个解析。从字符串的末尾开始当我们替换匹配时,否则我们就从第一个字符串中复制chars。

I am not sure if this can be optimized to an in-place algo.

我不确定这是否可以优化为一个到位的algo。

And a C++11 code example but I only search for one char.

还有一个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  

I'm just now learning C++, but editing some of the code previously posted, I'd probably use something like this. This gives you the flexibility to replace 1 or multiple instances, and also lets you specify the start point.

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

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  

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

#13


-2  

Why not just use a variable? It's way easier to maintain.
str name = "Adam"; str foo = "Hello " + name;

为什么不用变量呢?它更容易维护。str name =“亚当”;str foo = "Hello " + name;