namespace cpp

C++ lernen, kennen, anwenden

Benutzer-Werkzeuge

Webseiten-Werkzeuge


howto:split_string

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

howto:split_string [2017-01-29 15:58] (aktuell)
Zeile 1: Zeile 1:
 +====== Text mit Trennfolgen zergliedern ======
 +> // Teach a man to fish and you feed him for a lifetime. //
 +> // Unless he doesn'​t like sushi -- then you also have to teach him to cook. //
 +>> --- http://​www.stackoverflow.com/​questions/​1581839/​whats-the-mechanism-of-sizeof-in-c-c
 +===== Aufgabe =====
 +Eine Textzeichenkette ist in eine Folge von Teilen zu zerlegen, ​
 +zwischen denen jeweils eine feststehende Zeichenfolge zu finden ist.
 +Aus
 +  "1, 2, 3, 4, 5" ​   ​
 +werden mit der Trennzeichenfolge ", " die 5 Teilketten
 +  "​1",​ "​2",​ "​3",​ "​4",​ "​5"​.
 +Die gewünschte Funktion ''​split(text,​ separator)''​ nimmt ein Leerzeichen als Standardtrenner.  ​
 +===== Ein Ansatz in C++98 =====
 +<code cpp split.cpp>​
 +#include <​string>​
 +#include <​vector>​
 +
 +std::​vector<​std::​string> ​
 +split(const std::​string&​ input, const std::​string&​ separator = " ")
 +{
 +  std::​vector<​std::​string>​ result;
 +  std::​string::​size_type position, start = 0;
 +
 +  while (std::​string::​npos != (position = input.find(separator,​ start)))
 +  {
 +    result.push_back(input.substr(start,​ position-start));​
 +    start = position + separator.size();​
 +  }
 +
 +  result.push_back(input.substr(start));​
 +  return result;
 +}
 +</​code>​
 +Eine [[http://​stackoverflow.com/​questions/​236129/​split-a-string-in-c|Anzahl weiterer Lösungen]] findet sich auf Stackoverflow.
 +Für einzelne Separatorzeichen aus einer Liste vgl. http://​rosettacode.org/​wiki/​Tokenize_a_string#​C.2B.2B .
 +
 +===== Leichtgewichtiger in C++17 =====
 +Das Kopieren von Zeichenketten ist aufwendig. ​
 +Mit [[kennen:​include:​string_view|std::​string_view]] wird jeweils nur ein Zeiger auf den Anfang und die Länge gespeichert.
 +Voraussetzung ist, dass die zu zerlegende Teilzettenkette mindestens solange existiert, wie per ''​string_view''​ darauf zugegriffen wird:
 +<code cpp split_sv.cpp>​
 +#include <​string_view>​ // C++17
 +#include <​vector>​
 +
 +auto split(std::​string_view input, std::​string_view separator = " ")
 +{
 +  std::​vector<​std::​string_view>​ result;
 +  std::​string_view::​size_type position, start = 0;
 +
 +  while (std::​string_view::​npos != (position = input.find(separator,​ start)))
 +  {
 +    result.push_back(input.substr(start,​ position-start));​
 +    start = position + separator.size();​
 +  }
 +
 +  result.push_back(input.substr(start));​
 +  return result;
 +}
 +</​code>​
 +Hier wird eine ganze Zeichenkette als Trenner erwartet.
 +In diesem Beispiel werden die Zeichenfolgen ", " ​
 +der Eingabe ''​1,​ 2, 3, 4, 5''​ als Trenner akzeptiert,
 +ein einzelnes Komma jedoch nicht:
 +<code cpp>
 +#include <​iostream>​
 +
 +int main()
 +{
 +  std::string line;
 +  while (std::​getline(std::​cin,​ line))
 +  {
 +    for (auto part : split(line, ", ")) // C++11
 +    {
 +      std::cout << "​\'"​ << part << "​\'​\n";​
 +    }
 +  }
 +  return 0;
 +}
 +</​code>​
 +
 +===== Reguläre Ausdrücke als Trenner =====
 +[[kennen:​include:​regex|Reguläre Ausdrücke]] geben mehr Möglichkeiten zur Beschreibung des Trenners. ​
 +Hier eine C++17-Variante mit ''​string_view'':​
 +<code cpp split_regex_sv.cpp>​
 +#include <​iostream>​
 +#include <​regex>​
 +#include <​string_view>​
 +
 +// adapted from: http://​stackoverflow.com/​a/​28142357/​831725
 +
 +auto split(std::​string_view input, std::​string_view separator = "​\\s+"​) ​
 +{
 +    std::​vector<​std::​string_view>​ result;
 +    std::regex rex(separator.begin(),​ separator.end());​
 +    std::​cregex_token_iterator iter(input.begin(),​ input.end(),​ rex, -1);
 +    std::​cregex_token_iterator end;
 +                             // -1 : get stuff not matched by regex
 +    for (; iter != end; ++iter)  ​
 +    {
 +        std::​string_view::​size_type numchars = iter->​second - iter->​first; ​
 +        result.push_back({iter->​first,​ numchars});
 +    }
 +    return result;
 +}
 +
 +int main()
 +{
 +    for (auto e : split("​eins ​  zwei drei    "​)) ​ // Whitespaces als Trenner
 +    {
 +        std::cout << e << '​\n';​
 +    }
 +
 +    for (auto e : split("​vier|fuenf:​sechs,​sieben",​ "​[|:,​]"​)) ​
 +    {  ​
 +        std::cout << e << '​\n';​
 +    }
 +}
 +</​code> ​
  
howto/split_string.txt · Zuletzt geändert: 2017-01-29 15:58 (Externe Bearbeitung)