Wie schneide ich einen std::string?

Lesezeit: 6 Minuten

Wie schneide ich einen stdstring
Milan Babuskov

Ich verwende derzeit den folgenden Code, um alle rechts zu trimmen 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 es einige Endfälle gibt, in denen es fehlschlagen könnte?

Natürlich sind Antworten mit eleganten Alternativen und auch Linkstrimm-Lösung willkommen.

Wie schneide ich einen stdstring
Leon Timmermans

Verwenden String-Algorithmen von Boost wäre am einfachsten:

#include <boost/algorithm/string.hpp>

std::string str("hello world! ");
boost::trim_right(str);

str ist jetzt "hello world!". Es gibt auch trim_left und trimdie beide Seiten beschneidet.


Wenn Sie hinzufügen _copy Suffix an einen der oben genannten Funktionsnamen, z trim_copygibt die Funktion eine getrimmte Kopie der Zeichenfolge zurück, anstatt sie durch eine Referenz zu ändern.

Wenn Sie hinzufügen _if Suffix an einen der oben genannten Funktionsnamen, z trim_copy_ifkönnen Sie alle Zeichen kürzen, die Ihrem benutzerdefinierten Prädikat entsprechen, im Gegensatz zu nur Leerzeichen.

  • Was verwendet Boost, um festzustellen, ob es sich bei einem Zeichen um Leerzeichen handelt?

    – Tom

    7. Dezember 2008 um 21:22 Uhr

  • Es hängt vom Gebietsschema ab. Mein Standardgebietsschema (VS2005, en) bedeutet, dass Tabulatoren, Leerzeichen, Wagenrückläufe, Zeilenumbrüche, vertikale Tabulatoren und Seitenvorschübe gekürzt werden.

    – Matty T

    26. Januar 2009 um 13:11 Uhr

  • Ich benutze schon viel Boost, #include <boost/format.hpp> #include <boost/tokenizer.hpp> #include <boost/lexical_cast.hpp> war aber besorgt über das Aufblähen des Codes beim Hinzufügen <boost/algorithm/string.hpp> wenn es schon welche gibt std::string::erase basierte Alternativen. Ich freue mich, beim Vergleich von MinSizeRel-Builds vor und nach dem Hinzufügen berichten zu können, dass die Trimmung von Boost meine Codegröße überhaupt nicht erhöht hat (muss schon irgendwo dafür bezahlen) und mein Code ist nicht mit ein paar weiteren Funktionen überladen.

    – Rian Sanderson

    25. Juli 2011 um 5:36 Uhr


  • @MattyT: Welche Referenz verwenden Sie für diese Liste (bestimmen, ob ein Zeichen Leerzeichen ist)?

    – Faheem Mitha

    30. Dezember 2011 um 4:04 Uhr

  • beantwortet nicht wirklich die Frage, die nach std::string fragt (nicht nach boost oder einer anderen Bibliothek …)

    – hfrmobil

    4. November 2019 um 14:20 Uhr

  • Wenn Sie basic_string und template auf dem CharT verwenden, können Sie dies für alle Strings tun, verwenden Sie einfach eine Template-Variable für die Leerzeichen, so dass Sie sie wie ws verwenden. Technisch gesehen könnten Sie es an diesem Punkt für c ++ 20 vorbereiten und es auch mit constexpr markieren, da dies Inline impliziert

    – Gestrandet

    2. Dezember 2019 um 1:09 Uhr

  • @Beached In der Tat. Es ist jedoch etwas kompliziert, hier eine Antwort einzugeben. Ich habe dafür Template-Funktionen geschrieben und es ist sicherlich ziemlich kompliziert. Ich habe schon viele verschiedene Ansätze ausprobiert und bin mir immer noch nicht sicher, welcher der beste ist.

    – Galik

    2. Dezember 2019 um 1:18 Uhr

1647223212 700 Wie schneide ich einen stdstring
Bill die Eidechse

Verwenden Sie den folgenden Code, um (nachgestellte) Leerzeichen und Tabulatorzeichen rechts abzuschneiden std::strings (Idee):

// trim trailing spaces
size_t endpos = str.find_last_not_of(" \t");
size_t startpos = str.find_first_not_of(" \t");
if( std::string::npos != endpos )
{
    str = str.substr( 0, endpos+1 );
    str = str.substr( startpos );
}
else {
    str.erase(std::remove(std::begin(str), std::end(str), ' '), std::end(str));
}

Und nur um die Dinge auszugleichen, füge ich auch den linken Trimmcode hinzu (Idee):

