C++ 用另一个字符串替换部分字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3418231/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Replace part of a string with another string
提问by Tom Leese
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++ 库。
回答by Michael Mrozek
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'
}
}
回答by Tom
With C++11 you can use std::regex
like so:
使用 C++11,您可以std::regex
像这样使用:
#include <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.
转义转义字符需要双反斜杠。
回答by S.C. Madsen
回答by Czarek Tomczak
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
回答by Czarek Tomczak
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.
是的,你可以做到,但是你必须用字符串的 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 Librarywhich covers all this stuff very well.
回答by Galik
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 positionof the match we don't have the problem of invalidating iterators.
它反复调用std::string::find()
以定位搜索字符串的其他匹配项,直到std::string::find()
找不到任何内容。因为std::string::find()
返回匹配的位置,所以我们不存在使迭代器失效的问题。
回答by maxoumime
This sounds like an option
这听起来像是一个选择
string.replace(string.find("%s"), string("%s").size(), "Something");
string.replace(string.find("%s"), string("%s").size(), "Something");
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
)在此字符串中插入多个变量
回答by Volomike
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++ 字符串。解决方法是使用.size()
的类的方法std::string
。
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;
回答by Damian
If you want to do it quickly you can use a two scan approach. Pseudo code:
如果您想快速完成,您可以使用两次扫描方法。伪代码:
- first parse. find how many matching chars.
- expand the length of the string.
- 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.
- 首先解析。找到多少个匹配的字符。
- 扩展字符串的长度。
- 第二次解析。当我们得到要替换的匹配项时,从字符串的末尾开始,否则我们只需从第一个字符串中复制字符。
I am not sure if this can be optimized to an in-place 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, '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);
');
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";
}