Die Boost C++ Bibliotheken

API

Boost.Spirit bietet mit boost::spirit::qi::parse() und boost::spirit::qi::phrase_parse() zwei Funktionen an, um Formate zu parsen.

Beispiel 11.1. boost::spirit::qi::parse() in Aktion
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>

using namespace boost::spirit;

int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::parse(it, s.end(), ascii::digit);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

Beispiel 11.1 stellt die Funktion boost::spirit::qi::parse() vor. boost::spirit::qi::parse() erwartet zwei Iteratoren auf einen String, der geparst werden soll, sowie einen Parser. Im Beispiel wird als Parser boost::spirit::ascii::digit verwendet. Bei diesem Objekt handelt es sich um einen Parser, der von Boost.Spirit zur Verfügung gestellt wird. boost::spirit::ascii::digit zählt zu den Zeichenklassenparsern. Dies sind Parser, die Zeichen daraufhin überprüfen, ob sie zu einer bestimmten Klasse gehören. Mit boost::spirit::ascii::digit wird überprüft, ob ein Zeichen eine Ziffer zwischen 0 und 9 ist.

Im Beispiel werden Iteratoren auf einen String übergeben, der von der Standardeingabe gelesen wird. Beachten Sie, dass der Iterator auf den Anfang des Strings nicht direkt an boost::spirit::qi::parse() übergeben wird. Er wird in der Variablen it gespeichert, die dann an boost::spirit::qi::parse() übergeben wird. Der Grund ist, dass boost::spirit::qi::parse() den Iterator verändert. boost::spirit::qi::parse() gibt nicht nur ein Ergebnis vom Typ bool zurück, sondern setzt den Iterator unter Umständen neu.

Wenn Sie das Beispiel ausführen und eine Ziffer gefolgt von Enter eingeben, wird true ausgegeben. Geben Sie zwei Ziffern gefolgt von Enter ein, wird true und die zweite Ziffer ausgegeben. Geben Sie einen Buchstaben gefolgt von Enter ein, wird false und der Buchstabe ausgegeben.

Der im Beispiel 11.1 verwendete Parser boost::spirit::ascii::digit überprüft genau ein Zeichen darauf, ob es eine Ziffer ist. Ist das erste eingegebene Zeichen eine Ziffer, gibt boost::spirit::qi::parse() true zurück – andernfalls false. Der Rückgabewert von boost::spirit::qi::parse() gibt an, inwiefern ein Parser erfolgreich auf einen String angewandt werden konnte.

boost::spirit::qi::parse() gibt auch true zurück, wenn Sie mehrere Ziffern eingeben. Da der Parser boost::spirit::ascii::digit lediglich das erste eingegebene Zeichen überprüft, kann er auch in diesem Fall erfolgreich auf den String angewandt werden. Alle Zeichen ab dem zweiten werden vom Parser boost::spirit::ascii::digit jedoch ignoriert.

Um erkennen zu können, bis zu welcher Stelle im String Zeichen erfolgreich geparst wurden, verändert boost::spirit::qi::parse() den Iterator it. Nach einem Aufruf von boost::spirit::qi::parse() zeigt it auf das Zeichen nach dem letzten erfolgreich geparsten Zeichen. Geben Sie mehr als eine Ziffer ein, zeigt it auf die zweite eingegebene Ziffer. Geben Sie genaue eine Ziffer ein, ist it gleichbedeutend mit dem End-Iterator von s. Geben Sie genau einen Buchstaben ein, zeigt it auf den Buchstaben.

Beachten Sie, dass boost::spirit::qi::parse() Leerzeichen nicht ignoriert. Wenn Sie das obige Beispiel ausführen und ein Leerzeichen vor einer Ziffer eingeben, wird false ausgegeben. boost::spirit::qi::parse() überprüft das erste eingegebene Zeichen. Handelt es sich dabei um ein Leerzeichen, wird der Parser auf dieses angewandt. Möchten Sie Leerzeichen ignorieren, können Sie anstatt boost::spirit::qi::parse() die Funktion boost::spirit::qi::phrase_parse() aufrufen.

Beispiel 11.2. boost::spirit::qi::phrase_parse() in Aktion
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>

