2010-05-07 6 views
3
  • utilise-t-il setlocale()?
  • suppose-t-il utf-8 pour toutes les chaînes d'entrée dans un environnement local UTF-8?
  • Je comprends ce qu'est unicode et comment est-il lié à utf-8, mais comment peut-on se "convertir" en interne avec toutes ses chaînes? Comment convertit-il toutes les chaînes d'entrée en UTF-8?

Utilise-t-il une fonction de bibliothèque C?Comment exactement un programme convertit tout en UTF-8 en interne?

Les paramètres régionaux en cours doivent-ils être des paramètres régionaux UTF-8?

MISE À JOUR: Si des détails techniques spécifiques pouvaient être dans votre réponse, ce serait génial car c'est plus conforme à ce que je recherche. Je comprends déjà les raisons de l'utilisation de l'UTF-8 en interne et pourquoi il est beaucoup plus simple de gérer plusieurs environnements locaux.

MISE À JOUR: une réponse mentionated simplement utiliser iconv et/ou aux soins intensifs, cependant, comment ne strcmp() ainsi que toutes les autres routines savoir pour les comparer au format UTF-8 alors? Est-ce que setlocale() doit être exécuté? Ou n'est-ce pas important?

Répondre

5

Il est un peu difficile de dire par où commencer ici, car il y a beaucoup de suppositions en jeu.

Dans C comme nous le connaissons et l'aimons, il existe un type de données 'char'. Dans toutes les implémentations couramment utilisées, ce type de données contient un octet de 8 bits.

Dans le langage, contrairement à toutes les fonctions de bibliothèque que vous utilisez, ces éléments ne sont que des entiers à deux éléments. Ils n'ont aucune sémantique de «caractère». Dès que vous commencez à appeler des fonctions de la bibliothèque standard avec 'str' ou 'is' dans leurs noms (par exemple, strcmp, isalnum), vous avez affaire à la sémantique des caractères.

Les programmes C doivent faire face au désordre géant fait de la sémantique des caractères avant l'invention d'Unicode. Diverses organisations ont inventé un très grand nombre de normes d'encodage. Certains sont un caractère par octet. Certains sont plusieurs caractères par octet. Dans certains, il est toujours sûr de demander if (charvalue == 'a'). Dans d'autres, cela peut obtenir la mauvaise réponse en raison d'une séquence multi-octets.

Dans à peu près tous les environnements modernes, la sémantique de la bibliothèque standard est déterminée par les paramètres régionaux.

Où l'UTF-8 entre-t-il? Il y a longtemps, le Consortium Unicode a été fondé pour essayer de mettre de l'ordre dans tout ce chaos. Unicode définit une valeur de caractère (dans un espace de caractère de 32 bits) pour beaucoup, beaucoup, beaucoup de caractères. L'intention est de couvrir tous les caractères d'utilisation pratique. Si vous voulez que votre code fonctionne en anglais, en arabe, en chinois et en sumérien cunéiforme, vous voulez une sémantique de caractères Unicode, pas pour écrire du code qui esquive et tisse un codage de caractères différent. Sur le plan conceptuel, la façon la plus simple d'utiliser des caractères 32 bits (UTF-32) consiste à utiliser un seul élément par caractère logique. La plupart des gens ont décidé que cela n'était pas pratique. Notez que, dans les versions modernes de gcc, le type de données wchar_t est un caractère 32 bits --- mais Microsoft Visual Studio n'est pas d'accord, définissant ce type de données à 16 bits (UTF-16 ou UCS-2, en fonction de votre point de vue).

La plupart des programmes non Windows C sont beaucoup trop investis en caractères 8 bits pour être modifiés. Ainsi, la norme Unicode inclut UTF-8, une représentation du texte Unicode comme une séquence de 8 bits. En UTF-8, chaque caractère logique a une longueur comprise entre 1 et 4 octets. Les caractères de base ISO-646 ('ascii') se jouent eux-mêmes, les opérations simples sur des caractères simples fonctionnent comme prévu. Si votre environnement inclut des paramètres régionaux pour UTF-8, vous pouvez définir les paramètres régionaux sur un environnement local UTF-8 et toutes les fonctions standard de lib fonctionneront. Si votre environnement n'inclut pas les locales pour UTF-8, vous aurez besoin d'un module complémentaire, comme ICU ou ICONV.

Cette discussion entière est restée, jusqu'à présent, aux données se reposant dans des variables dans la mémoire. Vous devez également composer avec la lecture et l'écriture. Si vous appelez open(2) ou l'équivalent moral de Windows, vous obtiendrez les octets bruts du fichier. Si ceux-ci ne sont pas en UTF-8, vous devrez les convertir si vous voulez travailler en UTF-8.Si vous appelez fopen(3), la bibliothèque standard peut essayer de vous faire une faveur et effectuer une conversion entre son idée de l'encodage par défaut des fichiers et son idée de ce que vous voulez en mémoire. Si vous avez besoin, par exemple, d'exécuter un programme sur un système dans une langue grecque et de lire un fichier de chinois dans Big5, vous devrez faire attention aux options que vous passerez à ouvrir, ou vous voudrez peut-être l'éviter. Et vous aurez besoin d'ICONV ou ICU pour convertir vers et depuis UTF-8.

Votre question mentionne 'input strings'. Cela pourrait être un certain nombre de choses. Dans un environnement local UTF-8, argv sera UTF-8. Le descripteur de fichier 0 sera UTF-8. Si le shell ne s'exécute pas dans un environnement local UTF-8 et que vous appelez le setlocale dans un environnement local UTF-8, vous n'obtiendrez pas nécessairement les valeurs dans UTF-8 dans argv. Si vous connectez le contenu d'un fichier à un descripteur de fichier, vous obtiendrez tout ce qui se trouve dans le fichier, quel que soit son encodage.

+1

Les points de code UTF-8 sont compris entre 1 et 6 octets, et non entre 1 et 4, car chaque octet successif a un bit de moins. – Ioan

+0

@loan, plus maintenant. Représenter des paires de substitution comme deux séries de trois n'est plus acceptable. – bmargulies

+0

@bmargulies, Je ne sais pas ce que tu veux dire. Je pensais que la raison pour laquelle cela prenait 1-6 octets était parce que 8b + 7b + 6b + 5b + 4b + 3b = 33 bits pour contenir un point de code possible de 32 bits? – Ioan

1

Une chaîne est vraiment un concept abstrait. Mais à l'intérieur d'un ordinateur, toute chaîne aura une représentation concrète en nombre d'octets en utilisant un codage de caractères spécifique. Donc, "convertir tout en UTF-8 en interne" signifie qu'une application utilise UTF-8 pour toutes les chaînes en interne, a toute sa logique écrite pour fonctionner sur des chaînes UTF-8, et convertit chaque entrée externe de tout ce qui encode cette chaîne utilise pour UTF-8. Il peut ou non vous permettre de choisir quel encodage utiliser pour la sortie. Ceci est vraiment la manière la plus sensée d'écrire une application capable de gérer du texte dans différents codages, au moins si la logique interne peut fonctionner efficacement sur UTF-8 (c'est-à-dire ne nécessite pas d'accès aléatoire).

+0

Pouvez-vous donner plus de détails techniques? Je comprends les détails de haut niveau que vous m'avez déjà donnés. – dlamotte

2

Euh ... Je suppose que vous poser des questions sur des choses telles que libiconv ou ICU, mais ... ils sont juste des bibliothèques pour convertir les jeux de caractères ...

EDIT:

Vous ne pouvez pas utiliser les fonctions de gestion de chaîne C standard, car vous ne traitez pas de chaînes C standard. Les versions compatibles UTF-8 sont disponibles dans des bibliothèques telles que glib ou ICU.

+0

Je suppose que vous avez raison ... hein – dlamotte

+0

Bien sûr, vous pouvez utiliser les fonctions standard. L'un des charmes spéciaux de UTF-8 est que les fonctions comme strlen et strcmp fonctionnent correctement sur les cas simples. – bmargulies

+0

Et si vous supposez que chaque cas est un cas simple, vous allez bientôt rencontrer des bugs à gauche et à droite. –

0

si vous voulez comparer deux chaînes en C, ils ont tous deux être dans le même encodage. strcmp() est juste un memcmp() (ou une comparaison par octet) qui s'arrête à la valeur 0. Il n'y aura aucune conversion dans strcmp de C. Si vous devez faire face à différents encodages (CP850, UTF-8, Ansi, Windows, Mac), vous devez faire très attention à ce que vous comparez, sinon vous comparez des pommes avec des poires.

Les bibliothèques mentionnées ci-dessus ont une implémentation différente de strcmp(), qui connaît et gère l'encodage, l'écrou vous devez toujours connaître et fournir l'encodage par vous-même.

si vous traitez avec XML, vous pouvez utiliser libxml, qui code pour vous dans la représentation correcte (interne), selon l'encodage donné à travers l'en-tête xml.

tables de codage/caractères est l'un des plus mauvais concept en C, remontant aux anciens jours où les octets de caractères où 7 bits de long et le monde de l'ordinateur a eu lieu qu'aux États-Unis. (donc pas de trémas, accents, EURO-Sign, etc)

1

ICU utilise l'utf-16 en interne (ce qui est un bon format pour travailler en interne)), mais a des routines de commodité pour comparer utf-8. Vous lui indiquez les paramètres régionaux que vous souhaitez utiliser pour comparer, ou vous pouvez utiliser le paramètre UCA non pris en charge si vous spécifiez le paramètre "racine".

Questions connexes