用另一个字符串替换字符串的一部分
是否有可能在C ++中用另一个字符串替换部分字符串?
基本上我想这样做:
QString string("hello $name"); string.replace("$name", "Somename");
但是我想使用标准C ++库。
有一个函数可以找到一个字符串中的子字符串( find
),以及一个用另一个字符串replace
字符串中特定范围的函数( 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' } }
用C ++ 11,你可以像这样使用std::regex
:
std::string string("hello $name"); string = std::regex_replace(string, std::regex("\\$name"), "Somename");
转义字符需要双反斜杠。
std::string
有一个replace
方法,那你在找什么?
你可以尝试:
s.replace(s.find("$name"), sizeof("Somename")-1, "Somename");
我还没有尝试过自己,只要阅读find()
和replace()
的文档即可。
要返回新的字符串使用这个:
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
是的,你可以做到这一点,但你必须找到第一个字符串的位置与字符串的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” ,它涵盖了所有这些内容。
这听起来像一个选项
string.replace(string.find("%s"), string("%s").size(), "Something");
你可以把它封装在一个函数中,但是这个单行解决方案听起来可以接受。 问题是,这只会改变第一次发生,你可能想循环它,但它也允许你插入几个变量到这个字符串具有相同的标记( %s
)
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; }
如果所有字符串都是std :: string,那么如果使用sizeof()
,则会发现奇怪的字符截断问题,因为它是针对C字符串而不是C ++字符串的。 解决的办法是使用std::string
的.size()
类方法。
sHaystack.replace(sHaystack.find(sNeedle), sNeedle.size(), sReplace);
这取代了sHaystack内联 – 没有必要再做一个=分配。
用法示例:
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;
我一般使用这个:
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()
返回匹配的位置 ,所以我们没有使迭代器无效的问题。
如果你想快速做到这一点,你可以使用两种扫描方法。 伪代码:
- 先解析。 找到多少匹配的字符。
- 展开字符串的长度。
- 第二个解析。 当我们得到一个我们替换的匹配时,从字符串的末尾开始,否则我们只复制第一个字符串中的字符。
我不确定这是否可以优化到就地算法。
和一个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"; }
我只是现在正在学习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; }
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);