Comment calculer le nombre de caractères dans une chaîne unicode en C
Permet de dire que j'ai une chaîne de caractères:
char theString[] = "你们好āa";
Étant donné que mon encodage est utf-8, cette chaîne est de 12 octets de long (trois caractères hanzi sont trois octets chacun, le caractère latin avec le macron est de deux octets, et le 'a' est un octet:
strlen(theString) == 12
Comment puis-je compter le nombre de caractères? Comment puis-je faire l'équivalent de subscripting de sorte que:
theString[3] == "好"
Comment puis-je tranche, de chat et de ces chaînes?
Vous devez vous connecter pour publier un commentaire.
Vous ne pouvez compter que les personnages qui ont les deux premiers bits sont pas mis à
10
(c'est à dire, tout moins que0x80
ou supérieure à0xbf
).C'est parce que tous les personnages, avec les deux premiers bits mis à
10
UTF-8 poursuite octets.Voir ici pour une description de l'encodage et de la façon dont
strlen
pouvez travailler sur une chaîne UTF-8.Pour trancher et découper des chaînes UTF-8, vous avez essentiellement de suivre les mêmes règles. N'importe quel octet de départ avec un
0
bits ou un11
de la séquence de le début de l'UTF-8 code point, tous les autres sont des caractères de continuité.Votre meilleur pari, si vous ne voulez pas utiliser une bibliothèque tierce, est tout simplement de fournir des fonctions le long des lignes de:
pour obtenir, respectivement:
sz
UTF-8 octets d'une chaîne.sz
UTF-8 octets d'une chaîne, en commençant àpos
.pos
.Ce sera un bon bloc de construction pour être capable de manipuler les chaînes de caractères suffisamment à vos fins.
Le plus simple est d'utiliser une bibliothèque comme ICU
\X
, rendant les choses plus faciles. Cela dit, il y a des morceaux de code C qui de tout faire pour eux-mêmes, commevim
— cependant, qui semble utiliser quelque chose de plus comme\PM\pM*
, et est également bloqué en travaillant uniquement sur les BMP. Soupir.Essayez ceci pour la taille:
Exemple d'exécution:
Noter que votre exemple est un arrêt par une erreur.
theString[2] == "好"
Selon votre notion de "caractère", cette question peut devenir plus ou moins impliqués.
Tout d'abord, vous devez transformer votre chaîne d'octets en une chaîne de caractères de l'unicode codepoints. Vous pouvez faire cela avec
iconv()
de soins intensifs, mais si c'est la seule chose que vous faites,iconv()
est beaucoup plus facile, et ça fait partie de la norme POSIX.Votre chaîne de caractères de l'unicode codepoints pourrait être quelque chose comme un null
uint32_t[]
, ou si vous avez C1x, un tableau dechar32_t
. La taille de ce tableau (c'est à dire son nombre d'éléments, pas sa taille en octets) est le nombre de codepoints (plus le terminator), et qui devrait vous donner un très bon début.Cependant, la notion de "caractère imprimable" est assez complexe, et l'on peut préférer à compter graphèmes plutôt que codepoints - par exemple, un
a
avec un accent^
peut être exprimé par deux unicode codepoints, ou comme un héritage codepointâ
- les deux sont valables, et les deux sont requis par le standard unicode pour être traités de manière égale. Il y a un processus appelé la "normalisation" qui transforme votre chaîne dans une certaine version, mais il y a beaucoup de graphèmes qui ne sont pas exprimables comme un seul codepoint, et en général il n'y a pas moyen de contourner une bonne bibliothèque qui comprend cela et compte graphèmes pour vous.Cela dit, c'est à vous de décider quelle est la complexité de vos scripts sont et comment fond que vous souhaitez traiter. Transformer en unicode codepoints est un must, tout au-delà qui est à votre discrétion.
N'hésitez pas à poser des questions sur les soins intensifs si vous décidez que vous en avez besoin, mais n'hésitez pas à explorer beaucoup plus simple
iconv()
premier.Dans le monde réel,
theString[3]=foo;
n'est pas une véritable opération. Pourquoi jamais vous voulez remplacer un caractère à une position particulière dans la chaîne de caractères avec un caractère différent? Il n'y a certainement pas de langage naturel-traitement de texte de la tâche pour laquelle cette opération est significative.Comptage de caractères est également peu susceptible d'être utile. Combien de caractères (pour votre idée de "caractère") sont là, dans le "á"? Comment à propos de "á"? Maintenant, comment au sujet de "གི"? Si vous avez besoin de cette information pour mettre en œuvre une sorte d'édition de texte, vous allez avoir à faire face à ces questions difficiles, ou tout simplement utiliser une bibliothèque existante/gui toolkit. Je recommanderais ce dernier, sauf si vous êtes un expert sur le monde des scripts et des langues et pensez que vous pouvez faire mieux.
Pour toutes autres fins,
strlen
vous dit exactement l'information qui est réellement utile: combien d'espace de stockage d'une chaîne de caractères. C'est ce qui est nécessaire pour la combinaison et la séparation des chaînes. Si tout ce que vous voulez faire est de combiner les chaînes ou les séparer à un délimiteur particulier,snprintf
(oustrcat
si vous insistez...) etstrstr
tout ce dont vous avez besoin.Si vous souhaitez effectuer de plus haut niveau en langage naturel-texte opérations, comme la capitalisation, de la ligne de rupture, etc. ou même de niveau supérieur, des opérations comme la pluralisation, le temps des changements, etc. ensuite, vous aurez besoin soit d'une bibliothèque comme unité de soins intensifs ou respectivement quelque chose de beaucoup plus haut niveau et linguistiquement capable (et spécifiques de la langue(s) vous travaillez).
Encore une fois, la plupart des programmes n'ont pas de toute utilisation de ce genre de chose, il suffit d'assembler et d'analyser le texte sans aucune considération pour le langage naturel.
Cela permettra de compter les caractères dans une Chaîne UTF-8... (qui se Trouve dans cet article: Encore plus rapide de caractères UTF-8 de comptage)
Cependant, je suis toujours perplexe sur le découpage et la concaténation?!?
En général, nous devrions utiliser un autre type de données de caractères unicode.
Par exemple, vous pouvez utiliser l'échelle de type de données char
Note du modificateur L qui indique que la chaîne est composée de larges caractères.
La longueur de la chaîne peut être calculée à l'aide de la
wcslen
fonction, qui se comporte commestrlen
.wchar_t
n'est pas nécessairement l'utilisation de l'UTF-32 (c'est à dire le 2 octets cas) rend cette solution portables...Une chose n'est pas clair dans les réponses ci-dessus est pourquoi il n'est pas simple. Chaque caractère est codé d'une manière ou d'une autre - il n'a pas à être en UTF-8, par exemple - et chaque personnage peut avoir plusieurs codages, avec différentes façons de gérer la combinaison des accents, etc. Les règles sont vraiment complexes, et varient selon le codage (par exemple, utf-8 vs utf-16).
Cette question a d'énormes problèmes de sécurité, il est impératif que cela soit fait correctement. Utilisez un système d'exploitation fourni par la bibliothèque ou le bien-connu de la troisième partie de la bibliothèque pour manipuler des chaînes unicode; ne pas rouler votre propre.
Je n'ai de mise en œuvre similaire années en arrière. Mais je n'ai pas le code avec moi.
Pour chacun des caractères unicode, le premier octet indique le nombre d'octets de la suivre pour la construction d'un caractère unicode. Basé sur le premier octet, vous pouvez déterminer la longueur de chaque caractère unicode.
Je pense que c'est une bonne UTF8 bibliothèque.
entrez description du lien ici
Une séquence de points de code constituent une seule syllabe /lettre /personnage dans beaucoup d'autres Ouest-Européen des langues (par exemple: toutes les langues Indo-aryennes)
Ainsi, lorsque vous avez le comptage de la durée OU de trouver la sous-chaîne (il y a certainement des cas d'utilisation de trouver les sous-chaînes - disons de la lecture d'un bourreau de jeu), vous avez besoin à l'avance, syllabe par syllabe , et non pas par le point de code par le code de point.
Ainsi, la définition du personnage/de la syllabe et où vous casser la chaîne en segments de syllabes" dépend de la nature de la langue que vous travaillez avec.
Par exemple, la structure des syllabes dans de nombreuses langues Indo-aryennes (Hindi, Telugu, Kannada, Malayalam, le Népalais, le Tamoul, le Punjabi, etc.) peut-être l'un des suivants
Vous avez besoin pour analyser la chaîne et regarder pour ces modèles de briser la chaîne et de trouver les sous-chaînes.
Je ne pense pas que c'est possible d'avoir une méthode usage général qui peut magiquement briser les chaînes de la au-dessus de la mode pour toute chaîne unicode (ou d'une séquence de points de code) - que le modèle qui fonctionne pour une langue ne peut pas être applicable pour une autre lettre;
Je pense qu'il y a peut-être certaines méthodes /bibliothèques qui peut prendre un peu de définition des paramètres de configuration que l'entrée de briser les chaînes unicode en une telle syllabe morceaux. Ne sais pas si! Apprécier si l'on peut partager comment ils ont résolu ce problème en utilisant tout disponibles dans le commerce ou les méthodes de source libre.