Tudo isso está bem documentado em sites de referência . Mas se você não conhecesse essas funções, você poderia facilmente fazer este tipo de coisas manualmente:
std::string output;
output.reserve(str.size());// optional, avoids buffer reallocations in the loopfor(size_t i =0; i < str.size();++i)if(str[i]!='a') output += str[i];
@jww: Suponho que você esteja falando sobre o último exemplo de código e né o comprimento da string original. Para cada caractere de entrada, eu faço um teste de caractere O(1)e 0 ou 1 acréscimo de caractere. O acréscimo de caracteres O(1)se houver memória suficiente reservada ou O(current_length)se um novo buffer for alocado. Se você fizer isso output.reserve(str.size())antes do loop, isso nunca acontecerá e você terá um O(n)custo global . Caso contrário, de forma assintótica, acho que o custo se deve à O(n . log(n) )estratégia de realocação do contêiner STL.
Antoine,
5
Eu precisava de #include <algorithm>
S Meaden
Boa resposta. É sempre bom se a resposta contém muitas soluções. Para mim, a solução com o foré a mais adequada.
Dmitry Nichiporenko de
@DmitryNichiporenko a resposta com o para não pode ser a mais adequada. Se você tiver um predicado ou uma saída não vazia, prefiro considerar: output.reserve (str.size () + output.size ()); std :: copy_if (str.begin (), str.end (), std :: back_inserter (output), [] (char c) {return predicate (c);});
Jimifiki
10
O algoritmo std::replacefunciona por elemento em uma determinada sequência (portanto, substitui elementos por elementos diferentes e não pode substituí-lo por nada ). Mas não existe um personagem vazio . Se você quiser remover elementos de uma sequência, os seguintes elementos devem ser movidos e std::replacenão funcionam assim.
Você pode tentar usar std::remove( junto comstd::erase ) para conseguir isso.
stringRemoveChar(string str,char c){string result;for(size_t i =0; i < str.size(); i++){char currentChar = str[i];if(currentChar != c)
result += currentChar;}return result;}
É assim que eu fiz.
Ou você pode fazer o que Antoine mencionou:
Veja esta pergunta
que responde ao mesmo problema. No seu caso:
Acho que o método std: remove funciona, mas estava apresentando alguns problemas de compatibilidade com os includes, então acabei escrevendo esta pequena função:
Você acha certo. Em vez de escrever o seu próprio, é melhor descobrir por que você não pode usar cabeçalhos C ++ padrão.
xtofl
Bem, essa é uma opinião pessoal xtofl, Nem sempre é bom usar o terceiro código - você na verdade não sabe o que ele faz nem as performances ao invés de escrever o que você precisa especificamente.
Damien
1
Eu entendo o que você quer dizer. No entanto, é humildade que me faz escolher a versão que foi revisada, testada e otimizada por escritores de biblioteca profissionais em tempo integral, ao invés da minha própria. A biblioteca padrão pode ser considerada como conhecimento necessário: suas funções, bem como sua complexidade de tempo de execução.
xtofl
Strings à parte, é uma solução C para um problema C ++. Eu não acho que isso deveria ter sido rejeitado.
Basicamente, sempre que encontro um determinado char, avanço o deslocamento e realoco o char para o índice correto. Não sei se isso é correto ou eficiente, estou começando (mais uma vez) em C ++ e gostaria de receber qualquer contribuição sobre isso.
''
não é um personagem de fato.Respostas:
Basicamente,
replace
substitui um personagem por outro e''
não é um personagem. O que você está procurando éerase
.Veja esta pergunta que responde ao mesmo problema. No seu caso:
Ou use
boost
se for uma opção para você, como:Tudo isso está bem documentado em sites de referência . Mas se você não conhecesse essas funções, você poderia facilmente fazer este tipo de coisas manualmente:
fonte
O(n^2)
?n
é o comprimento da string original. Para cada caractere de entrada, eu faço um teste de caractereO(1)
e 0 ou 1 acréscimo de caractere. O acréscimo de caracteresO(1)
se houver memória suficiente reservada ouO(current_length)
se um novo buffer for alocado. Se você fizer issooutput.reserve(str.size())
antes do loop, isso nunca acontecerá e você terá umO(n)
custo global . Caso contrário, de forma assintótica, acho que o custo se deve àO(n . log(n) )
estratégia de realocação do contêiner STL.for
é a mais adequada.O algoritmo
std::replace
funciona por elemento em uma determinada sequência (portanto, substitui elementos por elementos diferentes e não pode substituí-lo por nada ). Mas não existe um personagem vazio . Se você quiser remover elementos de uma sequência, os seguintes elementos devem ser movidos estd::replace
não funcionam assim.Você pode tentar usar
std::remove
( junto comstd::erase
) para conseguir isso.fonte
Usando
copy_if
:fonte
É assim que eu fiz.
Ou você pode fazer o que Antoine mencionou:
fonte
Este código remove a repetição de caracteres, ou seja, se a entrada for aaabbcc, a saída será abc.
fonte
Caso você tenha um
predicate
e / ou não vaziooutput
para preencher com a string filtrada, eu consideraria:Na pergunta original, o predicado é
[](char c){return c != 'a';}
fonte
Com base em outras respostas, aqui vai mais um exemplo em que removi todos os caracteres especiais em uma determinada string:
Entrada vs saída:
fonte
Acho que o método std: remove funciona, mas estava apresentando alguns problemas de compatibilidade com os includes, então acabei escrevendo esta pequena função:
Basta usar como
e removerá todas as ocorrências da lista de caracteres fornecida.
Isso também pode ser um pouco mais eficiente, pois o loop retorna após a primeira correspondência, portanto, fazemos menos comparação.
fonte
É assim que eu faço:
Basicamente, sempre que encontro um determinado char, avanço o deslocamento e realoco o char para o índice correto. Não sei se isso é correto ou eficiente, estou começando (mais uma vez) em C ++ e gostaria de receber qualquer contribuição sobre isso.
fonte
Irá remover Y e S maiúsculo de str, deixando "ourtring".
Observe que
remove
é um algoritmo e precisa do cabeçalho<algorithm>
incluído.fonte