using namespace boost::spirit;

int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), ascii::digit, ascii::space);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

boost::spirit::qi::phrase_parse() funktioniert wie boost::spirit::qi::parse(), erwartet jedoch einen zusätzlichen Parameter. Dieser wird als Skipper bezeichnet. Der Skipper ist nichts anderes als ein Parser, der Zeichen liest, die ignoriert werden sollen. Im Beispiel 11.2 wird boost::spirit::ascii::space übergeben – ein Zeichenklassenparser zum Erkennen von Leerzeichen.

Der Skipper boost::spirit::ascii::space interpretiert Leerzeichen als Trennzeichen. Wenn Sie das Beispiel ausführen und ein Leerzeichen gefolgt von einer Ziffer eingeben, wird true ausgegeben. Im Gegensatz zum vorherigen Beispiel wird der Parser boost::spirit::ascii::digit nicht auf das Leerzeichen angewandt, sondern auf das erste Zeichen, das kein Leerzeichen ist.

Beachten Sie, dass im obigen Beispiel beliebig viele Leerzeichen ignoriert werden. boost::spirit::qi::phrase_parse() gibt auch dann true zurück, wenn Sie mehrere Leerzeichen gefolgt von einer Ziffer eingeben.

boost::spirit::qi::phrase_parse() verändert so wie boost::spirit::qi::parse() den als ersten Parameter übergebenen Iterator, so dass Sie feststellen können, bis zu welchem Zeichen der String erfolgreich geparst wurde. Im obigen Beispiel werden mögliche Leerzeichen nach einer erfolgreich geparsten Ziffer übersprungen. Wenn Sie eine Ziffer gefolgt von einem Leerzeichen gefolgt von einem Buchstaben eingeben, zeigt der Iterator direkt auf den Buchstaben. Möchten Sie, dass der Iterator auf das Leerzeichen nach der Ziffer zeigt, können Sie mit boost::spirit::qi::skip_flag::dont_postskip einen zusätzlichen Parameter an boost::spirit::qi::phrase_parse() übergeben.

Beispiel 11.3. phrase_parse() mit boost::spirit::qi::skip_flag::dont_postskip
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>

using namespace boost::spirit;

int main()
{
  std::string s;
  std::getline(std::cin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), ascii::digit, ascii::space,
    qi::skip_flag::dont_postskip);
  std::cout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::cout << std::string{it, s.end()} << '\n';
}

Im Beispiel 11.3 wird boost::spirit::qi::skip_flag::dont_postskip an boost::spirit::qi::phrase_parse() übergeben, um mögliche Leerzeichen nach einer erfolgreich geparsten Ziffer nicht zu überspringen. Wenn Sie eine Ziffer gefolgt von einem Leerzeichen gefolgt von einem Buchstaben eingeben, zeigt it nach dem Aufruf von boost::spirit::qi::phrase_parse() auf das Leerzeichen.

Boost.Spirit unterstützt neben boost::spirit::qi::skip_flag::dont_postskip lediglich das Flag boost::spirit::qi::skip_flag::postskip. boost::spirit::qi::skip_flag::postskip ist der Standardwert, der gilt, wenn Sie boost::spirit::qi::phrase_parse() wie im vorherigen Beispiel ohne explizite Angabe eines Flags aufrufen.

Beispiel 11.4. boost::spirit::qi::phrase_parse() mit Wide-Strings
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>

using namespace boost::spirit;

int main()
{
  std::wstring s;
  std::getline(std::wcin, s);
  auto it = s.begin();
  bool match = qi::phrase_parse(it, s.end(), ascii::digit, ascii::space,
    qi::skip_flag::dont_postskip);
  std::wcout << std::boolalpha << match << '\n';
  if (it != s.end())
    std::wcout << std::wstring{it, s.end()} << '\n';
}

Sie können sowohl boost::spirit::qi::parse() als auch boost::spirit::qi::phrase_parse() Iteratoren auf einen Wide-String übergeben. So funktioniert Beispiel 11.4 wie das vorherige.

Boost.Spirit unterstützt auch die mit C++11 in die Standardbibliothek aufgenommen String-Typen std::u16string und std::u32string.