// trim leading spaces
size_t startpos = str.find_first_not_of(" \t");
if( string::npos != startpos )
{
    str = str.substr( startpos );
}

  • Dies erkennt keine anderen Formen von Leerzeichen … Newline, Line Feed, Carriage Return im Besonderen.

    – Tom

    7. Dezember 2008 um 21:23 Uhr

  • Rechts. Sie müssen es für den Leerraum anpassen, den Sie trimmen möchten. Meine spezielle Anwendung erwartete nur Leerzeichen und Tabulatoren, aber Sie können \n\r hinzufügen, um die anderen abzufangen.

    – Bill die Eidechse

    8. Dezember 2008 um 0:20 Uhr

  • str.substr(...).swap(str) ist besser. Speichern Sie eine Aufgabe.

    – updogliu

    30. August 2012 um 8:55 Uhr


  • @updogliu Wird die Zugzuweisung nicht verwendet basic_string& operator= (basic_string&& str) noexcept; ?

    – Nürettin

    8. Oktober 2013 um 8:47 Uhr


  • Diese Antwort ändert keine Zeichenfolgen, die ALLE Leerzeichen sind. Was ein Fehlschlag ist.

    – Tom Andersen

    9. April 2014 um 22:19 Uhr

Etwas spät zur Party, aber egal. Jetzt ist C++11 da, wir haben Lambdas und Auto-Variablen. Meine Version, die auch nur Leerzeichen und leere Zeichenfolgen verarbeitet, ist also:

#include <cctype>
#include <string>
#include <algorithm>

inline std::string trim(const std::string &s)
{
   auto wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
   auto wsback=std::find_if_not(s.rbegin(),s.rend(),[](int c){return std::isspace(c);}).base();
   return (wsback<=wsfront ? std::string() : std::string(wsfront,wsback));
}

Wir könnten daraus einen umgekehrten Iterator machen wsfront und verwenden Sie dies als Beendigungsbedingung in der zweiten find_if_not aber das ist nur nützlich im Fall eines reinen Whitespace-Strings, und gcc 4.8 ist zumindest nicht schlau genug, um den Typ des Reverse-Iterators abzuleiten (std::string::const_reverse_iterator) mit auto. Ich weiß nicht, wie teuer der Bau eines Reverse-Iterators ist, also YMMV hier. Mit dieser Änderung sieht der Code so aus:

inline std::string trim(const std::string &s)
{
   auto  wsfront=std::find_if_not(s.begin(),s.end(),[](int c){return std::isspace(c);});
   return std::string(wsfront,std::find_if_not(s.rbegin(),std::string::const_reverse_iterator(wsfront),[](int c){return std::isspace(c);}).base());
}

  • Dies erkennt keine anderen Formen von Leerzeichen … Newline, Line Feed, Carriage Return im Besonderen.

    – Tom

    7. Dezember 2008 um 21:23 Uhr

  • Rechts. Sie müssen es für den Leerraum anpassen, den Sie trimmen möchten. Meine spezielle Anwendung erwartete nur Leerzeichen und Tabulatoren, aber Sie können \n\r hinzufügen, um die anderen abzufangen.

    – Bill die Eidechse

    8. Dezember 2008 um 0:20 Uhr

  • str.substr(...).swap(str) ist besser. Speichern Sie eine Aufgabe.

    – updogliu

    30. August 2012 um 8:55 Uhr


  • @updogliu Wird die Zugzuweisung nicht verwendet basic_string& operator= (basic_string&& str) noexcept; ?

    – Nürettin

    8. Oktober 2013 um 8:47 Uhr


  • Diese Antwort ändert keine Zeichenfolgen, die ALLE Leerzeichen sind. Was ein Fehlschlag ist.

    – Tom Andersen

    9. April 2014 um 22:19 Uhr

1647223213 50 Wie schneide ich einen stdstring
Jerome Adofo

Versuchen Sie dies, es funktioniert für mich.

inline std::string trim(std::string& str)
{
    str.erase(str.find_last_not_of(' ')+1);         //suffixing spaces
    str.erase(0, str.find_first_not_of(' '));       //prefixing spaces
    return str;
}

  • @rgove Bitte erklären. str.find_last_not_of(x) gibt die Position des ersten Zeichens ungleich x zurück. Es gibt nur npos zurück, wenn keine Zeichen nicht mit x übereinstimmen. Wenn im Beispiel keine Leerzeichen angehängt werden, wird das Äquivalent von zurückgegeben str.length() - 1im Wesentlichen nachgebend str.erase((str.length() - 1) + 1). Das heißt, es sei denn, ich irre mich gewaltig.

    – Travis

    30. Oktober 2013 um 14:46 Uhr


  • Dies sollte std::string& zurückgeben, um zu vermeiden, dass der Kopierkonstruktor unnötig aufgerufen wird.

    – heksesang

    17. Oktober 2014 um 10:49 Uhr

  • Ich bin verwirrt, warum dies eine Kopie zurückgibt, nachdem der Rückgabeparameter geändert wurde?

    – Galik

    18. Juni 2015 um 0:51 Uhr

  • @MiloDC Meine Verwirrung ist, warum ich eine Kopie zurücksende anstatt eine Referenz. Eine Rückkehr erscheint mir sinnvoller std::string&.

    – Galik

    21. Dezember 2017 um 2:16 Uhr

  • Wenn Sie die Reihenfolge ändern (entfernen Sie zuerst nachgestellte Leerzeichen und dann vorangestellte Leerzeichen), ist dies effizienter.

    – CITBL

    7. Januar 2019 um 18:05 Uhr


999640cookie-checkWie schneide ich einen std::string?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy