在C ++中是否可以用另一个字符串替换一个字符串的一部分?
基本上,我想这样做:
QString string("hello $name");
string.replace("$name", "Somename");
但是我想使用标准C ++库。
在C ++中是否可以用另一个字符串替换一个字符串的一部分?
基本上,我想这样做:
QString string("hello $name");
string.replace("$name", "Somename");
但是我想使用标准C ++库。
Answers:
有一个函数可以在字符串(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
可能看起来像这样:
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'
}
}
from
与to
每通过const
参考?如果from
不存在,您的功能是什么?-1
为此。
const
,如果我编写了这样的实用程序方法,则只有在知道了替换有效
const
无视C ++的最佳工具之一。按const
引用传递应该是功能参数的默认模式。(如果没有FTR,则const
您甚至无法将字符串文字传递给函数,因为您无法将临时变量绑定到非const
引用。因此该函数甚至都不会执行写入的操作。)
在C ++ 11中,您可以这样使用std::regex
:
#include <regex>
...
std::string string("hello $name");
string = std::regex_replace(string, std::regex("\\$name"), "Somename");
要转义转义字符,必须使用双反斜杠。
std::regex_replace
不接受Qt的字符串。
string
用string.toStdString()
。
String
为std::string
,因为问题与Qt不相关。请考虑这样做-之后,我们会很乐意为您答复。
R"(\$name)"
而不是"\\$name"
。
std::string
有一种replace
方法,就是您要寻找的吗?
您可以尝试:
s.replace(s.find("$name"), sizeof("$name") - 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
是的,您可以执行此操作,但是必须使用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 )
}
如果您打算使用标准库,则应该真正拿到本书《 C ++标准库》的副本,该书 很好地涵盖了所有内容。
我通常这样使用:
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()
返回匹配的位置,所以我们没有使迭代器无效的问题。
这听起来像一个选择
string.replace(string.find("%s"), string("%s").size(), "Something");
您可以将其包装在一个函数中,但是这种单行解决方案听起来可以接受。问题在于,这只会更改第一次出现的内容,您可能希望对其进行循环,但是它还允许您使用相同的标记(%s
)将多个变量插入此字符串中
str.replace(str.find("%s"), string("%s").size(), "Something");
如果所有字符串都是std :: string,则使用时会发现字符截断的奇怪问题,sizeof()
因为它用于C字符串,而不是C ++字符串。解决方法是使用的.size()
类方法std::string
。
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;
如果要快速执行此操作,可以使用两次扫描方法。伪代码:
我不确定是否可以将其优化为就地算法。
还有一个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";
}
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;
}
我自己的实现考虑到字符串只需要调整一次大小,然后替换就可以发生了。
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(), "\\", "/"), ":", "");
我现在正在学习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;
}
这可能会更好用
void replace(string& input, const string& from, const string& to)
{
while(true)
{
size_t startPosition = input.find(from);
if(startPosition == string::npos)
break;
input.replace(startPosition, from.length(), to);
}
}