J'utilise ce qui suit:
replace (str1.begin(), str1.end(), 'a' , '')
Mais cela donne une erreur de compilation.
J'utilise ce qui suit:
replace (str1.begin(), str1.end(), 'a' , '')
Mais cela donne une erreur de compilation.
Réponses:
Fondamentalement, replace
remplace un caractère par un autre et ''
n'est pas un personnage. Ce que vous recherchez, c'est erase
.
Voir cette question qui répond au même problème. Dans ton cas:
#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());
Ou utilisez boost
si c'est une option pour vous, comme:
#include <boost/algorithm/string.hpp>
boost::erase_all(str, "a");
Tout cela est bien documenté sur les sites Web de référence . Mais si vous ne connaissez pas ces fonctions, vous pouvez facilement faire ce genre de choses à la main:
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
s'agit de la longueur de chaîne d'origine. Pour chaque caractère d'entrée, je fais 1 test de caractère O(1)
et 0 ou 1 caractère ajouté. L'ajout de caractères O(1)
est une quantité suffisante de mémoire réservée ou O(current_length)
si un nouveau tampon est alloué. Si vous le faites output.reserve(str.size())
avant la boucle, cela ne se produit jamais et vous avez un O(n)
coût global . Sinon, de manière asymptotique, je suppose que le coût est O(n . log(n) )
dû à la stratégie de réallocation des conteneurs STL.
for
est la plus adaptée.
L'algorithme std::replace
fonctionne par élément sur une séquence donnée (il remplace donc les éléments par des éléments différents, et ne peut pas le remplacer par rien ). Mais il n'y a pas de caractère vide . Si vous souhaitez supprimer des éléments d'une séquence, les éléments suivants doivent être déplacés et std::replace
ne fonctionnent pas comme ceci.
Vous pouvez essayer d'utiliser std::remove
( avecstd::erase
) pour y parvenir.
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;
}
Voilà comment je l'ai fait.
Ou vous pouvez faire comme Antoine l'a mentionné:
Voir cette question qui répond au même problème. Dans ton cas:
#include <algorithm> str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());
Ce code supprime la répétition des caractères, c'est-à-dire que si l'entrée est aaabbcc alors la sortie sera 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;
Au cas où vous auriez un predicate
et / ou un non vide output
à remplir avec la chaîne filtrée, je considérerais:
output.reserve(str.size() + output.size());
std::copy_if(str.cbegin(),
str.cend(),
std::back_inserter(output),
predicate});
Dans la question d'origine, le prédicat est [](char c){return c != 'a';}
Sur la base d'autres réponses, voici un autre exemple où j'ai supprimé tous les caractères spéciaux dans une chaîne donnée:
#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;
}
Entrée vs sortie:
Input:ra,..pha
Output:rapha
Input:ovo,
Output:ovo
Input:a.vo
Output:avo
Input:oi?
Output:oi
Je suppose que la méthode std: remove fonctionne mais cela posait un problème de compatibilité avec les includes donc j'ai fini par écrire cette petite fonction:
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);
}
Utilisez simplement comme
myString = removeCharsFromString (maString, "abc \ r");
et il supprimera toutes les occurrences de la liste de caractères donnée.
Cela peut également être un peu plus efficace car la boucle revient après la première correspondance, nous faisons donc moins de comparaison.
Voici comment je fais:
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;
}
Fondamentalement, chaque fois que je trouve un caractère donné, j'avance le décalage et je déplace le caractère vers l'index correct. Je ne sais pas si c'est correct ou efficace, je commence (encore une fois) au C ++ et j'apprécierais toute contribution à ce sujet.
#include <string>
#include <algorithm>
std::string str = "YourString";
char chars[] = {'Y', 'S'};
str.erase (std::remove(str.begin(), str.end(), chars[i]), str.end());
Supprime les majuscules Y et S de str, laissant "ourtring".
Notez qu'il remove
s'agit d'un algorithme et que l'en-tête doit être <algorithm>
inclus.
''
n'est en effet pas un personnage.