Ich muss UTF-8-Zeichen aus einer Textdatei lesen und sie verarbeiten.
zum Beispiel, um die Häufigkeit des Auftretens eines bestimmten Zeichens zu berechnen. Gewöhnliche Charaktere sind in Ordnung. Das Problem tritt bei Zeichen wie ü
oder ğ
auf.
Das folgende ist mein Code, um zu prüfen, ob ein bestimmtes Zeichen auftritt, das den ASCII-Code des eingehenden Zeichens vergleicht:
SOME_NUMBER
ist was ich für diese Charaktere nicht herausfinden kann. Tatsächlich drucken diese Zeichen 5 verschiedene Zahlen aus, wenn sie versuchen, sie als Dezimalzahl zu drucken.
während zum Beispiel für das Zeichen 'a'
würde ich tun als: if(c == 97){ frequency++; }
, da der ASCII-Code von 'a'
ist 97
.
Gibt es trotzdem, dass ich diese Sonderzeichen in C identifizieren konnte?
P.S. Das Arbeiten mit normalem Zeichen (nicht wchar_t
) erzeugt das gleiche Problem, aber dieses Mal druckt das Drucken des dezimalen Äquivalents des ankommenden Zeichens 5 verschiedene NEGATIVE Zahlen für diese speziellen Zeichen. Problem steht.
Eine moderne C-Plattform sollte alles bieten, was Sie für eine solche Aufgabe benötigen.
Als erstes müssen Sie sicher sein, dass Ihr Programm unter einem Gebietsschema läuft, das mit utf8 umgehen kann. Ihre Umgebung sollte bereits darauf eingestellt sein, das einzige, was Sie in Ihrem Code tun müssen, ist
%Vor% wechselt vom Gebietsschema "C"
in Ihre native Umgebung.
Dann können Sie Strings wie üblich mit fgets
lesen, z. Um Vergleiche für Zeichen mit Akzenten zu erstellen, müssen Sie eine solche Zeichenfolge in eine breite Zeichenfolge ( mbsrtowcs
) konvertieren, wie Sie bereits erwähnt haben. Die Codierung von solchen breiten Zeichen ist Implementierung definiert, aber Sie müssen diese Codierung nicht kennen, um Prüfungen durchzuführen.
Gewöhnlich funktioniert sowas wie L'ä'
perfekt, solange die Plattform, auf der Sie kompilieren und wo Sie sie ausführen, nicht komplett vermasselt ist. Wenn Sie Codes benötigen, die Sie nicht einmal auf der Tastatur eingeben können, können Sie die L'\uXXXX'
-Notation von C11 verwenden, wie didierc in seiner Antwort erwähnt. ( 'L'\uXXXX'
ist für die "Basic" -Zeichen, wenn Sie etwas wirklich seltsames haben, würden Sie L'\UXXXXXXXX'
verwenden, ein Großbuchstabe U mit 8 Hex-Ziffern)
Wie gesagt, die Codierung für breite Zeichen ist Implementierung definiert, aber gute Chancen sind, dass es entweder utf-16 oder utf-32 ist, die Sie mit sizeof(wchar_t)
und dem vordefinierten Makro __STDC_ISO_10646__
überprüfen können. Selbst wenn Ihre Plattform nur utf-16 unterstützt (was 2-Wort- "Zeichen" haben kann), sollte der von Ihnen beschriebene Anwendungsfall keine Probleme verursachen, da alle Ihre Zeichen mit dem L'\uXXXX'
-Formular codiert werden können.
Wenn Sie in Ihren Code Wide-Character-Literale einfügen müssen, können Sie das mit folgender Schreibweise tun:
%Vor% Aber ich glaube, dass Sie das nicht brauchen sollten, wenn Sie die Häufigkeitsstatistik der Charaktere beibehalten wollen. Mit dem wchar_t
-Typ können Sie einfach Werte wie alle anderen ganzzahligen Typen vergleichen:
Mit diesem Vergleichsoperator und den Funktionen zum Extrahieren von wchar_t
aus Ihrem Datenstrom sollten Sie in der Lage sein, eine assoziative Tabelle von wchar_t
bis unsigned int
nur mit Ihren Eingabezeichen zu erstellen (C Hashtable-Implementierungen sind im Web vorhanden) .
Vielleicht ist ein wichtiger Punkt hier, dass breite Zeichen und utf8 Zeichen verschiedene Typen sind: Die Funktion fgetwc
ergibt einen Wert von win_t
- was ein integraler Typ ist% engobing wchar_t
(selbst von Größe 16 oder 32bits) , während utf8 Zeichen von 1 bis zu 4 Bytes (also 8 bis 32 Bits) in einer einfachen char *
belegen können. Da Sie wchar_t
direkt erhalten, müssen Sie sich eigentlich keine Gedanken über die utf8-Codierung machen.
Dies ist ein Vorschlag für eine Lösung, die keine großen Zeichen enthält:
Aus Wikipedia: Entwurf von UTF-8-Sequenzen mit mehreren Bytes
Die Leitung "1" des 1. Bytes gibt die Anzahl der folgenden Bytes an "10" am Anfang eines Bytes signalisiert ein Fortsetzungsbyte "0" als 1. Byte signalisiert eine Einzelbyte-Sequenz
Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
Daher müssen Sie zuerst wissen, ob Sie in einer Multi-Byte-Sequenz positioniert sind, indem Sie Folgendes testen:
%Vor% Dann müssen Sie das Byte akkumulieren, bis die Sequenz abgeschlossen ist (Anzahl 1
zählen, um zu wissen, wie viele Iterationen Sie benötigen) und schließlich erhalten Sie Ihr eindeutiges Unicode-Zeichen und können eine Häufigkeit zuordnen.
Beachten Sie, dass die string.h
API mit der UTF-8-Multibyte-Sequenz funktioniert. Zum Beispiel können Sie die Vorkommen von ü
(0xC3 0xBC) in einer Zeichenkette str
: