How to find and replace all occurrences of a substring in a string?

I need to find a string and edit its formatting.

So far I can replace the first occurrence of a line, but I cannot do this with the next occurrences of this line.

This is what I have, like:

if(chartDataString.find("*A") == string::npos){ return;} else{chartDataString.replace(chartDataString.find("*A"), 3,"[A]\n");} 

If it does not find the string, it does not print anything at all, so this is not good.

I know I need to skip the entire chartDataString line and replace all occurrences. I know that there are many similar messages, but I do not understand (for example, Replace a substring with another C ++ substring )

I also tried to do something like this to iterate over a 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 given the suggestions, this should theoretically work, but I don't know why this is not

 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
source share
5 answers

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(); } 
+14
source

The find function takes an optional second argument: the position from which to start the search. By default, this value is zero.

A good position to start looking for the next match is the position at which the previous replacement was inserted, plus this replacement length. For example, if we insert a string of length 3 at position 7, then the next find should start at position 10.

If the search string is a substring of substitution, this approach will avoid an infinite loop. Imagine if you try to replace all log entries with analog , but don't miss the replacement.

+2
source

It is rather inconvenient (and probably not too effective) to do this in place. I usually use the function line by line:

 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 through until you can find the from instance by adding intermediate text and to , and moving forward to the next from instance. At the end, you add any text after the last from instance.

(If you intend to program a lot in C ++, it might be a good idea to get used to using iterators, as above, rather than special std::string member functions. Things like the above can be created to work with any of C ++ container types, and for this reason are more idiomatic.)

+2
source
 /// Returns a version of 'str' where every occurrence of /// 'find' is substituted by 'replace'. /// - Inspired by James Kanze. /// - http://stackoverflow.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" ); } } 
0
source

Quick baking 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; } 
0
source

Source: https://habr.com/ru/post/959410/


All Articles