Was ist der beste Weg, um trim std::string?
Derzeit bin ich über den folgenden code nach rechts trimmen alle std::strings
in meinen Programmen:
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
Es funktioniert gut, aber ich Frage mich, ob gibt es einige end-Fällen, in denen es möglicherweise nicht?
Natürlich Antworten mit eleganten alternativen und auch zu den linken Trimm-Lösung sind willkommen.
Die Antworten auf diese Frage sind ein Beweis dafür, wie ohne die C++ standard-Bibliothek ist.
Und es immer noch nicht über diese Funktion in C++11.
Toll, nicht wahr! Blick auf die konkurrierenden Optionen, die wir jetzt zur Verfügung haben, die nicht durch eine einzelne person, die die Idee des "das Weg, wir müssen es tun"!
Funktionalität innerhalb einer Art, nun, das ist eine design-Entscheidung, und das hinzufügen einer trim-Funktion, um einen string könnte (zumindest unter c++) nicht die beste Lösung sowieso - aber weder standard-Weg, es zu tun, statt, sodass jeder Nutzer ärgern über die gleichen solche kleinen Fragen immer und immer wieder, ist sicherlich nicht zu helfen, wer entweder
Sie können die Frage stellen, warum trimmen Funktionen sind nicht eingebaut in die
Und es immer noch nicht über diese Funktion in C++11.
Toll, nicht wahr! Blick auf die konkurrierenden Optionen, die wir jetzt zur Verfügung haben, die nicht durch eine einzelne person, die die Idee des "das Weg, wir müssen es tun"!
Funktionalität innerhalb einer Art, nun, das ist eine design-Entscheidung, und das hinzufügen einer trim-Funktion, um einen string könnte (zumindest unter c++) nicht die beste Lösung sowieso - aber weder standard-Weg, es zu tun, statt, sodass jeder Nutzer ärgern über die gleichen solche kleinen Fragen immer und immer wieder, ist sicherlich nicht zu helfen, wer entweder
Sie können die Frage stellen, warum trimmen Funktionen sind nicht eingebaut in die
std::string
Klasse, wenn er Funktionen wie diese, die in anderen Sprachen so gut zu benutzen (Python zum Beispiel).InformationsquelleAutor Milan Babuškov | 2008-10-19
Du musst angemeldet sein, um einen Kommentar abzugeben.
BEARBEITEN, Da c++17, einige Teile der standard-Bibliothek entfernt wurden. Zum Glück, beginnend mit c++11 haben wir Lambda-Ausdrücke, die eine überlegene Lösung.
Dank https://stackoverflow.com/a/44973498/524503 für die moderne Lösung.
Original Antwort:
Ich Neige dazu, verwenden Sie eine dieser 3 für meine trimmen muss:
Sind Sie ziemlich selbsterklärend und funktioniert sehr gut.
BEARBEITEN: BTW, ich habe
std::ptr_fun
dort zu helfen, keine Verwechslungenstd::isspace
denn es gibt tatsächlich eine zweite definition, die unterstützt Gebietsschemas. Dies hätte eine Besetzung genau das gleiche, aber ich Neige dazu, dies besser.BEARBEITEN: einige Bemerkungen über die Annahme von parameter-Referenz, änderung und Rückgabe. Ich Bin Damit Einverstanden. Eine Umsetzung, die würde ich wahrscheinlich bevorzugen würde, werden zwei Gruppen von Funktionen, eine für die im Ort und man macht eine Kopie. Bessere Beispiele wären:
Bin ich unter Beibehaltung der ursprünglichen Antwort oben aber für den Zusammenhang und im Interesse, dass die hohe stimmten die Antwort noch verfügbar.
boost::trim
um das problem zu lösen.Ich würd Zeiger verwenden anstelle von Referenzen, so dass von der callpoint ist viel einfacher zu verstehen, dass diese Funktionen Bearbeiten Sie die Zeichenfolge im Ort, anstatt eine Kopie erstellen.
Beachten Sie, dass mit isspace können Sie leicht Undefiniertes Verhalten mit nicht-ASCII-Zeichen stacked-crooked.com/view?id=49bf8b0759f0dd36dffdad47663ac69f
Warum die statische? Das ist, wo ein anonymer namespace würden bevorzugt werden?
sicher, man könnte eine anonyme namespace statt, wenn Sie bevorzugen.
InformationsquelleAutor Evan Teran
Mit Boost string algorithmen wäre das einfachste:
str
ist jetzt"hello world!"
. Es gibt auchtrim_left
undtrim
, die Borten beiden Seiten.Wenn Sie hinzufügen
_copy
suffix zu einem der oben genannten Funktionsnamen sind z.B.trim_copy
, die Funktion gibt eine getrimmte Kopie des Strings anstelle von ändern es durch einen Verweis.Wenn Sie hinzufügen
_if
suffix zu einem der oben genannten Funktionsnamen sind z.B.trim_copy_if
können Sie trimmen alle Zeichen der Befriedigung der eigenen custom-Prädikat, im Gegensatz zu nur Leerzeichen.Boost ist, wie eine massive hammer für so ein winziges problem.
Boost löst viele kleine Probleme. Es ist ein massiver hammer, das löst eine Menge.
Boost ist eine Sammlung von hämmern in vielen verschiedenen Größen lösen viele andere Probleme.
Sie sagen das, als ob Boost ist eine alles-oder-nichts-monolith, wo man seinen Header irgendwie zufügt, die ganze Sache auf dem Programm. Was natürlich nicht der Fall ist. Btw, ich habe noch nie verwendet, Boost, fwiw.
InformationsquelleAutor Leon Timmermans
Verwenden Sie den folgenden code nach rechts trim (trailing) Leerzeichen und Tabulator-Zeichen von
std::strings
(ideone):Und nur um die Dinge auszugleichen, werde ich die Links kürzen-code zu (ideone):
Recht. Sie haben, um es anzupassen, für den whitespace-Zeichen, die Sie schauen, um zu trimmen. Meine Besondere Anwendung wurde nur erwartet, Leerzeichen und Tabulatoren, aber Sie können hinzufügen \n\r fangen die anderen.
str.substr(...).swap(str)
ist besser. Speichern einer Zuordnung.Wird es nicht verwenden, bewegen Zuordnung
basic_string& operator= (basic_string&& str) noexcept;
?Diese Antwort ändert sich nicht, die Zeichenfolgen, die ALLE Räume. Das ist ein fail.
InformationsquelleAutor Bill the Lizard
Bisschen spät, um der Partei, aber nie Verstand. Jetzt C++11 ist hier, wir haben lambdas und auto-Variablen. Also meine version, die auch Griffe all-whitespace-Zeichen und leere strings, ist:
Könnten wir einen reverse-iterator von
wsfront
und verwenden Sie, dass als Abbruchbedingung in der zweitenfind_if_not
aber das ist nur nützlich im Falle von all-whitespace-string, und gcc 4.8 mindestens nicht klug genug, um Rückschlüsse auf die Art der reverse-iterator (std::string::const_reverse_iterator
) mitauto
. Ich weiß nicht, wie teuer konstruieren ein reverse-iterator ist, so YMMV hier. Mit dieser änderung wird der code wie folgt aussieht:Ich will immer eine Funktion aufrufen, um die trim-string, statt es umzusetzen
Für was es Wert ist, es gibt keine Notwendigkeit zu verwenden, die lambda. Sie können nur übergeben
std::isspace
:auto wsfront=std::find_if_not(s.begin(),s.end(),std::isspace);
+1 wahrscheinlich die einzige Antwort, mit der Umsetzung, die nur eine O(N) string kopieren.
Compiler sind nicht unbedingt so schlau. tun, was Sie sagen, ist zweideutig:
candidate template ignored: couldn't infer template argument '_Predicate' find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred)
InformationsquelleAutor David G
Was du tust ist gut und robust. Ich habe die gleiche Methode, die für eine lange Zeit und ich habe noch zu finden, eine schnellere Methode:
Durch Angabe der Zeichen, die abgeschnitten werden, haben Sie die Flexibilität zu trimmen, nicht-whitespace-Zeichen und die Effizienz zu trimmen, nur die Zeichen, die Sie getrimmt.
trim
, D. H.rtrim(ltrim(s, t), t)
es wird etwas effizienterDie innere Funktion wird zuerst durchgeführt, so dass Sie Ihren Weg es wird trim von der linken Seite, bevor trimmen von rechts. Ich denke, das wäre weniger effizienter wäre es nicht?
Genau. Mein Fehler
InformationsquelleAutor Galik
Versuchen Sie dieses, es funktioniert für mich.
Bitte erklären.
str.find_last_not_of(x)
gibt die position des ersten Zeichens nicht gleich x ist. Es gibt nur npos, wenn keine chars passen nicht zu x ist. In dem Beispiel, wenn es keine suffixing Räume, wird es wieder das äquivalent vonstr.length() - 1
, was im wesentlichenstr.erase((str.length() - 1) + 1).
ist, wenn ich mich nicht furchtbar Irre.Sieht aus wie du Recht hast. Entschuldigung an die Beantworter.
Ich bin verwirrt, warum dies gibt eine Kopie nach dem ändern der return-parameter?
Meine Verwirrung ist, warum bringen Sie eine Kopie statt eine Referenz. Es macht mehr Sinn für mich zurück
std::string&
.InformationsquelleAutor user818330
Ich mag tzaman Lösung, das einzige problem dabei ist, dass Sie nicht schneiden Sie ein string der nur aus Leerzeichen besteht.
Korrigieren, dass 1 Fehler, hinzufügen str.clear () - zwischen den 2 trimmer-Linien
ltrim
oderrtrim
wie diese.Gut, aber können nicht damit umgehen string mit internen Leerzeichen. z.B. trim( abc def") -> abc und nur abc Links.
nicht arbeiten, haben wir die Räume zwischen den
Eine gute Lösung, wenn Sie wissen, dass es keine internen whitespaces!
Das ist schön und einfach, aber es ist auch Recht langsam, als der string wird kopiert und in die und aus der
std::stringstream
.InformationsquelleAutor Michaël Schoonbrood
http://ideone.com/nFVtEo
Wie das funktioniert: Dies ist eine Kopie-wie Lösung - es findet die position des ersten Zeichen, das kein Leerzeichen(
it
) und Umgekehrt: die position des Zeichens nach dem es nur Leerzeichen(rit
) - danach gibt es eine neu erstellte Zeichenfolge == eine Kopie der Teil der ursprünglichen Zeichenfolge - Teil basiert auf diesen Iteratoren...Danke, für mich gearbeitet: std:string s = "Oh noez: space \r\n"; std::string clean = trim(s);
InformationsquelleAutor Pushkoff
In dem Fall ein leerer string ist, wird Ihr code wird davon ausgegangen, dass das hinzufügen von 1 bis
string::npos
gibt 0.string::npos
ist der Typstring::size_type
, die nicht signiert ist. Also, Sie verlassen sich auf das overflow-Verhalten hinaus.Hinzufügen
1
zustd::string::npos
muss geben0
nach derC++ Standard
. So ist es eine gute Annahme, die können sich absolut darauf verlassen.InformationsquelleAutor Greg Hewgill
Gehackt aus der Cplusplus.com
Diese Werke für den null-Fall sowie. 🙂
rtrim
, nichtltrim
^ tun Sie dagegen, mit find_first_not_of? Es ist relativ einfach, es zu ändern.
InformationsquelleAutor Paul Nathan
Meine Lösung basiert auf der Antwort von @Bill, die Eidechse.
Beachten Sie, dass diese Funktionen wird ein leerer string zurückgegeben, wenn die Eingabe-Zeichenfolge enthält nichts außer whitespace-Zeichen.
InformationsquelleAutor DavidRR
Meine Antwort ist eine Verbesserung auf der top Antwort für diesen post, Borten control-Zeichen sowie Leerzeichen (0-32 und 127 auf die ASCII-Tabelle).
std::isgraph
bestimmt, ob ein Charakter eine grafische Darstellung, so dass Sie verwenden können, dies zu ändern Evan ' s Antwort zu löschen, alle Zeichen, die nicht über eine grafische Darstellung von beiden Seiten einer Zeichenfolge. Das Ergebnis ist eine viel elegantere Lösung:Hinweis: Alternativ sollten Sie in der Lage sein zu verwenden
std::iswgraph
, wenn Sie brauchen Unterstützung für wide-Zeichen, aber Sie haben auch diesen code Bearbeiten, um zu ermöglichenstd::wstring
manipulation, das ist etwas, was ich noch nicht getestet, (siehe die Referenz-Seite fürstd::basic_string
zu erkunden, diese option).InformationsquelleAutor Clay Freeman
Mit C++11 kamen auch ein regulärer Ausdruck Modul, das kann verwendet werden, zu trimmen führende oder nachfolgende Leerzeichen.
Vielleicht so etwas wie dieses:
InformationsquelleAutor Some programmer dude
Dies ist, was ich verwenden. Nur halten Sie das entfernen von Leerzeichen von der front, und dann, wenn es etwas nach Links, das gleiche tun auf der Rückseite.
InformationsquelleAutor synaptik
Für was es Wert ist, hier ist eine trim-Implementierung mit einem Auge in Richtung performance. Es ist viel schneller als viele andere trim-Routinen, die ich gesehen habe um. Anstelle der Verwendung von Iteratoren und std::findet, verwendet es roh c-strings und-Indizes. Es optimiert den folgenden besonderen Fällen: Größe 0-Zeichenfolge (nichts tun), string ohne Leerzeichen, trim (nichts tun), string mit nur Leerzeichen zu trimmen (nur die Größe der Zeichenfolge) Zeichenfolge, die ganz whitespace-Zeichen (löschen Sie einfach die Zeichenfolge). Und schließlich, im schlimmsten Fall (Zeichenkette mit führenden Leerzeichen), es tut sein bestes geben, um eine effiziente kopieren Konstruktion, Durchführung nur 1 kopieren und dann verschieben, kopieren, an die Stelle der ursprünglichen Zeichenfolge.
InformationsquelleAutor mbgda
Wäre es etwas effizienter, wenn man diese in das Gegenteil um und schneiden aus den richtigen ersten vor dem Aufruf einer Verschiebung durch abschneiden der linken.
InformationsquelleAutor freeboy1015
Einen eleganten Weg, es zu tun sein kann, wie
Sowie die unterstützenden Funktionen sind implementiert:
Und sobald Sie haben alle diese, können Sie schreiben so gut:
InformationsquelleAutor gjha
Trim C++11 Umsetzung:
InformationsquelleAutor GutiMac
Ich denke, wenn Sie anfangen zu Fragen, für den "besten Weg" zu trimmen ist eine Zeichenfolge, würde ich sagen, eine gute Umsetzung wäre ein:
Offensichtlich gibt es zu viele verschiedene Möglichkeiten, dies zu nähern und es auf jeden Fall, hängt davon ab, was Sie eigentlich brauchen. Aber der C-standard-Bibliothek hat noch einige sehr nützliche Funktionen in <string.h>, wie memchr. Es gibt einen Grund, warum C gilt immer noch als die beste Sprache für IO - seine stdlib ist pure Effizienz.
InformationsquelleAutor Jorma Rebane
Mit C++17, die Sie verwenden können basic_string_view::remove_prefix und basic_string_view::remove_suffix:
InformationsquelleAutor Phidelux
Ich bin mir nicht sicher, ob Ihre Umgebung ist die gleiche, aber in mir, die leere Zeichenfolge Fall dazu, dass das Programm abgebrochen wird. Ich würde entweder wickeln, löschen, rufen Sie mit einer if(!s.empty()) oder die Verwendung von Boost wie bereits erwähnt.
InformationsquelleAutor Steve
Hier ist, was ich kam mit:
Stream-Extraktion eliminiert Leerzeichen automatisch, so dass dies funktioniert wie ein Charme.
Ziemlich sauber und elegant zu, wenn ich so sagen selbst. 😉
InformationsquelleAutor tzaman
Beitrag meine Lösung für den Lärm.
trim
standardmäßig erstellen Sie einen neuen string-und die Rückkehr der veränderten, währendtrim_in_place
ändert den übergebenen string. Dietrim
- Funktion unterstützt c++11 move-Semantik.InformationsquelleAutor vmrob
Diese kann getan werden einfach in C++11 durch die Zugabe von
back()
undpop_back()
.InformationsquelleAutor nobar
Hier ist meine version:
Danke für die Korrektur, Sie haben Recht.
InformationsquelleAutor nulleight
Den oben genannten Methoden sind toll, aber manchmal Sie wollen verwenden Sie eine Kombination von Funktionen für das, was Ihre routine betrachtet werden whitespace-Zeichen. In diesem Fall, mit funktoren zu kombinieren Operationen können sich chaotisch, so dass ich lieber eine einfache Schleife, die ich ändern kann, für die Trimmung. Hier ist eine leicht modifizierte trim-Funktion kopiert von der C-version hier auf ALSO. In diesem Beispiel bin ich beim trimmen nicht alphanumerische Zeichen.
InformationsquelleAutor Corwin Joy
Diese version trimmt die interne Leerzeichen und nicht-alphanumerische Zeichen:
InformationsquelleAutor Brian
Noch eine andere option - löscht ein oder mehrere Zeichen von beiden enden.
InformationsquelleAutor Brian W.
Was ist das...?
Hinweis: ich bin noch relativ neu in C++, also bitte verzeihen Sie mir, wenn ich bin off base hier.
regex
für das trimmen ist etwas übertrieben.Ist es viel mehr CPU-Kapazität als einige der anderen Optionen?
Sicher, aber nur um sicher zu sein Profil selbst.
InformationsquelleAutor Duncan
Ich wollte ein update meiner alten C++ - trim-Funktion mit einer C++ 11 Ansatz habe ich getestet, eine Menge von den Antworten auf die Frage. Mein Fazit ist, dass ich meine alten C++ - Lösung!
Es ist die Schnellste, die von großen, auch das hinzufügen von mehr Zeichen zu überprüfen (z.B. \r\n ich sehe keine Verwendung für \f\v) ist immer noch schneller als die Lösungen mit Hilfe von Algorithmus.
InformationsquelleAutor elxala