我如何使用标准c++库替换字符串的一部分与另一个字符串?
QString s("hello $name"); // Example using Qt. s.replace("$name", "Somename");
使用std::string::replace:
std::string::replace
s.replace(s.find("$name"), sizeof("$name") - 1, "Somename");
是的,你可以这样做,但你必须用字符串的find()成员找到第一个字符串的位置,然后用它的replace()成员替换。
string s("hello $name"); size_type pos = s.find( "$name" ); if ( pos != string::npos ) { s.replace( pos, 5, "somename" ); // 5 = length( $name ) }
如果你打算使用标准库,你真的应该得到一本c++标准库的书,它很好地涵盖了所有这些东西。
有一个函数用于查找字符串中的子字符串(find),还有一个函数用于用另一个字符串替换字符串中的特定范围(replace),所以你可以结合它们来获得你想要的效果:
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可能看起来像这样:
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' } }
要返回新字符串,请使用以下命令:
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
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& 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()返回匹配的位置,所以我们不存在使迭代器失效的问题。
std::string::find()
在c++ 11中,你可以像这样使用std::regex:
std::regex
#include <regex> ... std::string string("hello $name"); string = std::regex_replace(string, std::regex("\\$name"), "Somename");
对于转义字符,需要使用双反斜杠。
string.replace(string.find("%s"), string("%s").size(), "Something");
%s
我现在正在学习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; }
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);
如果所有字符串都是std::string,如果使用sizeof(),你会发现字符截断的奇怪问题,因为它是针对C字符串,而不是c++字符串。修复方法是使用std::string的.size()类方法。
sizeof()
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;
如果你想快速完成,你可以使用两次扫描的方法。 伪代码:< / p >
我不确定这是否可以优化到一个到位的算法。
和一个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"; }
我自己的实现,考虑到字符串只需要调整一次大小,然后替换就可以发生。
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(), "\\", "/"), ":", "");
这个用起来可能更好
void replace(string& input, const string& from, const string& to) { auto pos = 0; while(true) { size_t startPosition = input.find(from, pos); if(startPosition == string::npos) return; input.replace(startPosition, from.length(), to); pos += to.length(); } }
你可以使用这个代码来删除减法,也可以替换,也可以删除额外的空白。 代码:< / p >
#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; }
那么加速方案呢:
boost::replace_all(value, "token1", "token2");