Zeichenbehandlung

Zur portablen Klassifikation und Umwandlung von einzelnen Zeichen zwischen verschiedenen Darstellungen gibt es std::ctype.

Video

Quellcode

#include <locale>
#include <iostream>

int main()
{
    std::locale de_loc("de_DE.UTF-8");
    auto &de = std::use_facet<std::ctype<wchar_t>>(de_loc);
    
    std::locale en_loc("en_US.UTF-8");
    auto &en = std::use_facet<std::ctype<wchar_t>>(en_loc);

    auto &cl = std::use_facet<std::ctype<wchar_t>>(std::locale::classic());

    std::wcout << de.is(std::ctype_base::alpha, L'Ü') << std::endl;
    std::wcout << en.is(std::ctype_base::alpha, L'Ü') << std::endl;
    std::wcout << cl.is(std::ctype_base::alpha, L'Ü') << std::endl;
    
    std::string str { "Man kann auch char * auch wcout ausgeben." };
    wchar_t ostr[256] = {};
    
    de.widen(str.data(), str.data()+str.size(), ostr);
    std::wcout << ostr << std::endl;
    
    en.widen(str.data(), str.data()+str.size(), ostr);
    std::wcout << ostr << std::endl;
}

Erklärung

Zur Verarbeitung einzelner Zeichen unter Beachtung der gewählten Locale stellt C++ die Facette std::ctype bereit. Mit ihr kann man Zeichen auf ihre Eigenschaften prüfen (numerisch, Buchstabe, etc.) oder zwischen einzelnen Darstellungen wie char und wchar_t konvertieren.

Die Prüfung auf die Art des Zeichens geschieht durch std::ctype::is. Die Methode erwartet zwei Parameter: einen Satz von Flags, welche mit dem Zeichen abgeglichen werden sollen und das zu prüfende Zeichen. Der Standard definiert eine Reihe von Flags (bspw. für die Prüfung, ob ein Zeichen ein Buchstabe oder eine Zahl ist), die sich mit | verknüpfen lassen, um auf mehrere Klassen parallel zu prüfen. Wenn ein Zeichen eine der Klassen besitzt, so liefert die Funktion true zurück. Im Beispiel oben tut sie das für das Zeichen 'Ü' in der deutschen und (überraschenderweise) amerikanischen Locale. Die Standard-C-Locale liefert false

Ein weiterer Dienst, den std::ctype bereitstellt, ist die Umwandlung von Zeichen zwischen char und wchar_t (oder einem anderen Zeichentyp, wobei nur die beiden unterstützt werden müssen und bspw. die Standardbibliothek von GCC 4.7 auch keine weiteren Spezialisierungen mitbringt). Abhängig vom Zeichentyp kann diese Umwandlung nämlich nicht durch einen einfachen Cast zwischen den Zeichentypen geschehen, sondern ist etwas komplexer. Zur Umwandlung in den breiteren Typ stellt std::ctype die Methode widen() zur Verfügung. Diese nimmt entweder einen Buchstaben und liefert seine Darstellung im breiteren Zeichentyp oder sie erwartet drei Pointer auf Anfang und Ende eines char-Arrays als Eingabe und auf den Anfang eine Arrays vom gewählten Zeichentyp als Ausgabe und wandelt das komplette Array um. Dabei ist nicht genau spezifiziert, wie die Methode mit Zeichen umgeht, die sie nicht umwandeln kann. GCC 4.7 lässt sie einfach weg.