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

是否有可能在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()返回匹配的位置 ,所以我们没有使迭代器无效的问题。

如果你想快速做到这一点,你可以使用两种扫描方法。 伪代码:

  1. 先解析。 找到多少匹配的字符。
  2. 展开字符串的长度。
  3. 第二个解析。 当我们得到一个我们替换的匹配时,从字符串的末尾开始,否则我们只复制第一个字符串中的字符。

我不确定这是否可以优化到就地算法。

和一个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);