2010-08-27 7 views
2

Comment comptez-vous unicode caractères dans un fichier UTF-8 en C++? Peut-être si quelqu'un serait si gentil de me montrer une méthode "autonome", ou alternativement, un court exemple en utilisant http://icu-project.org/index.html. Une erreur importante est que j'ai besoin de construire des comptes de chaque caractère, donc ce n'est pas comme si je comptais le nombre total de caractères, mais le nombre d'occurrences d'un ensemble de caractères.compter les caractères Unicode en C++

+3

Voulez-vous compter les caractères ou codepoints? Basé sur votre édition, il semble aussi que vous vous souciez de la normalisation. Toutes les réponses (au moment de l'écriture) concernent le comptage des points de code. –

+0

@Logan: Qu'entendez-vous par "normalisation"? –

+2

Logan a raison. Lien: http://unicode.org/reports/tr15/ –

Répondre

9

en UTF-8, un octet non leader a toujours les deux bits supérieurs mis à 10, donc simplement ignorer tous ces octets. Si cela ne vous dérange pas, vous pouvez faire plus que cela (pour passer au-dessus des octets non-premiers basés sur le modèle binaire d'un octet principal) mais en réalité, il est peu probable de faire beaucoup de différence vous serez généralement proche de la bande passante mémoire de toute façon). Edit: À l'origine, j'ai mal lu votre question en demandant simplement comment compter la longueur d'une chaîne de caractères encodés en UTF-8. Si vous voulez compter les fréquences de caractères, vous voulez probablement convert those to UTF-32/UCS-4, alors vous aurez besoin d'une sorte de matrice clairsemée pour compter les fréquences. La partie la plus difficile concerne le comptage des points de code en fonction des caractères. Par exemple, considérons le caractère "À" - la "lettre majuscule latine A avec tombe". Il y a au moins deux manières différentes de produire ce personnage. Vous pouvez utiliser le code de code U + 00C0, qui encode le tout dans un seul code, ou vous pouvez utiliser le code de code U + 0041 (lettre majuscule latine A) suivi du code de code U + 0300 (Combining grave accent). Normaliser (par rapport à Unicode) signifie transformer tous ces caractères dans la même forme. Vous pouvez soit les combiner en un seul point de code, soit les séparer en points de code distincts. Pour vos besoins, il est probablement plus facile de les combiner en un seul point de code autant que possible. Ecrire ceci par vous-même n'est probablement pas très pratique - j'utiliserais le normalizer API du projet ICU.

+0

+1 pour la normalisation Unicode. Il y a aussi un api win32 pour ça. –

4

Si vous savez que la séquence UTF-8 est bien formée, c'est assez facile. Comptez chaque octet qui commence par un bit zéro ou deux bits de un. La première condition va chatcher chaque point de code qui est représenté par un seul octet, la seconde va attraper le premier octet de chaque séquence multi-octets.

while (*p != 0) 
{ 
    if ((*p & 0x80) == 0 || (*p & 0xc0) == 0xc0) 
     ++count; 
    ++p; 
} 

Ou bien comme l'a remarqué dans les commentaires, vous pouvez simplement ignorer chaque octet qui est une continuation:

while (*p != 0) 
{ 
    if ((*p & 0xc0) != 0x80) 
     ++count; 
    ++p; 
} 

Ou si vous voulez être super intelligent et en faire un 2-liner: Le Wikipedia page for UTF-8 montre clairement les modèles.

+0

Il devrait être (* p & 0xc0)! = 0x80 – jean

+0

@jean l'un fonctionne de la même manière. –

+0

== a plus de priorité que & – jean

0

Je ne considère pas cela comme une question centrée sur la langue. Le format UTF-8 est assez simple. le décoder à partir d'un fichier ne devrait contenir que quelques lignes de code dans n'importe quelle langue.

open file 
until eof 
    if file.readchar & 0xC0 != 0x80 
     increment count 
close file 
+0

(file.readchar & 0xC0)! = 0x80. au moins en C,! = a une plus grande priorité que & – jean

3

Je sais, il est en retard pour ce fil, mais il pourrait aider

avec des trucs de soins intensifs, je l'ai fait comme ceci:

string TheString = "blabla" ; 
UnicodeString uStr = UnicodeString::fromUTF8(theString.c_str()) ; 
cout << "length = " << uStr.length() << endl ; 
Questions connexes