Estou usando o seguinte:
replace (str1.begin(), str1.end(), 'a' , '')
Mas isso está dando erro de compilação.
Estou usando o seguinte:
replace (str1.begin(), str1.end(), 'a' , '')
Mas isso está dando erro de compilação.
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:
#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());
Ou use boost
se for uma opção para você, como:
#include <boost/algorithm/string.hpp>
boost::erase_all(str, "a");
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 loop
for(size_t i = 0; i < str.size(); ++i)
if(str[i] != 'a') output += str[i];
O(n^2)
?
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.
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 e std::replace
não funcionam assim.
Você pode tentar usar std::remove
( junto comstd::erase
) para conseguir isso.
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());
string RemoveChar(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:
#include <algorithm> str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());
Este código remove a repetição de caracteres, ou seja, se a entrada for aaabbcc, a saída será abc.
cin >> s;
ans = "";
ans += s[0];
for(int i = 1;i < s.length();++i)
if(s[i] != s[i-1])
ans += s[i];
cout << ans << endl;
Caso você tenha um predicate
e / ou não vazio output
para preencher com a string filtrada, eu consideraria:
output.reserve(str.size() + output.size());
std::copy_if(str.cbegin(),
str.cend(),
std::back_inserter(output),
predicate});
Na pergunta original, o predicado é [](char c){return c != 'a';}
Com base em outras respostas, aqui vai mais um exemplo em que removi todos os caracteres especiais em uma determinada string:
#include <iostream>
#include <string>
#include <algorithm>
std::string chars(".,?!.:;_,!'\"-");
int main(int argc, char const *argv){
std::string input("oi?");
std::string output = eraseSpecialChars(input);
return 0;
}
std::string eraseSpecialChars(std::string str){
std::string newStr;
newStr.assign(str);
for(int i = 0; i < str.length(); i++){
for(int j = 0; j < chars.length(); j++ ){
if(str.at(i) == chars.at(j)){
char c = str.at(i);
newStr.erase(std::remove(newStr.begin(), newStr.end(), c), newStr.end());
}
}
}
return newStr;
}
Entrada vs saída:
Input:ra,..pha
Output:rapha
Input:ovo,
Output:ovo
Input:a.vo
Output:avo
Input:oi?
Output:oi
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:
string removeCharsFromString(const string str, char* charsToRemove )
{
char c[str.length()+1]; // + terminating char
const char *p = str.c_str();
unsigned int z=0, size = str.length();
unsigned int x;
bool rem=false;
for(x=0; x<size; x++)
{
rem = false;
for (unsigned int i = 0; charsToRemove[i] != 0; i++)
{
if (charsToRemove[i] == p[x])
{
rem = true;
break;
}
}
if (rem == false) c[z++] = p[x];
}
c[z] = '\0';
return string(c);
}
Basta usar como
myString = removeCharsFromString (myString, "abc \ r");
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.
É assim que eu faço:
std::string removeAll(std::string str, char c) {
size_t offset = 0;
size_t size = str.size();
size_t i = 0;
while (i < size - offset) {
if (str[i + offset] == c) {
offset++;
}
if (offset != 0) {
str[i] = str[i + offset];
}
i++;
}
str.resize(size - offset);
return str;
}
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.
#include <string>
#include <algorithm>
std::string str = "YourString";
char chars[] = {'Y', 'S'};
str.erase (std::remove(str.begin(), str.end(), chars[i]), str.end());
Irá remover Y e S maiúsculo de str, deixando "ourtring".
Observe que remove
é um algoritmo e precisa do cabeçalho <algorithm>
incluído.
''
não é um personagem de fato.