Substituir parte de uma string por outra string

É possível em C ++ para replace parte de uma seqüência de caracteres por outra seqüência de caracteres?

Basicamente, gostaria de fazer isso:

QString string("hello $name"); string.replace("$name", "Somename"); 

Mas eu gostaria de usar as bibliotecas Standard C ++.

Há uma function para encontrar uma substring dentro de uma string ( find ), e uma function para replace um intervalo específico em uma string com outra string ( replace ), para que você possa combiná-los para obter o efeito desejado:

 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"); 

Em resposta a um comentário, acho que replaceAll provavelmente seria algo assim:

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

Com o C ++ 11 você pode usar o std::regex forma:

  std::string string("hello $name"); string = std::regex_replace(string, std::regex("\\$name"), "Somename"); 

A barra invertida dupla é necessária para escaping de um caractere de escape.

std::string tem um método de replace , é isso que você está procurando?

Você poderia tentar:

 s.replace(s.find("$name"), sizeof("Somename")-1, "Somename"); 

Eu não tentei, apenas leia a documentação em find() e replace() .

Para ter a nova string retornada use isto:

 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 modified: " << 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 

Sim, você pode fazer isso, mas você tem que encontrar a posição da primeira string com o membro find () da string, e então replace com o membro replace ().

 string s("hello $name"); size_type pos = s.find( "$name" ); if ( pos != string::npos ) { s.replace( pos, 5, "somename" ); // 5 = length( $name ) } 

Se você está planejando usar a Biblioteca Padrão, você deve realmente se apossar de uma cópia do livro The C ++ Standard Library, que cobre tudo isso muito bem.

Isso soa como uma opção

string.replace(string.find("%s"), string("%s").size(), "Something");

Você poderia envolver isso em uma function, mas esta solução de uma linha parece aceitável. O problema é que isso mudará apenas a primeira ocorrência, você pode querer fazer um loop, mas também permite inserir diversas variables ​​nessa string com o mesmo token ( %s )

Se todas as strings forem std :: string, você encontrará problemas estranhos com o corte de caracteres se estiver usando sizeof() porque é indicado para strings C, não para strings C ++. A correção é usar o método de class .size() de std::string .

 sHaystack.replace(sHaystack.find(sNeedle), sNeedle.size(), sReplace); 

Isso substitui o sHaystack inline – não é necessário fazer uma = atribuição de volta a isso.

Exemplo de uso:

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

Eu uso geralmente isso:

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

Ele repetidamente chama std::string::find() para localizar outras ocorrências da string procurada até que std::string::find() não encontre nada. Como std::string::find() retorna a posição da correspondência, não temos o problema de invalidar os iteradores.

Se você quiser fazer isso rapidamente, você pode usar uma abordagem de duas digitalizações. Pseudo-código:

  1. primeira análise. encontre quantos caracteres correspondentes.
  2. expanda o comprimento da string.
  3. segunda análise. Comece a partir do final da string quando recebermos uma correspondência que substituímos, senão copiamos os caracteres da primeira string.

Não tenho certeza se isso pode ser otimizado para um algoritmo no local.

E um exemplo de código C ++ 11, mas eu só procuro por um caractere.

 #include  #include  #include  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"; } 

Eu estou apenas agora aprendendo C ++, mas editando alguns dos códigos previamente postados, eu provavelmente usaria algo assim. Isso oferece a flexibilidade de replace 1 ou várias instâncias e também permite especificar o ponto inicial.

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