Substituir substring por outra substring C ++

Como eu poderia replace uma substring em uma string com outra substring em C ++, quais funções eu poderia usar?

eg: string test = "abc def abc def"; test.replace("abc", "hij").replace("def", "klm"); //replace occurrence of abc and def with other substring 

Não há nenhuma function interna no C ++ para fazer isso. Se você quiser replace todas as instâncias de uma substring por outra, poderá fazê-lo misturando chamadas em string::find e string::replace . Por exemplo:

 size_t index = 0; while (true) { /* Locate the substring to replace. */ index = str.find("abc", index); if (index == std::string::npos) break; /* Make the replacement. */ str.replace(index, 3, "def"); /* Advance index forward so the next iteration doesn't pick it up as well. */ index += 3; } 

Na última linha deste código, eu adicionei o index pelo comprimento da string que foi inserida na string. Neste exemplo em particular – substituindo "abc" por "def" – isto não é realmente necessário. No entanto, em uma configuração mais geral, é importante pular a string que acabou de ser substituída. Por exemplo, se você quiser replace "abc" por "abcabc" , sem pular o segmento de string recém-substituído, esse código replaceá continuamente partes das strings recém-substituídas até que a memory seja esgotada. Independentemente, pode ser um pouco mais rápido ignorar esses novos caracteres, pois isso economiza tempo e esforço com a function string::find .

Espero que isto ajude!

Boost String Algorithms Library maneira:

 #include  { // 1. string test = "abc def abc def"; boost::replace_all(test, "abc", "hij"); boost::replace_all(test, "def", "klm"); } { // 2. string test = boost::replace_all_copy ( boost::replace_all_copy("abc def abc def", "abc", "hij") , "def" , "klm" ); } 

