@MatthieuM. Twój przykład jest mylący, myślę, że istotą pytania jest modyfikacja oryginalnego ciągu, w twoim przykładzie nie modyfikujesz oryginalnego ciągu, ponieważ w twoim przykładzie oryginalny ciąg nazywa się „myString”, co powoduje zamieszanie, w pytaniu jest to „st”. Kod powinien być: st = st.substr(0, st.size()-1). Ale to nadal nie wygląda we właściwy sposób, myślę, że właściwym sposobem jest użycie funkcji, który jest przeznaczony do tego zadania, to się nazywa erase (), a kod jest: st.erase(st.size()-1). Nazywa się to „wersją mutującą”.
Czarek Tomczak
1
@CzarekTomczak: Rozumiem, że nie jest to dokładnie to, o co poproszono, dlatego wyłączenie odpowiedzialności przed samą istotą.
Matthieu M.
2
@MattPhillips: jego rozwiązanie jest jednak specyficzne dla C ++ 11 ( pop_backnie istniało w C ++ 03) i jest to również modyfikacja na miejscu (a OP nigdy nie wyjaśnił, czy chce na miejscu, czy nie) ... as takie, że ma się poprawną odpowiedź, ale nie jest to możliwe tylko jeden.
Matthieu M.,
404
Proste rozwiązanie, jeśli używasz C ++ 11. Prawdopodobnie również czas O (1):
Jako FYI - jest obsługiwany tylko z GCC 4.7 (oczywiście wraz z przełącznikiem kompilacji -std = c ++ 11)
Shmil The Cat
20
Nie zapomnij sprawdzić length().
Tak, wydaje się, że jest za daleko na stronie ...!
James Bedford
1
The behavior is undefined if the string is empty. od tutaj
Raffi
24
if(str.size ()>0) str.resize (str.size ()-1);
Alternatywa std :: erase jest dobra, ale podoba mi się „- 1” (niezależnie od tego, czy jest to rozmiar, czy iterator końcowy) - pomaga mi wyrazić zamiar.
BTW - Czy naprawdę nie ma std :: string :: pop_back? - wydaje się dziwny.
Nie ma std::string::pop_backw C ++ 03; został jednak dodany w C ++ 0x.
James McNellis
Ok dzięki. Spowodowało to trochę zamieszania - mógłbym przysiąc, że go użyłem, ale go nie ma. Może mam gdzieś niestandardową bibliotekę w jakimś kompilatorze (między VC ++ 2003, VC ++ 2008, MinGW GCC3 MinGW GCC 4 i Linux GCC 4, masz kilka różnic). Bardziej prawdopodobne jest, że mylę się z innymi typami.
Steve314
resize () prawdopodobnie nie jest przeznaczony do takiego zastosowania, jest to funkcja związana z pamięcią, erase () służy do usuwania znaków.
Czarek Tomczak
3
@Czarek Tomczak - przepraszam za absurdalnie spóźnioną odpowiedź, ale resizejest to funkcja zmiany rozmiaru i nie jest już funkcją pamięci, niż cokolwiek innego, co mogłoby zwiększyć potrzebną pamięć. Na przykład, jeśli masz resizemniejszy rozmiar, nie zmniejszy to zarezerwowanej pamięci. Myślę, że myślisz o tym reserve, co najmniej może zmniejszyć przydzieloną pamięć, jeśli zostaniesz o to poproszony - zobacz tutaj zmień rozmiar i zarezerwuj tutaj .
Steve314,
3
if (! str.empty ()) jest
lepszy
19
buf.erase(buf.size()-1);
Zakłada się, że wiesz, że ciąg nie jest pusty. Jeśli tak, otrzymasz out_of_rangewyjątek.
buf [buf.size () - 1] = '\ 0'; niczego nie usuwa - po prostu zmienia znak, który miał tam wartość zero. std:; łańcuchy mogą szczęśliwie zawierać takie znaki.
Neil ma rację. Prawdopodobnie powinienem to wyjaśnić w mojej odpowiedzi. Druga opcja skutecznie zmieni wartość ostatniego znaku, więc nie będzie drukowany, ale długość łańcucha pozostanie taka sama. Użycie kasowania faktycznie „usuwa” ostatni znak i zmieni rozmiar łańcucha.
RC.
@RC Zostanie wydrukowane, zakładając, że używasz czegoś takiego jak cout << buf. To, jak będzie wyglądać, zależy od twojej platformy. Zawsze możesz to wyjaśnić, edytując odpowiedź.
Co jest znacznie lepszego size() w porównaniu end()z inną odpowiedzią?
Może to prowadzić do dziwnej sytuacji: rozmiar łańcucha został zmniejszony, ale ostatni znak nie jest ustawiony na „\ 0”.
Deqing
1
@ Deqing, czy możesz podać więcej szczegółów na temat tego, co dzieje się w takim przypadku?
ribamar
Na przykład, jeśli string s("abc");po erase wydaje robocza: cout<<s; // prints "ab"jednak ostatni znak jest nadal istnieje: cout<<s[2]; // still prints 'c'.
Deqing
1
łatwo naprawić: juststr[str.length()-1] = 0; str.erase(str.end()-1);
taxilian
5
@Dequing: twój przykład jest nieprawidłowy. Kasowanie zmniejsza rozmiar ciągu, więc dostęp do niego s[2]jest nielegalny.
CString str=CString("Hello world"); str.Delete(str.GetLength()-1);
Odpowiedzi:
W przypadku wersji niemutującej:
źródło
st = st.substr(0, st.size()-1)
. Ale to nadal nie wygląda we właściwy sposób, myślę, że właściwym sposobem jest użycie funkcji, który jest przeznaczony do tego zadania, to się nazywa erase (), a kod jest:st.erase(st.size()-1)
. Nazywa się to „wersją mutującą”.pop_back
nie istniało w C ++ 03) i jest to również modyfikacja na miejscu (a OP nigdy nie wyjaśnił, czy chce na miejscu, czy nie) ... as takie, że ma się poprawną odpowiedź, ale nie jest to możliwe tylko jeden.Proste rozwiązanie, jeśli używasz C ++ 11. Prawdopodobnie również czas O (1):
źródło
length()
.The behavior is undefined if the string is empty.
od tutajAlternatywa std :: erase jest dobra, ale podoba mi się „- 1” (niezależnie od tego, czy jest to rozmiar, czy iterator końcowy) - pomaga mi wyrazić zamiar.
BTW - Czy naprawdę nie ma std :: string :: pop_back? - wydaje się dziwny.
źródło
std::string::pop_back
w C ++ 03; został jednak dodany w C ++ 0x.resize
jest to funkcja zmiany rozmiaru i nie jest już funkcją pamięci, niż cokolwiek innego, co mogłoby zwiększyć potrzebną pamięć. Na przykład, jeśli maszresize
mniejszy rozmiar, nie zmniejszy to zarezerwowanej pamięci. Myślę, że myślisz o tymreserve
, co najmniej może zmniejszyć przydzieloną pamięć, jeśli zostaniesz o to poproszony - zobacz tutaj zmień rozmiar i zarezerwuj tutaj .Zakłada się, że wiesz, że ciąg nie jest pusty. Jeśli tak, otrzymasz
out_of_range
wyjątek.źródło
size()
w porównaniuend()
z inną odpowiedzią?str.erase( str.end()-1 )
Odniesienie: prototyp std :: string :: erase () 2
nie wymaga c ++ 11 lub c ++ 0x.
źródło
string s("abc");
po erase wydaje robocza:cout<<s; // prints "ab"
jednak ostatni znak jest nadal istnieje:cout<<s[2]; // still prints 'c'
.str[str.length()-1] = 0; str.erase(str.end()-1);
s[2]
jest nielegalny.To wszystko, czego potrzebujesz:
źródło
źródło
Dzięki C ++ 11 nie potrzebujesz nawet długości / rozmiaru. Dopóki łańcuch nie jest pusty, możesz wykonać następujące czynności:
źródło
str.erase(str.begin() + str.size() - 1)
str.erase(str.rbegin())
nie kompiluje się niestety, ponieważreverse_iterator
nie można go przekonwertować na normal_iterator.C ++ 11 jest twoim przyjacielem w tym przypadku.
źródło
str.erase(str.end() - 1)
?Jeśli długość nie jest równa zero, możesz również
źródło
\0
nie zmienia długości łańcucha.str.length()
będzie niedokładny.