I need to search a string and edit the formatting of it.
我需要搜索一个字符串并编辑它的格式。
So far I can replace the first occurrence of the string, but I am unable to do so with the next occurrences of this string.
到目前为止,我可以替换字符串的第一次出现,但是我不能替换这个字符串的下一次出现。
This is what I have working, sort of:
这就是我的工作,
if(chartDataString.find("*A") == string::npos){ return;}
else{chartDataString.replace(chartDataString.find("*A"), 3,"[A]\n");}
If it doesn't find the string, nothing prints at all, so that's not good.
如果它找不到弦,就不会有任何东西打印出来,这就不好了。
I know I need to loop through the entire string chartDataString and replace all occurrences. I know there are a lot of similar posts to this but I don't understand (like this Replace substring with another substring C++)
我知道我需要遍历整个字符串chartDataString并替换所有出现的内容。我知道有很多类似的文章但是我不明白(比如用另一个子字符串c++替换子字符串)
I've also tried to do something like this to loop over the string:
我也试过这样做来循环字符串:
string toSearch = chartDataString;
string toFind = "*A:";
for (int i = 0; i<toSearch.length() - toFind.length(); i++){
if(toSearch.substr(i, toFind.length()) == toFind){
chartDataString.replace(chartDataString.find(toFind), 3, "[A]\n");
}
}
EDIT taking into consideration suggestions, this in theory should work, but I don't know why it doesn't
考虑到建议,这在理论上应该行得通,但我不知道为什么行不通
size_t startPos=0;
string myString = "*A";
while(string::npos != (startPos = chartDataString.find(myString, startPos))){
chartDataString.replace(chartDataString.find(myString, startPos), 3, "*A\n");
startPos = startPos + myString.length();
}
6 个解决方案
#1
18
try the following
试试以下
const std::string s = "*A";
const std::string t = "*A\n";
std::string::size_type n = 0;
while ( ( n = chartDataString.find( s, n ) ) != std::string::npos )
{
chartDataString.replace( n, s.size(), t );
n += t.size();
}
#2
2
The find
function takes an optional second argument: the position from which to begin searching. By default this is zero.
find函数接受第二个可选参数:开始搜索的位置。默认情况下这是零。
A good position to begin searching for the next match is the position where the previous replacement was inserted, plus that replacement's length. For instance if we insert a string of length 3 at position 7, then the next find
should begin at position 10.
开始搜索下一个匹配项的一个好位置是插入前一个替换项的位置,加上替换项的长度。例如,如果我们在位置7插入一个长度为3的字符串,那么下一个查找应该从位置10开始。
If the search string happens to be a substring of the replacement, this approach will avoid an infinite loop. Imagine if you try to replace all occurrences of log
with analog
, but don't skip over the replacement.
如果搜索字符串恰好是替换的子字符串,这种方法将避免无限循环。想象一下,如果您尝试用模拟替换所有出现的日志,但是不要跳过替换。
#3
2
It's fairly awkward (and probably not too efficient) to do it in place. I usually use a function along the lines of:
在合适的地方做这件事相当尴尬(可能也不是很有效率)。我通常使用的函数是:
std::string
replaceAll( std::string const& original, std::string const& from, std::string const& to )
{
std::string results;
std::string::const_iterator end = original.end();
std::string::const_iterator current = original.begin();
std::string::const_iterator next = std::search( current, end, from.begin(), from.end() );
while ( next != end ) {
results.append( current, next );
results.append( to );
current = next + from.size();
next = std::search( current, end, from.begin(), from.end() );
}
results.append( current, next );
return results;
}
Basically, you loop as long as you can find an instance of from
, appending the intermediate text and to
, and advancing to the next instance of from
. At the end, you append any text after the last instance of from
.
基本上,只要您能够找到一个from的实例,然后附加中间文本,并向下一个实例前进,您就会循环。最后,在from的最后一个实例之后追加任何文本。
(If you're going to do much programming in C++, it's probably a good idea to get used to using iterators, like the above, rather than the special member functions of std::string
. Things like the above can be made to work with any of the C++ container types, and for this reason, are more idiomatic.)
(如果您打算使用c++进行大量编程,那么最好习惯使用迭代器,如上面所示,而不是使用std::string的特殊成员函数。像上面这样的东西可以用于任何c++容器类型,出于这个原因,它们更符合习惯用法。
#4
1
In case boost
is available, you can use the following:
如果有boost,您可以使用以下工具:
std::string origStr = "this string has *A and then another *A";
std::string subStringToRemove = "*A";
std::string subStringToReplace = "[A]";
boost::replace_all(origStr , subStringToRemove , subStringToReplace);
To perform the modification on the original string, OR
对原始字符串执行修改
std::string result = boost::replace_all_copy(origStr , subStringToRemove , subStringToReplace);
To perform the modifications without modifying the original string.
在不修改原始字符串的情况下执行修改。
Hope it helps.
希望它可以帮助。
Cheers,
欢呼,
Guy
的家伙
#5
0
/// Returns a version of 'str' where every occurrence of
/// 'find' is substituted by 'replace'.
/// - Inspired by James Kanze.
/// - http://*.com/questions/20406744/
std::string replace_all(
const std::string & str , // where to work
const std::string & find , // substitute 'find'
const std::string & replace // by 'replace'
) {
using namespace std;
string result;
size_t find_len = find.size();
size_t pos,from=0;
while ( string::npos != ( pos=str.find(find,from) ) ) {
result.append( str, from, pos-from );
result.append( replace );
from = pos + find_len;
}
result.append( str, from , string::npos );
return result;
/*
This code might be an improvement to James Kanze's
because it uses std::string methods instead of
general algorithms [as 'std::search()'].
*/
}
int main() {
{
std::string test = "*A ... *A ... *A ...";
std::string changed = "*A\n ... *A\n ... *A\n ...";
assert( changed == replace_all( test, "*A", "*A\n" ) );
}
{
std::string GB = "My gorila ate the banana";
std::string gg = replace_all( GB, "gorila", "banana" );
assert( gg == "My banana ate the banana" );
gg = replace_all( gg, "banana", "gorila" );
assert( gg == "My gorila ate the gorila" );
std::string bb = replace_all( GB, "banana", "gorila" );
assert( gg == "My gorila ate the gorila" );
bb = replace_all( bb, "gorila" , "banana" );
assert( bb == "My banana ate the banana" );
}
{
std::string str, res;
str.assign( "ababaabcd" );
res = replace_all( str, "ab", "fg");
assert( res == "fgfgafgcd" );
str="aaaaaaaa"; assert( 8==str.size() );
res = replace_all( str, "aa", "a" );
assert( res == "aaaa" );
assert( "" == replace_all( str, "aa", "" ) );
str = "aaaaaaa"; assert( 7==str.size() );
res = replace_all( str, "aa", "a" );
assert( res == "aaaa" );
str = "..aaaaaa.."; assert( 10==str.size() );
res = replace_all( str, "aa", "a" );
assert( res == "..aaa.." );
str = "baaaac"; assert( 6==str.size() );
res = replace_all( str, "aa", "" );
assert( res == "bc" );
}
}
#6
0
Quick-baked version, but working:) version:
快烤版,但工作:)版本:
string replace(const string& data, const string& substr, const string& replacement)
{
string res;
string::const_iterator b = cbegin(data);
string::const_iterator e = cend(data);
string::const_iterator pos = search(b, e, cbegin(substr), cend(substr));
while (pos != e)
{
copy(b, pos, back_inserter(res));
copy(begin(replacement), end(replacement), back_inserter(res));
b = pos + substr.size();
pos = search(b, e, cbegin(substr), cend(substr));
}
copy(b, e, back_inserter(res));
return res;
}
#1
18
try the following
试试以下
const std::string s = "*A";
const std::string t = "*A\n";
std::string::size_type n = 0;
while ( ( n = chartDataString.find( s, n ) ) != std::string::npos )
{
chartDataString.replace( n, s.size(), t );
n += t.size();
}
#2
2
The find
function takes an optional second argument: the position from which to begin searching. By default this is zero.
find函数接受第二个可选参数:开始搜索的位置。默认情况下这是零。
A good position to begin searching for the next match is the position where the previous replacement was inserted, plus that replacement's length. For instance if we insert a string of length 3 at position 7, then the next find
should begin at position 10.
开始搜索下一个匹配项的一个好位置是插入前一个替换项的位置,加上替换项的长度。例如,如果我们在位置7插入一个长度为3的字符串,那么下一个查找应该从位置10开始。
If the search string happens to be a substring of the replacement, this approach will avoid an infinite loop. Imagine if you try to replace all occurrences of log
with analog
, but don't skip over the replacement.
如果搜索字符串恰好是替换的子字符串,这种方法将避免无限循环。想象一下,如果您尝试用模拟替换所有出现的日志,但是不要跳过替换。
#3
2
It's fairly awkward (and probably not too efficient) to do it in place. I usually use a function along the lines of:
在合适的地方做这件事相当尴尬(可能也不是很有效率)。我通常使用的函数是:
std::string
replaceAll( std::string const& original, std::string const& from, std::string const& to )
{
std::string results;
std::string::const_iterator end = original.end();
std::string::const_iterator current = original.begin();
std::string::const_iterator next = std::search( current, end, from.begin(), from.end() );
while ( next != end ) {
results.append( current, next );
results.append( to );
current = next + from.size();
next = std::search( current, end, from.begin(), from.end() );
}
results.append( current, next );
return results;
}
Basically, you loop as long as you can find an instance of from
, appending the intermediate text and to
, and advancing to the next instance of from
. At the end, you append any text after the last instance of from
.
基本上,只要您能够找到一个from的实例,然后附加中间文本,并向下一个实例前进,您就会循环。最后,在from的最后一个实例之后追加任何文本。
(If you're going to do much programming in C++, it's probably a good idea to get used to using iterators, like the above, rather than the special member functions of std::string
. Things like the above can be made to work with any of the C++ container types, and for this reason, are more idiomatic.)
(如果您打算使用c++进行大量编程,那么最好习惯使用迭代器,如上面所示,而不是使用std::string的特殊成员函数。像上面这样的东西可以用于任何c++容器类型,出于这个原因,它们更符合习惯用法。
#4
1
In case boost
is available, you can use the following:
如果有boost,您可以使用以下工具:
std::string origStr = "this string has *A and then another *A";
std::string subStringToRemove = "*A";
std::string subStringToReplace = "[A]";
boost::replace_all(origStr , subStringToRemove , subStringToReplace);
To perform the modification on the original string, OR
对原始字符串执行修改
std::string result = boost::replace_all_copy(origStr , subStringToRemove , subStringToReplace);
To perform the modifications without modifying the original string.
在不修改原始字符串的情况下执行修改。
Hope it helps.
希望它可以帮助。
Cheers,
欢呼,
Guy
的家伙
#5
0
/// Returns a version of 'str' where every occurrence of
/// 'find' is substituted by 'replace'.
/// - Inspired by James Kanze.
/// - http://*.com/questions/20406744/
std::string replace_all(
const std::string & str , // where to work
const std::string & find , // substitute 'find'
const std::string & replace // by 'replace'
) {
using namespace std;
string result;
size_t find_len = find.size();
size_t pos,from=0;
while ( string::npos != ( pos=str.find(find,from) ) ) {
result.append( str, from, pos-from );
result.append( replace );
from = pos + find_len;
}
result.append( str, from , string::npos );
return result;
/*
This code might be an improvement to James Kanze's
because it uses std::string methods instead of
general algorithms [as 'std::search()'].
*/
}
int main() {
{
std::string test = "*A ... *A ... *A ...";
std::string changed = "*A\n ... *A\n ... *A\n ...";
assert( changed == replace_all( test, "*A", "*A\n" ) );
}
{
std::string GB = "My gorila ate the banana";
std::string gg = replace_all( GB, "gorila", "banana" );
assert( gg == "My banana ate the banana" );
gg = replace_all( gg, "banana", "gorila" );
assert( gg == "My gorila ate the gorila" );
std::string bb = replace_all( GB, "banana", "gorila" );
assert( gg == "My gorila ate the gorila" );
bb = replace_all( bb, "gorila" , "banana" );
assert( bb == "My banana ate the banana" );
}
{
std::string str, res;
str.assign( "ababaabcd" );
res = replace_all( str, "ab", "fg");
assert( res == "fgfgafgcd" );
str="aaaaaaaa"; assert( 8==str.size() );
res = replace_all( str, "aa", "a" );
assert( res == "aaaa" );
assert( "" == replace_all( str, "aa", "" ) );
str = "aaaaaaa"; assert( 7==str.size() );
res = replace_all( str, "aa", "a" );
assert( res == "aaaa" );
str = "..aaaaaa.."; assert( 10==str.size() );
res = replace_all( str, "aa", "a" );
assert( res == "..aaa.." );
str = "baaaac"; assert( 6==str.size() );
res = replace_all( str, "aa", "" );
assert( res == "bc" );
}
}
#6
0
Quick-baked version, but working:) version:
快烤版,但工作:)版本:
string replace(const string& data, const string& substr, const string& replacement)
{
string res;
string::const_iterator b = cbegin(data);
string::const_iterator e = cend(data);
string::const_iterator pos = search(b, e, cbegin(substr), cend(substr));
while (pos != e)
{
copy(b, pos, back_inserter(res));
copy(begin(replacement), end(replacement), back_inserter(res));
b = pos + substr.size();
pos = search(b, e, cbegin(substr), cend(substr));
}
copy(b, e, back_inserter(res));
return res;
}