Die Boost C++ Bibliotheken

Kapitel 10. Boost.Tokenizer

Die Bibliothek Boost.Tokenizer ermöglicht es, über Teilausdrücke in einem String zu iterieren. Dabei werden bestimmte Zeichen im String als Trennzeichen interpretiert.

Beispiel 10.1. Über Teilausdrücke eines Strings mit boost::tokenizer iterieren
#include <boost/tokenizer.hpp>
#include <string>
#include <iostream>

int main()
{
  typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
  std::string s = "Boost C++ Libraries";
  tokenizer tok{s};
  for (tokenizer::iterator it = tok.begin(); it != tok.end(); ++it)
    std::cout << *it << '\n';
}

Boost.Tokenizer definiert eine Klasse boost::tokenizer in der Headerdatei boost/tokenizer.hpp. Bei dieser Klasse handelt es sich um ein Template: Als Template-Parameter muss eine Klasse angegeben werden, die zusammenhängende Ausdrücke identifiziert. So wird im Beispiel 10.1 die Klasse boost::char_separator verwendet, die Leerzeichen und Interpunktionszeichen als Trennzeichen interpretiert.

Ein Tokenizer muss mit einem String vom Typ std::string initialisiert werden. Über die Methoden begin() und end() kann der Tokenizer wie ein Container behandelt werden. Über den Iterator wird auf Teilausdrücke des Strings zugegriffen, mit dem der Tokenizer initialisiert wurde. Wie Teilausdrücke gefunden werden, hängt von der Klasse ab, die als Template-Parameter angegeben ist.

Obiges Beispiel gibt Boost, C, +, + und Libraries aus, weil boost::char_separator standardmäßig Leerzeichen und Interpunktionszeichen als Trennzeichen interpretiert. Um diese Zeichen identifiziereren zu können, greift boost::char_separator auf die Funktionen std::isspace() und std::ispunct() zu. Die beiden Pluszeichen werden ausgegeben, weil Boost.Tokenizer zwischen Trennzeichen unterscheidet, die unterdrückt und ausgegeben werden sollen: Standardmäßig werden Leerzeichen unterdrückt und Interpunktionszeichen ausgegeben.

Beispiel 10.2. boost::char_separator initialisieren, um die Iteration anzupassen
#include <boost/tokenizer.hpp>
#include <string>
#include <iostream>

int main()
{
  typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
  std::string s = "Boost C++ Libraries";
  boost::char_separator<char> sep{" "};
  tokenizer tok{s, sep};
  for (const auto &t : tok)
    std::cout << t << '\n';
}

Für den Fall, dass Interpunktionszeichen nicht als Trennzeichen interpretiert werden sollen, können Sie ein Objekt vom Typ boost::char_separator entsprechend initialisieren und als Parameter an den Tokenizer übergeben.

Der Konstruktor von boost::char_separator erwartet drei Parameter, von denen lediglich der erste angegeben werden muss. Der erste Parameter beschreibt Trennzeichen, die unterdrückt werden sollen. Für Beispiel 10.2 bedeutet das wie zuvor, dass Leerzeichen Trennzeichen sind.

Der zweite Parameter beschreibt Trennzeichen, die ausgegeben werden sollen. Wird der zweite Parameter so wie im Beispiel 10.2 nicht angegeben, ist er leer. Es gibt demnach keine Trennzeichen, die ausgegeben werden sollen. Wird Beispiel 10.2 ausgeführt, wird Boost, C++ und Libraries ausgegeben.

Beispiel 10.3. Mit boost::char_separator das Standardverhalten simulieren
#include <boost/tokenizer.hpp>
#include <string>
#include <iostream>

int main()
{
  typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
  std::string s = "Boost C++ Libraries";
  boost::char_separator<char> sep{" ", "+"};
  tokenizer tok{s, sep};
  for (const auto &t : tok)
    std::cout << t << '\n';
}

Wenn Sie so wie im Beispiel 10.3 als zweiten Parameter ein Pluszeichen angeben, erhalten Sie das Standardverhalten aus dem ersten Beispiel in diesem Kapitel.

