Ich verwende derzeit den folgenden Code, um alle Elemente std::strings
in meinen Programmen nach rechts zu kürzen :
std::string s;
s.erase(s.find_last_not_of(" \n\r\t")+1);
Es funktioniert gut, aber ich frage mich, ob es einige Endfälle gibt, in denen es fehlschlagen könnte.
Antworten mit eleganten Alternativen und auch Links-Trimm-Lösungen sind natürlich willkommen.
std::string
Klasse integriert sind, wenn es Funktionen wie diese sind, die die Verwendung anderer Sprachen so angenehm machen (z. B. Python).Antworten:
BEARBEITEN Seit c ++ 17 wurden einige Teile der Standardbibliothek entfernt. Glücklicherweise haben wir ab c ++ 11 Lambdas, die eine überlegene Lösung darstellen.
Vielen Dank an https://stackoverflow.com/a/44973498/524503 für die Einführung der modernen Lösung.
Ursprüngliche Antwort:
Ich neige dazu, eine dieser 3 für meine Trimmbedürfnisse zu verwenden:
Sie sind ziemlich selbsterklärend und funktionieren sehr gut.
EDIT : Übrigens, ich habe
std::ptr_fun
da drin, um bei der Disambiguierung zu helfen,std::isspace
da es tatsächlich eine zweite Definition gibt, die Gebietsschemas unterstützt. Dies hätte trotzdem eine Besetzung sein können, aber ich mag das eher besser.BEARBEITEN : Um einige Kommentare zum Akzeptieren eines Parameters als Referenz, zum Ändern und Zurückgeben zu beantworten. Genau. Eine Implementierung, die ich wahrscheinlich bevorzugen würde, wären zwei Funktionssätze, einer für In-Place und einer, der eine Kopie erstellt. Eine bessere Reihe von Beispielen wäre:
Ich behalte die obige ursprüngliche Antwort jedoch für den Kontext und im Interesse, die hochstimmige Antwort weiterhin verfügbar zu halten.
quelle
boost::trim
das Problem gelöst.Die Verwendung der String-Algorithmen von Boost wäre am einfachsten:
str
ist jetzt"hello world!"
. Es gibt auchtrim_left
undtrim
, die beide Seiten trimmt.Wenn Sie
_copy
einem der oben genannten Funktionsnamen ein Suffix hinzufügen , z. B.trim_copy
gibt die Funktion eine zugeschnittene Kopie der Zeichenfolge zurück, anstatt sie über eine Referenz zu ändern.Wenn Sie
_if
einem der oben genannten Funktionsnamen ein Suffix hinzufügen , z. B.trim_copy_if
können Sie alle Zeichen kürzen, die Ihrem benutzerdefinierten Prädikat entsprechen, und nicht nur Leerzeichen.quelle
Verwenden Sie den folgenden Code, um Leerzeichen und Tabulatorzeichen von
std::strings
( ideone ) nach rechts zu kürzen :Und nur um die Dinge auszugleichen, werde ich auch den linken Trimmcode ( ideone ) einfügen :
quelle
str.substr(...).swap(str)
ist besser. Speichern Sie eine Aufgabe.basic_string& operator= (basic_string&& str) noexcept;
?Was Sie tun, ist gut und robust. Ich habe lange Zeit dieselbe Methode angewendet und muss noch eine schnellere Methode finden:
Durch die Angabe der zu beschneidenden Zeichen haben Sie die Flexibilität, Nicht-Leerzeichen zu beschneiden, und die Effizienz, nur die Zeichen zu beschneiden, die Sie beschneiden möchten.
quelle
trim
, dh machen Siertrim(ltrim(s, t), t)
es etwas effizienterEtwas spät zur Party, aber egal. Jetzt ist C ++ 11 da, wir haben Lambdas und Auto-Variablen. Meine Version, die auch Leerzeichen und leere Zeichenfolgen verarbeitet, lautet also:
Wir könnten einen Reverse-Iterator daraus machen
wsfront
und diesen als Beendigungsbedingung in der zweiten verwenden,find_if_not
aber das ist nur im Fall einer All-Whitespace-Zeichenfolge nützlich, und gcc 4.8 ist zumindest nicht klug genug, um auf den Typ des Reverse-Iterators zu schließen (std::string::const_reverse_iterator
) mitauto
. Ich weiß nicht, wie teuer das Erstellen eines Reverse-Iterators ist, also YMMV hier. Mit dieser Änderung sieht der Code folgendermaßen aus:quelle
std::isspace
:auto wsfront=std::find_if_not(s.begin(),s.end(),std::isspace);
candidate template ignored: couldn't infer template argument '_Predicate' find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred)
Versuchen Sie dies, es funktioniert für mich.
quelle
str.find_last_not_of(x)
Gibt die Position des ersten Zeichens ungleich x zurück. Es wird nur npos zurückgegeben, wenn keine Zeichen nicht mit x übereinstimmen. Wenn im Beispiel keine Suffix-Leerzeichen vorhanden sind, wird das Äquivalent von zurückgegebenstr.length() - 1
, was im Wesentlichen ergibt.str.erase((str.length() - 1) + 1).
Das heißt, es sei denn, ich irre mich schrecklich.std::string&
.Ich mag die Lösung von tzaman. Das einzige Problem dabei ist, dass eine Zeichenfolge, die nur Leerzeichen enthält, nicht abgeschnitten wird.
Um diesen Fehler zu korrigieren, fügen Sie zwischen den beiden Trimmerlinien ein str.clear () ein
quelle
ltrim
oderrtrim
so.std::stringstream
.http://ideone.com/nFVtEo
quelle
it
), und umgekehrt: Position des Zeichens, nach der nur noch Leerzeichen (rit
) vorhanden sind - danach wird eine neu erstellte Zeichenfolge == zurückgegeben eine Kopie des Teils der ursprünglichen Zeichenfolge - ein Teil, der auf diesen Iteratoren basiert ...Im Fall einer leeren Zeichenfolge geht Ihr Code davon aus, dass das Hinzufügen von 1 zu
string::npos
0string::npos
vom Typ iststring::size_type
, der ohne Vorzeichen ist. Sie verlassen sich also auf das Überlaufverhalten der Addition.quelle
1
zustd::string::npos
müssen geben0
nach demC++ Standard
. Es ist also eine gute Annahme, auf die man sich absolut verlassen kann.Von Cplusplus.com gehackt
Dies funktioniert auch für den Nullfall. :-)
quelle
rtrim
nichtltrim
In C ++ 17 können Sie basic_string_view :: remove_prefix und basic_string_view :: remove_suffix verwenden :
Eine schöne Alternative:
quelle
Meine Lösung basiert auf der Antwort von @Bill the Lizard .
Beachten Sie, dass diese Funktionen die leere Zeichenfolge zurückgeben, wenn die Eingabezeichenfolge nur Leerzeichen enthält.
quelle
Meine Antwort ist eine Verbesserung gegenüber der Top-Antwort für diesen Beitrag, bei der sowohl Steuerzeichen als auch Leerzeichen (0-32 und 127 in der ASCII-Tabelle ) gekürzt werden .
std::isgraph
Legt fest, ob ein Zeichen eine grafische Darstellung hat. Sie können dies verwenden, um Evans Antwort zu ändern und alle Zeichen zu entfernen, die keine grafische Darstellung von beiden Seiten einer Zeichenfolge haben. Das Ergebnis ist eine viel elegantere Lösung:Hinweis: Alternativ sollten Sie in der Lage sein, zu verwenden
std::iswgraph
wenn Sie Unterstützung für breite Zeichen benötigen. Sie müssen diesen Code jedoch auch bearbeiten, um diestd::wstring
Manipulation zu aktivieren. Dies habe ich nicht getestet (Informationen zurstd::basic_string
Option finden Sie auf der Referenzseite ). .quelle
Mit C ++ 11 kam auch ein regulärer Ausdruck Modul für , mit dem natürlich führende oder nachfolgende Leerzeichen abgeschnitten werden können.
Vielleicht so etwas:
quelle
Das benutze ich. Entfernen Sie einfach weiter Platz von vorne und machen Sie dasselbe von hinten, wenn noch etwas übrig ist.
quelle
quelle
Für das, was es wert ist, ist hier eine Trimmimplementierung mit Blick auf die Leistung. Es ist viel schneller als viele andere Trimmroutinen, die ich gesehen habe. Anstatt Iteratoren und std :: find zu verwenden, werden rohe c-Zeichenfolgen und -Indizes verwendet. Es optimiert die folgenden Sonderfälle: Zeichenfolge der Größe 0 (nichts tun), Zeichenfolge ohne Leerzeichen zum Trimmen (nichts tun), Zeichenfolge mit nur nachgestellten Leerzeichen zum Trimmen (Größe der Zeichenfolge ändern), Zeichenfolge, die vollständig Leerzeichen enthält (nur die Zeichenfolge löschen) . Und im schlimmsten Fall (Zeichenfolge mit führendem Leerzeichen) ist es am besten, eine effiziente Kopierkonstruktion durchzuführen, nur eine Kopie auszuführen und diese Kopie dann anstelle der ursprünglichen Zeichenfolge zu verschieben.
quelle
Eine elegante Art, es zu tun, kann so sein
Und die unterstützenden Funktionen werden implementiert als:
Und wenn Sie alle diese Voraussetzungen erfüllt haben, können Sie auch Folgendes schreiben:
quelle
Trim C ++ 11-Implementierung:
quelle
Ich denke, wenn Sie nach dem "besten Weg" zum Trimmen eines Strings fragen, würde ich sagen, dass eine gute Implementierung eine wäre, die:
Offensichtlich gibt es zu viele verschiedene Möglichkeiten, dies zu erreichen, und es hängt definitiv davon ab, was Sie tatsächlich benötigen. Die C-Standardbibliothek verfügt jedoch noch über einige sehr nützliche Funktionen in <string.h>, wie z. B. memchr. Es gibt einen Grund, warum C immer noch als die beste Sprache für IO angesehen wird - seine stdlib ist reine Effizienz.
quelle
Ich bin nicht sicher, ob Ihre Umgebung dieselbe ist, aber in meiner führt der Fall einer leeren Zeichenfolge dazu, dass das Programm abgebrochen wird. Ich würde diesen Löschaufruf entweder mit einem if (! S.empty ()) abschließen oder Boost wie bereits erwähnt verwenden.
quelle
Folgendes habe ich mir ausgedacht:
Durch die Stream-Extraktion werden Leerzeichen automatisch entfernt, sodass dies wie ein Zauber wirkt.
Ziemlich sauber und elegant, wenn ich es selbst sage. ;)
quelle
Beitrag meiner Lösung zum Lärm.
trim
Standardmäßig wird eine neue Zeichenfolge erstellt und die geänderte zurückgegeben, währendtrim_in_place
die an sie übergebene Zeichenfolge geändert wird . Dietrim
Funktion unterstützt die C ++ 11-Verschiebungssemantik.quelle
Dies kann in C ++ 11 durch Hinzufügen von
back()
und einfacher erfolgenpop_back()
.quelle
Hier ist meine Version:
quelle
Die oben genannten Methoden sind großartig, aber manchmal möchten Sie eine Kombination von Funktionen für das verwenden, was Ihre Routine als Leerzeichen betrachtet. In diesem Fall kann die Verwendung von Funktoren zum Kombinieren von Operationen unübersichtlich werden. Daher bevorzuge ich eine einfache Schleife, die ich für die Trimmung ändern kann. Hier ist eine leicht modifizierte Trimmfunktion, die aus der C-Version hier auf SO kopiert wurde. In diesem Beispiel schneide ich nicht alphanumerische Zeichen.
quelle
Hier ist eine einfache Implementierung. Für eine so einfache Operation sollten Sie wahrscheinlich keine speziellen Konstrukte verwenden. Die eingebaute Funktion isspace () kümmert sich um verschiedene Formen weißer Zeichen, daher sollten wir sie nutzen. Sie müssen auch Sonderfälle berücksichtigen, in denen die Zeichenfolge leer ist oder nur eine Reihe von Leerzeichen. Das Trimmen nach links oder rechts kann aus dem folgenden Code abgeleitet werden.
quelle
Hier ist eine leicht verständliche Lösung für Anfänger, die nicht
std::
überall schreiben und noch nicht mitconst
Korrektheit,iterator
s, STLsalgorithm
usw. vertraut sind.Ich hoffe es hilft...
quelle
Diese Version schneidet interne Leerzeichen und nicht alphanumerische Zeichen:
quelle
Noch eine andere Option - entfernt ein oder mehrere Zeichen von beiden Enden.
quelle