Używam następujących:
replace (str1.begin(), str1.end(), 'a' , '')
Ale to daje błąd kompilacji.
Używam następujących:
replace (str1.begin(), str1.end(), 'a' , '')
Ale to daje błąd kompilacji.
Odpowiedzi:
Zasadniczo replace
zastępuje postać inną i ''
nie jest postacią. To, czego szukasz, to erase
.
Zobacz to pytanie, które odpowiada na ten sam problem. W Twoim przypadku:
#include <algorithm>
str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());
Lub użyj, boost
jeśli to opcja dla Ciebie, na przykład:
#include <boost/algorithm/string.hpp>
boost::erase_all(str, "a");
Wszystko to jest dobrze udokumentowane na referencyjnych stron internetowych . Ale jeśli nie znasz tych funkcji, możesz łatwo zrobić tego rodzaju rzeczy ręcznie:
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
jest to oryginalna długość ciągu. Dla każdego znaku wejściowego wykonuję 1 test znaku O(1)
i dołączam 0 lub 1 znak. Dołączanie znaków O(1)
jest wystarczające, O(current_length)
jeśli zarezerwowano wystarczającą ilość pamięci lub przydzielono nowy bufor. Jeśli zrobisz to output.reserve(str.size())
przed pętlą, nigdy się to nie zdarzy i masz globalny O(n)
koszt. W przeciwnym razie asymptotycznie, myślę, że koszt wynika O(n . log(n) )
ze strategii realokacji kontenerów STL.
for
najbardziej odpowiednie jest rozwiązanie z symbolem.
Algorytm std::replace
działa na element w danej sekwencji (więc zastępuje elementy innymi elementami i nie może go niczym zastąpić ). Ale nie ma pustego charakteru. Jeśli chcesz usunąć elementy z sekwencji, poniższe elementy muszą zostać przeniesione i std::replace
nie działa w ten sposób.
Możesz spróbować użyć std::remove
( razem zstd::erase
), aby to osiągnąć.
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;
}
Tak to zrobiłem.
Lub możesz zrobić tak, jak wspomniał Antoine:
Zobacz to pytanie, które odpowiada na ten sam problem. W Twoim przypadku:
#include <algorithm> str.erase(std::remove(str.begin(), str.end(), 'a'), str.end());
W przypadku, gdy masz a predicate
i / lub niepusty output
do wypełnienia przefiltrowanym ciągiem, rozważę:
output.reserve(str.size() + output.size());
std::copy_if(str.cbegin(),
str.cend(),
std::back_inserter(output),
predicate});
W pierwotnym pytaniu orzeczeniem jest [](char c){return c != 'a';}
Ten kod usuwa powtórzenia znaków, tj. Jeśli wejście to aaabbcc, to wyjście będzie miało postać abc. (tablica musi być posortowana, aby ten kod działał)
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;
Opierając się na innych odpowiedziach, oto jeszcze jeden przykład, w którym usunąłem wszystkie specjalne znaki z danego ciągu:
#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;
}
Wejście vs wyjście:
Input:ra,..pha
Output:rapha
Input:ovo,
Output:ovo
Input:a.vo
Output:avo
Input:oi?
Output:oi
70% szybsze rozwiązanie niż najlepsza odpowiedź
void removeCharsFromString(std::string& str, const char* charsToRemove)
{
size_t charsToRemoveLen = strlen(charsToRemove);
std::remove_if(str.begin(), str.end(), [charsToRemove, charsToRemoveLen](char ch) -> bool
{
for (int i = 0; i < charsToRemoveLen; ++i) {
if (ch == charsToRemove[i])
return true;
}
return false;
});
}
Wydaje mi się, że metoda std: remove działa, ale dawała pewien problem ze zgodnością z dołączeniami, więc napisałem tę małą funkcję:
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);
}
Po prostu użyj jako
myString = removeCharsFromString (myString, "abc \ r");
i usunie wszystkie wystąpienia z podanej listy znaków.
Może to być również nieco bardziej wydajne, gdy pętla powraca po pierwszym dopasowaniu, więc w rzeczywistości robimy mniej porównań.
Oto jak to robię:
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;
}
Zasadniczo za każdym razem, gdy znajduję dany znak, przesuwam przesunięcie i przenoszę znak do właściwego indeksu. Nie wiem, czy to jest poprawne czy wydajne, zaczynam (jeszcze raz) od C ++ i byłbym wdzięczny za wszelkie uwagi na ten temat.
#include <string>
#include <algorithm>
std::string str = "YourString";
char chars[] = {'Y', 'S'};
str.erase (std::remove(str.begin(), str.end(), chars[i]), str.end());
Usunie wielkie Y i S ze str, pozostawiając „ourtring”.
Zauważ, że remove
jest to algorytm i wymaga <algorithm>
dołączonego nagłówka .
''
nie jest w istocie postacią.