Verarbeitet UTF-8-Zeichen in C aus einer Textdatei

8

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:

%Vor%

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.

    
Ams 14.11.2014, 12:34
quelle

4 Antworten

10

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.

    
Jens Gustedt 14.11.2014 13:31
quelle
4

Sie können Ihre eigene utf-8 Dekodierungs-Lesefunktion erstellen.

Siehe die Formatbeschreibung in Ссылка

Dieser Code ist nicht sehr schön und robust. Aber es ist die Skizze dessen, was ich dachte ...

%Vor%     
V-X 14.11.2014 13:02
quelle
2

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:

%Vor%

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.

    
didierc 14.11.2014 13:21
quelle
1

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 :

finden %Vor%     
Coconop 14.11.2014 13:20
quelle

Tags und Links