Der dritte Parameter beschreibt, ob leere Teilausdrücke ausgegeben werden sollen oder nicht. Wenn zwei Trennzeichen direkt hintereinander stehen, ist der dazwischenliegende Teilausdruck leer. Standardmäßig werden diese leeren Teilausdrücke nicht ausgegeben. Sie können jedoch über den dritten Parameter das Verhalten von boost::char_separator ändern.

Beispiel 10.4. boost::char_separator initialisieren, um leere Teilausdrücke mitauszugeben
#include <boost/tokenizer.hpp>
#include <string>
#include <iostream>

int main()
{
  typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
  std::string s = "Boost C++ Libraries";
  boost::char_separator<char> sep{" ", "+", boost::keep_empty_tokens};
  tokenizer tok{s, sep};
  for (const auto &t : tok)
    std::cout << t << '\n';
}

Wenn Sie Beispiel 10.4 ausführen, werden zusätzlich zwei leere Teilausdrücke ausgegeben. So befindet sich ein leerer Teilausdruck zwischen den beiden Pluszeichen und zwischen dem zweiten Pluszeichen und dem folgenden Leerzeichen.

Beispiel 10.5. Boost.Tokenizer mit Wide-Strings
#include <boost/tokenizer.hpp>
#include <string>
#include <iostream>

int main()
{
  typedef boost::tokenizer<boost::char_separator<wchar_t>,
    std::wstring::const_iterator, std::wstring> tokenizer;
  std::wstring s = L"Boost C++ Libraries";
  boost::char_separator<wchar_t> sep{L" "};
  tokenizer tok{s, sep};
  for (const auto &t : tok)
    std::wcout << t << '\n';
}

Im Beispiel 10.5 wird über einen String vom Typ std::wstring iteriert. Damit der Tokenizer einen String von diesem Typ als Parameter akzeptiert, ist es notwendig, zusätzliche Template-Parameter anzugeben. Auch der Klasse boost::char_separator muss in diesem Fall als Template-Parameter wchar_t übergeben werden.

Neben boost::char_separator bietet Boost.Tokenizer zwei weitere Klassen an, um Teilausdrücke zu identifizieren.

Beispiel 10.6. boost::escaped_list_separator für das CSV-Format
#include <boost/tokenizer.hpp>
#include <string>
#include <iostream>

int main()
{
  typedef boost::tokenizer<boost::escaped_list_separator<char>> tokenizer;
  std::string s = "Boost,\"C++ Libraries\"";
  tokenizer tok{s};
  for (const auto &t : tok)
    std::cout << t << '\n';
}

Die Klasse boost::escaped_list_separator kann verwendet werden, um mehrere Werte zu lesen, die durch Komma getrennt sind. Dieses Format wird als CSV bezeichnet – eine Abkürzung für comma separated values. Dabei werden von boost::escaped_list_separator auch Anführungszeichen und Escape-Sequenzen berücksichtigt. So gibt Beispiel 10.6 Boost und C++ Libraries aus.

Eine weitere von Boost.Tokenizer zur Verfügung gestellte Klasse ist boost::offset_separator. Diese Klasse muss instanziiert werden. Das entsprechende Objekt muss als zweiter Parameter an den Konstruktor von boost::tokenizer übergeben werden.

Beispiel 10.7. Mit boost::offset_separator über Teilausdrücke iterieren
#include <boost/tokenizer.hpp>
#include <string>
#include <iostream>

int main()
{
  typedef boost::tokenizer<boost::offset_separator> tokenizer;
  std::string s = "Boost_C++_Libraries";
  int offsets[] = {5, 5, 9};
  boost::offset_separator sep{offsets, offsets + 3};
  tokenizer tok{s, sep};
  for (const auto &t : tok)
    std::cout << t << '\n';
}

Mit boost::offset_separator werden die Stellen im String beschrieben, an denen Teilausdrücke enden. So gibt Beispiel 10.7 an, dass der erste Teilausdruck nach 5 Zeichen, der zweite nach weiteren 5 Zeichen und der dritte nach weiteren 6 Zeichen endet. Das Beispiel gibt Boost, _C++_ und Libraries aus.