Eu acho que todas as soluções falharão se o comprimento da string substituta for diferente do tamanho da string a ser substituída. (procure por “abc” e substitua por “xxxxxx”) Uma abordagem geral pode ser:

 void replaceAll( string &s, const string &search, const string &replace ) { for( size_t pos = 0; ; pos += replace.length() ) { // Locate the substring to replace pos = s.find( search, pos ); if( pos == string::npos ) break; // Replace by erasing and inserting s.erase( pos, search.length() ); s.insert( pos, replace ); } } 

Em C ++ 11, você pode usar regex_replace :

 string test = "abc def abc def"; test = regex_replace(test, regex("def"), "klm"); 
 str.replace(str.find(str2),str2.length(),str3); 

Onde

  • str é a string base
  • str2 é a subcadeia para encontrar
  • str3 é a substring de substituição

Substituir substrings não deve ser tão difícil.

 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; } 

Se você precisa de performance, aqui está uma function otimizada que modifica a string de input, ela não cria uma cópia da string:

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

Testes:

 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 changed: " << input << std::endl; ReplaceStringInPlace(input, "bc", "??"); std::cout << "ReplaceStringInPlace() input string modified: " << input << std::endl; 

Saída:

 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 
 using std::string; string string_replace( string src, string const& target, string const& repl) { // handle error situations/trivial cases if (target.length() == 0) { // searching for a match to the empty string will result in // an infinite loop // it might make sense to throw an exception for this case return src; } if (src.length() == 0) { return src; // nothing to match against } size_t idx = 0; for (;;) { idx = src.find( target, idx); if (idx == string::npos) break; src.replace( idx, target.length(), repl); idx += repl.length(); } return src; } 

Como não é um membro da class string , ele não permite uma syntax tão agradável quanto em seu exemplo, mas o seguinte fará o equivalente:

 test = string_replace( string_replace( test, "abc", "hij"), "def", "klm") 

Generalizando na resposta da rotmax, aqui está uma solução completa para pesquisar e replace todas as instâncias em uma string. Se ambas as substrings forem de tamanhos diferentes, a substring será substituída usando string :: erase e string :: insert. Caso contrário, a string :: replace mais rápida será usada.

 void FindReplace(string& line, string& oldString, string& newString) { const size_t oldSize = oldString.length(); // do nothing if line is shorter than the string to find if( oldSize > line.length() ) return; const size_t newSize = newString.length(); for( size_t pos = 0; ; pos += newSize ) { // Locate the substring to replace pos = line.find( oldString, pos ); if( pos == string::npos ) return; if( oldSize == newSize ) { // if they're same size, use std::string::replace line.replace( pos, oldSize, newString ); } else { // if not same size, replace by erasing and inserting line.erase( pos, oldSize ); line.insert( pos, newString ); } } } 

Se você tiver certeza de que a substring necessária está presente na string, isso replaceá a primeira ocorrência de "abc" por "hij"

 test.replace( test.find("abc"), 3, "hij"); 

Ele irá falhar se você não tiver “abc” no teste, então use-o com cuidado.

  string & replace(string & subj, string old, string neu) { size_t uiui = subj.find(old); if (uiui != string::npos) { subj.erase(uiui, old.size()); subj.insert(uiui, neu); } return subj; } 

Eu acho que isso se encheckbox a sua exigência com poucos códigos!

a versão imposta por @Czarek Tomczak.
Permitir std::string e std::wstring .

 template  void ReplaceSubstring(std::basic_string& subject, const std::basic_string& search, const std::basic_string& replace) { if (search.empty()) { return; } typename std::basic_string::size_type pos = 0; while((pos = subject.find(search, pos)) != std::basic_string::npos) { subject.replace(pos, search.length(), replace); pos += replace.length(); } } 
 std::string replace(const std::string & in , const std::string & from , const std::string & to){ if(from.size() == 0 ) return in; std::string out = ""; std::string tmp = ""; for(int i = 0, ii = -1; i < in.size(); ++i) { // change ii if ( ii < 0 && from[0] == in[i] ) { ii = 0; tmp = from[0]; } else if( ii >= 0 && ii < from.size()-1 ) { ii ++ ; tmp = tmp + in[i]; if(from[ii] == in[i]) { } else { out = out + tmp; tmp = ""; ii = -1; } } else { out = out + in[i]; } if( tmp == from ) { out = out + to; tmp = ""; ii = -1; } } return out; }; 

Aqui está uma solução usando recursion que substitui todas as ocorrências de uma substring por outra substring. Isso funciona, não importa o tamanho das seqüências de caracteres.

 std::string ReplaceString(const std::string source_string, const std::string old_substring, const std::string new_substring) { // Can't replace nothing. if (old_substring.empty()) return source_string; // Find the first occurrence of the substring we want to replace. size_t substring_position = source_string.find(old_substring); // If not found, there is nothing to replace. if (substring_position == std::string::npos) return source_string; // Return the part of the source string until the first occurance of the old substring + the new replacement substring + the result of the same function on the remainder. return source_string.substr(0,substring_position) + new_substring + ReplaceString(source_string.substr(substring_position + old_substring.length(),source_string.length() - (substring_position + old_substring.length())), old_substring, new_substring); } 

Exemplo de uso:

 std::string my_cpp_string = "This string is unmodified. You heard me right, it's unmodified."; std::cout < < "The original C++ string is:\n" << my_cpp_string << std::endl; my_cpp_string = ReplaceString(my_cpp_string, "unmodified", "modified"); std::cout << "The final C++ string is:\n" << my_cpp_string << std::endl; 

Aqui está uma solução que escrevi usando a tática do construtor:

 #include  #include  using std::string; using std::stringstream; string stringReplace (const string& source, const string& toReplace, const string& replaceWith) { size_t pos = 0; size_t cursor = 0; int repLen = toReplace.length(); stringstream builder; do { pos = source.find(toReplace, cursor); if (string::npos != pos) { //copy up to the match, then append the replacement builder < < source.substr(cursor, pos - cursor); builder << replaceWith; // skip past the match cursor = pos + repLen; } } while (string::npos != pos); //copy the remainder builder << source.substr(cursor); return (builder.str()); } 

Testes:

 void addTestResult (const string&& testId, bool pass) { ... } void testStringReplace() { string source = "123456789012345678901234567890"; string toReplace = "567"; string replaceWith = "abcd"; string result = stringReplace (source, toReplace, replaceWith); string expected = "1234abcd8901234abcd8901234abcd890"; bool pass = (0 == result.compare(expected)); addTestResult("567", pass); source = "123456789012345678901234567890"; toReplace = "123"; replaceWith = "-"; result = stringReplace(source, toReplace, replaceWith); expected = "-4567890-4567890-4567890"; pass = (0 == result.compare(expected)); addTestResult("start", pass); source = "123456789012345678901234567890"; toReplace = "0"; replaceWith = ""; result = stringReplace(source, toReplace, replaceWith); expected = "123456789123456789123456789"; pass = (0 == result.compare(expected)); addTestResult("end", pass); source = "123123456789012345678901234567890"; toReplace = "123"; replaceWith = "-"; result = stringReplace(source, toReplace, replaceWith); expected = "--4567890-4567890-4567890"; pass = (0 == result.compare(expected)); addTestResult("concat", pass); source = "1232323323123456789012345678901234567890"; toReplace = "323"; replaceWith = "-"; result = stringReplace(source, toReplace, replaceWith); expected = "12-23-123456789012345678901234567890"; pass = (0 == result.compare(expected)); addTestResult("interleaved", pass); source = "1232323323123456789012345678901234567890"; toReplace = "==="; replaceWith = "-"; result = utils_stringReplace(source, toReplace, replaceWith); expected = source; pass = (0 == result.compare(expected)); addTestResult("no match", pass); }