Respostas:
std::string
não contém essa função, mas você pode usar a replace
função autônoma do algorithm
cabeçalho.
#include <algorithm>
#include <string>
void some_func() {
std::string s = "example string";
std::replace( s.begin(), s.end(), 'x', 'y'); // replace all 'x' to 'y'
}
std::string::replace()
invés de std::replace()
! 'x' ( char
) é implicitamente convertido para size_t
[valor 120], portanto, toda a cadeia de caracteres ou parte dela será preenchida com 120 cópias de 'y'.
Também pensei em lançar a solução boost :
#include <boost/algorithm/string/replace.hpp>
// in place
std::string in_place = "blah#blah";
boost::replace_all(in_place, "#", "@");
// copy
const std::string input = "blah#blah";
std::string output = boost::replace_all_copy(input, "#", "@");
-I
sinalizadores para o seu compilador para que ele encontre as bibliotecas do Boost no seu sistema. Talvez você precise instalá-lo primeiro.
A questão está centrada na character
substituição, mas, como achei esta página muito útil (especialmente a observação de Konrad ), gostaria de compartilhar essa implementação mais generalizada, que também permite lidar com substrings
:
std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
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(); // Handles case where 'to' is a substring of 'from'
}
return str;
}
Uso:
std::cout << ReplaceAll(string("Number Of Beans"), std::string(" "), std::string("_")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("X")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("h")) << std::endl;
Saídas:
Number_Of_Beans
XXjXugtXty
hhjhugthty
EDITAR:
O exposto acima pode ser implementado de uma maneira mais adequada, caso as performances sejam de sua preocupação, retornando nothing ( void
) e realizando as alterações diretamente na string str
fornecida como argumento, passada por endereço em vez de por valor . Isso evitaria cópias inúteis e caras da string original, enquanto retornava o resultado. Sua ligação, então ...
Código:
static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
// Same inner code...
// No return statement
}
Espero que isso seja útil para alguns outros ...
from
string está vazia, caso contrário, um loop sem fim ocorrerá.
Imagine um blob binário grande em que todos os 0x00 bytes sejam substituídos por "\ 1 \ x30" e todos os 0x01 bytes por "\ 1 \ x31" porque o protocolo de transporte não permite \ 0-bytes.
Nos casos em que:
as soluções fornecidas não podem ser aplicadas (porque substituem apenas caracteres únicos) ou têm um problema de desempenho, porque chamariam string :: replace várias vezes, o que gera cópias do tamanho do blob repetidamente. (Eu não sei a solução de reforço, talvez esteja tudo bem nessa perspectiva)
Este percorre todas as ocorrências na string de origem e constrói a nova string peça por peça uma vez :
void replaceAll(std::string& source, const std::string& from, const std::string& to)
{
std::string newString;
newString.reserve(source.length()); // avoids a few memory allocations
std::string::size_type lastPos = 0;
std::string::size_type findPos;
while(std::string::npos != (findPos = source.find(from, lastPos)))
{
newString.append(source, lastPos, findPos - lastPos);
newString += to;
lastPos = findPos + from.length();
}
// Care for the rest after last occurrence
newString += source.substr(lastPos);
source.swap(newString);
}
Uma simples localização e substituição de um único caractere seria algo como:
s.replace(s.find("x"), 1, "y")
Para fazer isso para toda a cadeia, a coisa mais fácil a fazer seria fazer um loop até você s.find
começar a retornar npos
. Suponho que você também pode pegar range_error
para sair do loop, mas isso é meio feio.
{
personagem. Não sei o que é uma "chave dupla". Talvez você tenha algum tipo de problema de fonte?
Se você estiver procurando substituir mais de um caractere e estiver lidando apenas com std::string
, então esse trecho funcionaria, substituindo sNeedle no sHaystack por sReplace, e sNeedle e sReplace não precisam ter o mesmo tamanho. Essa rotina usa o loop while para substituir todas as ocorrências, e não apenas a primeira encontrada da esquerda para a direita.
while(sHaystack.find(sNeedle) != std::string::npos) {
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}
find
ligação duas vezes. Considere tornar esse resultado uma variável temporária.
Como Kirill sugeriu, use o método de substituição ou itere ao longo da cadeia substituindo cada caractere independentemente.
Como alternativa, você pode usar o find
método ou find_first_of
dependendo do que você precisa fazer. Nenhuma dessas soluções fará o trabalho de uma só vez, mas com algumas linhas extras de código você deve fazê-las funcionar para você. :-)
#include <iostream>
#include <string>
using namespace std;
// Replace function..
string replace(string word, string target, string replacement){
int len, loop=0;
string nword="", let;
len=word.length();
len--;
while(loop<=len){
let=word.substr(loop, 1);
if(let==target){
nword=nword+replacement;
}else{
nword=nword+let;
}
loop++;
}
return nword;
}
//Main..
int main() {
string word;
cout<<"Enter Word: ";
cin>>word;
cout<<replace(word, "x", "y")<<endl;
return 0;
}
word
for longo, pode haver muita sobrecarga ao chamar a função. Você pode otimizar isso passando word
, target
e replacement
como referências const.
E o Abseil StrReplaceAll ? No arquivo de cabeçalho:
// This file defines `absl::StrReplaceAll()`, a general-purpose string
// replacement function designed for large, arbitrary text substitutions,
// especially on strings which you are receiving from some other system for
// further processing (e.g. processing regular expressions, escaping HTML
// entities, etc.). `StrReplaceAll` is designed to be efficient even when only
// one substitution is being performed, or when substitution is rare.
//
// If the string being modified is known at compile-time, and the substitutions
// vary, `absl::Substitute()` may be a better choice.
//
// Example:
//
// std::string html_escaped = absl::StrReplaceAll(user_input, {
// {"&", "&"},
// {"<", "<"},
// {">", ">"},
// {"\"", """},
// {"'", "'"}});
Moda antiga :-)
std::string str = "H:/recursos/audio/youtube/libre/falta/";
for (int i = 0; i < str.size(); i++) {
if (str[i] == '/') {
str[i] = '\\';
}
}
std::cout << str;
Resultado:
H: \ recursos \ áudio \ youtube \ libre \ falta \
Isso funciona! Usei algo semelhante a isso para um aplicativo de livraria, onde o inventário foi armazenado em um CSV (como um arquivo .dat). Porém, no caso de um único caractere, o que significa que o substituto é apenas um único caractere, por exemplo, '|', ele deve estar entre aspas duplas "|" para não lançar um constante constante de conversão inválido.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int count = 0; // for the number of occurences.
// final hold variable of corrected word up to the npos=j
string holdWord = "";
// a temp var in order to replace 0 to new npos
string holdTemp = "";
// a csv for a an entry in a book store
string holdLetter = "Big Java 7th Ed,Horstman,978-1118431115,99.85";
// j = npos
for (int j = 0; j < holdLetter.length(); j++) {
if (holdLetter[j] == ',') {
if ( count == 0 )
{
holdWord = holdLetter.replace(j, 1, " | ");
}
else {
string holdTemp1 = holdLetter.replace(j, 1, " | ");
// since replacement is three positions in length,
// must replace new replacement's 0 to npos-3, with
// the 0 to npos - 3 of the old replacement
holdTemp = holdTemp1.replace(0, j-3, holdWord, 0, j-3);
holdWord = "";
holdWord = holdTemp;
}
holdTemp = "";
count++;
}
}
cout << holdWord << endl;
return 0;
}
// result:
Big Java 7th Ed | Horstman | 978-1118431115 | 99.85
Infelizmente, estou usando o CentOS atualmente, então minha versão do compilador está abaixo. A versão C ++ (g ++), C ++ 98 padrão:
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Se você estiver disposto a usar std::string
s, poderá usar a strsub
função desse aplicativo de amostra como está ou atualizá-la se desejar que ele use um tipo ou conjunto de parâmetros diferente para atingir aproximadamente o mesmo objetivo. Basicamente, ele usa as propriedades e funcionalidades de std::string
para apagar rapidamente o conjunto de caracteres correspondente e inserir os caracteres desejados diretamente no std::string
. Toda vez que faz essa operação de substituição, o deslocamento é atualizado se ainda puder encontrar caracteres correspondentes para substituir e, se não puder mais devido a substituição, ele retornará a string em seu estado desde a última atualização.
#include <iostream>
#include <string>
std::string strsub(std::string stringToModify,
std::string charsToReplace,
std::string replacementChars);
int main()
{
std::string silly_typos = "annoiiyyyng syyyllii tiipos.";
std::cout << "Look at these " << silly_typos << std::endl;
silly_typos = strsub(silly_typos, "yyy", "i");
std::cout << "After a little elbow-grease, a few less " << silly_typos << std::endl;
silly_typos = strsub(silly_typos, "ii", "y");
std::cout << "There, no more " << silly_typos << std::endl;
return 0;
}
std::string strsub(std::string stringToModify,
std::string charsToReplace,
std::string replacementChars)
{
std::string this_string = stringToModify;
std::size_t this_occurrence = this_string.find(charsToReplace);
while (this_occurrence != std::string::npos)
{
this_string.erase(this_occurrence, charsToReplace.size());
this_string.insert(this_occurrence, replacementChars);
this_occurrence = this_string.find(charsToReplace,
this_occurrence + replacementChars.size());
}
return this_string;
}
Se você não quiser usar std::string
s como parâmetros para passar as seqüências de estilo C, poderá ver o exemplo atualizado abaixo:
#include <iostream>
#include <string>
std::string strsub(const char * stringToModify,
const char * charsToReplace,
const char * replacementChars,
uint64_t sizeOfCharsToReplace,
uint64_t sizeOfReplacementChars);
int main()
{
std::string silly_typos = "annoiiyyyng syyyllii tiipos.";
std::cout << "Look at these " << silly_typos << std::endl;
silly_typos = strsub(silly_typos.c_str(), "yyy", "i", 3, 1);
std::cout << "After a little elbow-grease, a few less " << silly_typos << std::endl;
silly_typos = strsub(silly_typos.c_str(), "ii", "y", 2, 1);
std::cout << "There, no more " << silly_typos << std::endl;
return 0;
}
std::string strsub(const char * stringToModify,
const char * charsToReplace,
const char * replacementChars,
uint64_t sizeOfCharsToReplace,
uint64_t sizeOfReplacementChars)
{
std::string this_string = stringToModify;
std::size_t this_occurrence = this_string.find(charsToReplace);
while (this_occurrence != std::string::npos)
{
this_string.erase(this_occurrence, sizeOfCharsToReplace);
this_string.insert(this_occurrence, replacementChars);
this_occurrence = this_string.find(charsToReplace,
this_occurrence + sizeOfReplacementChars);
}
return this_string;
}
Para situações simples, isso funciona muito bem sem o uso de qualquer outra biblioteca e, em seguida, std :: string (que já está em uso).
Substitua todas as ocorrências do caractere a pelo caractere b em some_string :
for (size_t i = 0; i < some_string.size(); ++i) {
if (some_string[i] == 'a') {
some_string.replace(i, 1, "b");
}
}
Se a sequência for grande ou várias chamadas a serem substituídas forem um problema, você poderá aplicar a técnica mencionada nesta resposta: https://stackoverflow.com/a/29752943/3622300
aqui está uma solução que eu criei, no espírito máximo de DRI. ele pesquisará sNeedle no sHaystack e o substituirá por sReplace, nTimes se não for 0, caso contrário, todas as ocorrências de sNeedle. não procurará novamente no texto substituído.
std::string str_replace(
std::string sHaystack, std::string sNeedle, std::string sReplace,
size_t nTimes=0)
{
size_t found = 0, pos = 0, c = 0;
size_t len = sNeedle.size();
size_t replen = sReplace.size();
std::string input(sHaystack);
do {
found = input.find(sNeedle, pos);
if (found == std::string::npos) {
break;
}
input.replace(found, len, sReplace);
pos = found + replen;
++c;
} while(!nTimes || c < nTimes);
return input;
}
std::string
é um contêiner projetado especificamente para operar com sequências de caracteres. link