Jaki jest preferowany sposób usuwania spacji z łańcucha w C ++? Mógłbym zapętlić wszystkie postacie i zbudować nowy ciąg, ale czy jest lepszy sposób?
222
Najlepiej jest użyć algorytmu remove_if
i isspace:
remove_if(str.begin(), str.end(), isspace);
Teraz sam algorytm nie może zmienić kontenera (tylko modyfikować wartości), więc faktycznie przetasowuje wartości i zwraca wskaźnik do miejsca, w którym powinien być teraz koniec. Musimy więc wywołać string :: erase, aby faktycznie zmodyfikować długość kontenera:
str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
Należy również pamiętać, że remove_if utworzy co najwyżej jedną kopię danych. Oto przykładowa implementacja:
template<typename T, typename P>
T remove_if(T beg, T end, P pred)
{
T dest = beg;
for (T itr = beg;itr != end; ++itr)
if (!pred(*itr))
*(dest++) = *itr;
return dest;
}
erase
później zadzwonić . To zwróci poprawny wynik.isspace
jest UB dla wszystkich zestawów znaków oprócz oryginalnego 7-bitowego ASCII. C99 § 7.4 / 1. to nie dziwi mnie, że to było upvoted w wysokości 71 głosami teraz, mimo że bardzo złe rady.isspace
, dla wszystkich znaków spoza ASCII, z domyślnym wyborem sygnatury w praktycechar
. W ten sposób ma niezdefiniowane zachowanie . Powtarzam to, ponieważ podejrzewam celową próbę zatopienia tego faktu w hałasie.źródło
<algorithm>
aby to działało.Od gamedev
źródło
::isspace
to UB.Czy możesz użyć Boost String Algo? http://www.boost.org/doc/libs/1_35_0/doc/html/string_algo/usage.html#id1290573
źródło
remove_if(str.begin(), str.end(), isspace);
Matt Price. Nie wiem dlaczego. W rzeczywistości wszystkie elementy wspomagające, które mają alternatywy STL, są wolniejsze niż odpowiadające im gcc (wszystkie te, które testowałem). Niektóre z nich są znacznie wolniejsze! (do 5 razy we wstawkach unordered_map) Być może dzieje się tak z powodu pamięci podręcznej procesora w udostępnianym środowisku lub czegoś podobnego.Do przycinania użyj algorytmów ciągu wzmocnionego :
źródło
Możesz użyć tego rozwiązania do usunięcia znaku:
źródło
Cześć, możesz zrobić coś takiego. Ta funkcja usuwa wszystkie spacje.
Zrobiłem inną funkcję, która usuwa wszystkie niepotrzebne spacje.
źródło
Użyj tego:
źródło
Jeśli chcesz to zrobić za pomocą łatwego makra, oto jedno:
Zakłada się, że zrobiłeś
#include <string>
oczywiście.Nazwij to tak:
źródło
Długo korzystałem z poniższej metody - nie jestem pewien jej złożoności.
s.erase(std::unique(s.begin(),s.end(),[](char s,char f){return (f==' '||s==' ');}),s.end());
kiedy chcesz usunąć postać,
' '
a niektóre na przykład-
użyćs.erase(std::unique(s.begin(),s.end(),[](char s,char f){return ((f==' '||s==' ')||(f=='-'||s=='-'));}),s.end());
podobnie po prostu zwiększ
||
liczbę, jeśli liczba znaków, które chcesz usunąć, nie wynosi 1ale jak wspominają inni, idiom usuwania usuń również wydaje się w porządku.
źródło
Ten kod w zasadzie pobiera ciąg znaków i iteruje wszystkie zawarte w nim znaki. Następnie sprawdza, czy ten ciąg jest białą spacją, jeśli nie jest, to znak jest dodawany do nowego ciągu.
źródło
Źródło:
Referencje zaczerpnięte z tego forum.
źródło
W C ++ 20 możesz używać darmowej funkcji std :: erase
Pełny przykład:
Drukuję | tak, że jest oczywiste, że przestrzeń na początku jest również usuwana.
Uwaga: usuwa to tylko spację, a nie każdą inną możliwą postać, którą można uznać za spację, patrz https://en.cppreference.com/w/cpp/string/byte/isspace
źródło
Usuwa wszystkie znaki spacji, takie jak tabulatory i podziały wierszy (C ++ 11):
źródło
wyjście: 2CF4323CB9DE
źródło
źródło
length()
zwraca asize_t
, a nie anint
.erase()
bierze, asize_type
nieint
. Funkcja prawdopodobnie zawiedzie, jeśli napotkane zostaną dwie kolejne spacje, ponieważ indeks jest zawsze zwiększany. Jeśli jedna spacja zostanie usunięta, pętla będzie czytać poza granicami łańcucha. Prawdopodobnie powinieneś usunąć tę odpowiedź, ponieważ wymaga ona dużej pomocy.Obawiam się, że to najlepsze rozwiązanie, jakie mogę wymyślić. Możesz jednak użyć funkcji replace (), aby wstępnie przydzielić wcześniej minimalną wymaganą pamięć, aby nieco przyspieszyć. Otrzymasz nowy ciąg znaków, który prawdopodobnie będzie krótszy, ale zajmuje tyle samo pamięci, ale unikniesz realokacji.
EDYCJA: W zależności od twojej sytuacji, może to powodować mniejsze obciążenie ogólne niż pomieszanie postaci.
Powinieneś wypróbować różne podejścia i przekonać się, co jest dla Ciebie najlepsze: możesz nie mieć żadnych problemów z wydajnością.
źródło