Entfernen Sie das letzte Zeichen aus der C ++ - Zeichenfolge

210

Wie kann ich das letzte Zeichen aus einer C ++ - Zeichenfolge entfernen?

Ich habe es versucht, st = substr(st.length()-1);aber es hat nicht funktioniert.

skazhy
quelle
6
Möchten Sie eine neue Zeichenfolge mit dem letzten entfernten Zeichen oder dieselbe Zeichenfolge ohne das letzte Zeichen?
Matthieu M.
Für einen MFC Visual C ++ CString: CString str=CString("Hello world"); str.Delete(str.GetLength()-1);
Sergiol

Antworten:

193

Für eine nicht mutierende Version:

st = myString.substr(0, myString.size()-1);
Matthieu M.
quelle
20
@MatthieuM. Ihr Beispiel ist verwirrend. Ich denke, dass der Kern der Frage darin besteht, die ursprüngliche Zeichenfolge zu ändern. In Ihrem Beispiel ändern Sie die ursprüngliche Zeichenfolge nicht, da in Ihrem Beispiel die ursprüngliche Zeichenfolge "myString" heißt, was zu Verwirrung führt. in der frage ist es "st". Ihr Code sollte sein : st = st.substr(0, st.size()-1). Aber es sieht immer noch nicht richtig aus. Ich denke, dass der richtige Weg darin besteht, die für diese Aufgabe vorgesehene Funktion zu verwenden. Sie heißt erase () und der Code lautet : st.erase(st.size()-1). Dies würde als "mutierende Version" bezeichnet.
Czarek Tomczak
1
@CzarekTomczak: Ich verstehe, dass dies nicht genau das ist, wonach gefragt wurde, daher der Haftungsausschluss vor dem eigentlichen Kern.
Matthieu M.
2
@MattPhillips: Seine Lösung ist jedoch C ++ 11-spezifisch ( pop_backgab es in C ++ 03 nicht) und es handelt sich auch um eine direkte Modifikation (und das OP hat nie geklärt, ob er an Ort und Stelle wollte oder nicht) ... as so hat er eine richtige Antwort, aber nicht die einzig mögliche.
Matthieu M.
403

Einfache Lösung, wenn Sie C ++ 11 verwenden. Wahrscheinlich auch O (1) Zeit:

st.pop_back();
mpgaillard
quelle
49
das ist für c ++ 11!
Amir
1
Als FYI - es wird nur von GCC 4.7 unterstützt (natürlich nicht mit dem Kompilierungsschalter -std = c ++ 11)
Shmil The Cat
20
Vergiss nicht zu überprüfen length().
Ja, es erscheint zu weit unten auf der Seite ..!
James Bedford
1
The behavior is undefined if the string is empty. von hier
Raffi
24
if (str.size () > 0)  str.resize (str.size () - 1);

Eine std :: erase-Alternative ist gut, aber ich mag die "- 1" (ob basierend auf einer Größe oder einem Enditerator) - für mich hilft sie, die Absicht auszudrücken.

Übrigens - Gibt es wirklich kein std :: string :: pop_back? - erscheint merkwürdig.

Steve314
quelle
11
Es gibt keine std::string::pop_backin C ++ 03; Es wurde jedoch in C ++ 0x hinzugefügt.
James McNellis
OK danke. Es hat ein bisschen Verwirrung gestiftet - ich könnte schwören, dass ich es benutzt habe, aber es ist nicht da. Vielleicht habe ich irgendwo eine nicht standardmäßige Bibliothek in einem Compiler (zwischen VC ++ 2003, VC ++ 2008, MinGW GCC3, MinGW GCC 4 und Linux GCC 4 gibt es einige Unterschiede). Wahrscheinlicher ist, dass ich nur mit anderen Typen verwechselt werde.
Steve314
resize () ist wahrscheinlich nicht für eine solche Verwendung vorgesehen, es ist eine speicherbezogene Funktion, erase () dient zum Löschen von Zeichen.
Czarek Tomczak
3
@Czarek Tomczak - Entschuldigung für die absurd späte Antwort, aber es resizeist eine Größenänderungsfunktion und keine Speicherfunktion mehr als alles andere, was den benötigten Speicher erhöhen könnte. Wenn Sie beispielsweise resizeeine kleinere Größe wählen, wird der reservierte Speicher nicht reduziert. Ich denke, Sie denken darüber nach reserve, was zumindest den zugewiesenen Speicher reduzieren könnte , wenn Sie dazu aufgefordert werden - siehe Größe hier ändern und hier reservieren .
Steve314
3
if (! str.empty ()) wird der Größe vorgezogen
ericcurtin
18
buf.erase(buf.size() - 1);

Dies setzt voraus, dass Sie wissen, dass die Zeichenfolge nicht leer ist. In diesem Fall erhalten Sie eine out_of_rangeAusnahme.

RC.
quelle
8
buf [buf.size () - 1] = '\ 0'; entfernt nichts - es ändert nur das Zeichen, das dort war, um den Wert Null zu haben. std :; Strings können solche Zeichen gerne enthalten.
Neil ist richtig. Ich hätte das wahrscheinlich in meiner Antwort klarstellen sollen. Die zweite Option ändert effektiv den Wert des letzten Zeichens, damit es nicht gedruckt wird, aber die Zeichenfolgenlänge bleibt gleich. Durch Löschen wird das letzte Zeichen "entfernt" und die Größe der Zeichenfolge geändert.
RC.
@RC Es wird gedruckt, vorausgesetzt, Sie verwenden so etwas wie cout << buf. Wie es aussieht, hängt von Ihrer Plattform ab. Und Sie können dies jederzeit klarstellen, indem Sie Ihre Antwort bearbeiten.
Was ist viel besser über size() statt end()einer anderen Antwort?
Ribamar
17

str.erase( str.end()-1 )

Referenz: std :: string :: erase () Prototyp 2

Kein c ++ 11 oder c ++ 0x erforderlich.

Ribamar
quelle
1
Dies kann zu einer seltsamen Situation führen: Die Größe der Zeichenfolge wurde reduziert, aber das letzte Zeichen ist nicht auf '\ 0' gesetzt.
Deqing
1
@Deqing können Sie mehr Details darüber geben, was in einem solchen Fall passiert?
Ribamar
Zum Beispiel, wenn Sie haben string s("abc");, scheint es nach dem Löschen zu funktionieren: cout<<s; // prints "ab"Das letzte Zeichen ist jedoch noch da : cout<<s[2]; // still prints 'c'.
Deqing
1
leicht zu str[str.length()-1] = 0; str.erase(str.end()-1);
beheben
5
@Dequing: Ihr Beispiel ist ungültig. Durch das Löschen wird die Größe der Zeichenfolge verringert, sodass der Zugriff auf s[2]unzulässig ist.
EML
11

Das ist alles was Sie brauchen:

#include <string>  //string::pop_back & string::empty

if (!st.empty())
    st.pop_back();
jcrv
quelle
9
int main () {

  string str1="123";
  string str2 = str1.substr (0,str1.length()-1);

  cout<<str2; // output: 12

  return 0;
}
Codaddict
quelle
2

Mit C ++ 11 benötigen Sie nicht einmal die Länge / Größe. Solange die Zeichenfolge nicht leer ist, können Sie Folgendes tun:

if (!st.empty())
  st.erase(std::prev(st.end())); // Erase element referred to by iterator one
                                 // before the end
Michael Goldshteyn
quelle
2

str.erase(str.begin() + str.size() - 1)

str.erase(str.rbegin()) kompiliert leider nicht da reverse_iterator nicht in einen normal_iterator konvertiert werden kann.

C ++ 11 ist in diesem Fall dein Freund.

Zebra
quelle
Diese Methode hat auch ein Problem, das letzte Zeichen ist nicht auf '\ 0' gesetzt.
Deqing
1
Gibt es einen bestimmten Grund, dies nicht zu tun str.erase(str.end() - 1)?
Vallentin
-4

Wenn die Länge nicht Null ist, können Sie auch

str[str.length() - 1] = '\0';
Jan Glaser
quelle
4
Wenn Sie das letzte Zeichen auf setzen, \0ändert sich die Länge der Zeichenfolge nicht. str.length()wird ungenau sein.
JWW
Ja, ich sehe es jetzt. Wir erwägen C ++. Sie sind richtig, es ändert nicht die Länge der Zeichenfolge
Jan Glaser