Je veux écrire un programme en C ++ qui devrait fonctionner sur UNIX et Windows. Ce programme devrait pouvoir utiliser les deux: les environnements Unicode et non Unicode. Son comportement ne doit dépendre que sur les paramètres de l'environnement. P>
Une des fonctionnalités intéressantes que je veux avoir, consiste à manipuler les noms de fichiers à lire des répertoires. Ceux-ci peuvent être unicode ... ou non. P>
Quel est le moyen le plus simple d'atteindre cela? p>
6 Réponses :
Vous devez choisir quel ONUICODE codant pour utiliser E.G UTF-8, ISO-8859-1 etc. Ensuite, vous devez en tenir compte dans votre C ++ dans toute votre manipulation de chaîne. Par exemple. Jetez un coup d'œil à w_char et wstring. Dans un environnement non unicode, je suppose que vous voulez dire que les variables d'entrée seront uniquement ASCII? p>
Oui, seul Ascii dans Non Unicode. Le problème avec deux versions du programme est que je dois fournir les deux et décider qui courir. Je préférerais avoir un programme et il suffit de l'exécuter.
@Simon: ASCII et UTF-8 sont compatibles à l'envers. Donc, tous les caractères ASCII sont également des caractères UTF-8 (aucun changement requis). Mais Remarque ASCII n'est que 0-127. OnCce Vous obtenez au-dessus de 127 ans, alors vous parlez de ISO-8859- * qui définit comment les codes 128-255 sont définis.
@Simon: Ce que vous pourriez faire, utilise des tableaux de caractères dans votre programme pour les chaînes. Toutes les entrées seraient converties en UTF-8 (octet par octet). Les caractères ASCII qui sont <127 resteraient les mêmes, tandis que le reste serait converti en fonction du schéma. Ce que vous avez à faire si vous allouez suffisamment d'espace dans la matrice pour le UTF-8. Un tableau de caractères est un éventail d'octets simples mais dans UTF-8, il serait de 2,3 ou 4 octets par caractère
Le meilleur moyen que j'ai vu est d'avoir et ainsi de suite. Vous utiliseriez ensuite des chaînes comme Typedef code> S et de très peu de macros définies en fonction de la compilation conditionnelle. Par exemple: s ("foo") code> et mystringa (s ("foo")); code>. J'ai montré deux façons de créer un type de chaîne. Soit devrait fonctionner. P> p>
Vous avez votre Typedef code> et #define code> syntaxe mélangée.
Ceci est une solution sensible. Une chose que je ferais en outre consiste à laisser la macro et les noms de type de Windows dominent; Ie TCHAR code> au lieu de mychar code>, _unicode code> au lieu de unicode code> et texte code> au lieu de s code>.
TCHAR code> est très spécifique à Windows. Bien sûr, vous pourrait i> le définir sur UNIX, mais ce n'est pas vraiment utile, sauf si (1) Vous avez une bibliothèque surchargée avec Char code> et WCHAR_T CODE> VERSIONS de tout, et (2) vous vous souciez de construire les deux versions.
@Daniel: Sauf que ces noms avec des soulignements principaux suivis de lettres majuscules appartiennent à la mise en œuvre. Cela signifie que _unicode et _T () sont techniquement sortis. Et merci pour la modification; Je ne sais pas ce que je pensais.
@ DAN04: La question initiale consistait à pouvoir basculer facilement entre ASCII et UNICODE sur Windows et Linux. Cela implique que les bibliothèques sont disponibles, ou du moins que la bonne sera disponible sur l'UNIX spécifique étant ciblée.
@David: ou cela pourrait être une hypothèse faite par un programmeur Windows utilisé pour disposer des fonctions "ANSI" et "Unicode" sans se rendre compte que d'autres plates-formes ne l'ont pas.
Vous devez décider comment vous représentez le texte en interne.
Cela devrait être constant, peu importe ce que vous choisissez d'autre. P>
Ensuite, chaque fois que vous lisez une entrée, vous devez transmettre le format d'entrée dans le format interne. Ensuite, du format interne au format de sortie sur la sortie. Si vous utilisez le même format interne et externe, cela devient une opération d'identité. P>
utf-8 est idéal pour le stockage et la transmission car il se compresse bien.
Mais je n'aime pas cela comme une représentation interne car il a une longueur variable. P>
utf-16: était censé être le sauveur de toute l'humanité.
Mais a été rapidement superflué par UTF-32 P>
utf-32: fixe avec. Donc grand pour la représentation interne et la manipulation.
Facile à convertir / de UTF-8.
Très volumineux (chaque personnage prend 4 octets). P>
La plupart des systèmes d'exploitation ont déjà été convertis en une représentation de chaîne UTF ou se dirigent de cette façon. Ainsi, en utilisant un format onld obsolet en interne, comme ISO-8859, des moyens simplement que les appels vers le système d'exploitation entraîneront des travaux supplémentaires car la chaîne est convertie en / depuis UTF. En conséquence, cela semble être une perte de temps (pour moi). P>
Remarque rapide: UTF16 et UTF32 sont soumis à des problèmes d'endansion. UTF8 et UTF16 rendent difficile de connaître le nombre de points Unicode ... mais le nombre de points étant différent du nombre de graphèmes, ce n'est pas vraiment important.
L'identifiant local de "" (chaîne vide) spécifie une locale par défaut spécifique à la mise en œuvre. Donc, si vous définissez le paramètre local global sur Ceci a quelques limitations majeures sur Windows, où MSVC ne prouve aucun STD :: Locale avec le codage UTF-8. Et Mac OS X ne fournissent pas de STD :: locale autre que la locale "C" de culture neutre. p>
En pratique, il est courant de normaliser sur l'UTF-8 encodé STD :: String partout interne à votre application. Ensuite, dans ces em> les cas spécifiques em> où vous devez interagir avec le système d'exploitation, effectuez la conversion de code si nécessaire. Par exemple, vous utiliserez un Const Char * codé avec UTF-8 pour définir un nom de fichier sur UNIX, mais un WCHAR * codé avec UTF-16 pour définir un nom de fichier sous Windows. P>
UTF-8 est un jeu de caractères interne largement recommandé pour les applications destinées à être portable. UTF-16 a les mêmes problèmes de codage de largeur variable que UTF-8, plus utilise plus d'espace pour de nombreuses langues. L'UTF-16 ajoute également un problème d'octroi d'octets et a relativement peu de support sur UNIX. UTF-32 est le codage le plus simple pour fonctionner, mais il utilise également le plus d'espace et n'a pas de support natif sur Windows. P> std :: locale ("") code> alors vous allez, en théorie, obtenez une locale par défaut initialisée en fonction des paramètres locaux de l'environnement. Ceci est à peu près autant d'aide que la norme C ++ vous donne. P>
Je veux écrire un programme en C ++ que devrait fonctionner sur UNIX et Windows. P> blockQuote>
Tout d'abord, assurez-vous de comprendre la différence entre la manière dont UNIX prend en charge Unicode et comment Windows prend en charge Unicode. P>
Dans les journées pré-unicode, les deux plates-formes étaient similaires dans ce que chaque paramètre local avait ses propres codages de caractères préférés. Les chaînes étaient des matrices de
char code>. Unchar code> = un caractère, sauf dans quelques locaux d'Asie orientale qui utilisaient des codages à deux octets (qui étaient maladroits à manipuler en raison d'être non synchronisants). P>Mais ils ont approché unicode de deux manières différentes. P>
Windows NT a adopté Unicode dans les premiers jours où Unicode était destiné à être un codage de caractères 16 bits à largeur fixe. Microsoft a écrit une version entièrement nouvelle de l'API Windows à l'aide de caractères 16 bits (
wchar_t code>) au lieu de 8 bits caractères. Pour la compatibilité à l'envers, ils ont conservé l'ancienne API "ANSI" autour et défini une tonne de macros afin que vous puissiez appeler la version "ANSI" ou "UNICODE" selon que_unicode code> a été défini. p>Dans le monde UNIX (spécifiquement, Plan 9 de Bell Labs), les développeurs ont décidé qu'il serait plus facile de développer la prise en charge du caractère multi-octets d'Asie de l'Est de Unix pour gérer des caractères de 3 octets et créé le codage maintenant appelé UTF- 8 Ces dernières années, les systèmes de type UNIX ont rendu UTF-8 le codage par défaut pour la plupart des locaux. P>
Windows théoriquement pourrait em> développer leur support ANSI pour inclure UTF-8, mais Ils n'ont toujours pas , en raison d'hypothèses codées durement sur la taille maximale d'un caractère. Donc, sous Windows, vous êtes bloqué par une API OS qui ne prend pas en charge UF-8 et une bibliothèque d'exécution C ++ qui ne prend pas en charge UTF-8. P>
Le résultat de ceci est que: p>
utf-8 est le codage le plus facile à travailler avec Unix. strong> li> utf-16 est le codage le plus facile à travailler avec Windows. strong> li> ul> Cela crée autant de complications pour le code multiplate-forme que cela sonne. Il est plus facile si vous venez de choisir un codage unicode codant fort> et tenez-y. P>
Quel codage devrait-il être? h2>
voir UF-8 ou UTF -16 ou UTF-32 ou UCS-2 p>
en résumé: p>
- UTF-8 vous permet de conserver l'hypothèse d'unités de code 8 bits. Li>
- UTF-32 vous permet de conserver l'hypothèse de caractères à largeur fixe. LI>
- uf-16 suce , mais c'est toujours autour de Windows et Java. Li> ul>
wchar_t h3>
est le type standard "de caractère large" C ++. Mais son codage n'est pas normalisé: il est UTF-16 sur Windows et UTF-32 sur UNIX. Sauf sur ces plates-formes qui utilisent dépendant des paramètres régionaux em> wchar_t code> codingings comme un héritage de la programmation de l'Est asiatique. P>
Si vous souhaitez utiliser UTF-32, utilisez un
uint32_t code> ou équivalent TypeDEF pour stocker des caractères. Ou utilisezwchar_t code> si__ stdc_iso_10646 __ code> est défini etuint32_t code>. P>.La nouvelle standard C ++ aura
char16_t code> etchar32_t code>, ce qui permettra d'effacer la confusion sur la manière de représenter UF-16 et UTF-32. P>TCHAR H3>
est un Windows Typedef pour
wchar_t code> (supposé être utf-16) lorsque_unicode code> est défini etchar code> (supposé être "ANSI ") autrement. Il a été conçu pour traiter l'API Windows surchargé mentionné ci-dessus. P>dans Mon avis ,
TCHAR code> suce . Il combine les inconvénients de la dépendante de la plate-forme code> Char code> avec les inconvénients du dépendant de la plate-formewchar_t code>. Évitez-le. P>la considération la plus importante h3>
Les codages de caractères concernent l'échange d'informations. C'est ce que le "II" signifie en ASCII. Votre programme n'existe pas dans un vide. Vous devez lire et écrire des fichiers, qui sont plus susceptibles d'être codés dans UTF-8 que dans UTF-16. P>
D'autre part, vous pouvez travailler avec des bibliothèques utilisant des caractères UTF-16 (ou plus rarement, UTF-32). Ceci est particulièrement vrai sur Windows. P>
Ma recommandation est de Utiliser le formulaire de codage qui minimise la quantité de conversion que vous devez faire. strong> p>
Ce programme devrait pouvoir utiliser Les deux: l'Unicode et non Unicode environnements p> blockQuote>
Il serait beaucoup mieux de faire fonctionner votre programme entièrement dans Unicode en interne et ne gérera que des codages hérités pour la lecture de données héritées (ou l'écrire, mais seul em> s'il est explicitement demandé à.) P >
UTF-16 est également le format interne de la chaîne native de MacOS X et iOS (API de cacao). Pas seulement Windows et Java. Unix est l'intrus, en fait.
Une note importante: le «caractère large» Windows API fonctionne avec UCS-2, pas UTF-16.
Il y a au moins certains contextes dans lesquels des paires de substitution sont supportées. msdn.microsoft.com/en-us/Library/ DD374069% 28VS.85% 29.aspx
@Daniel. Windows API fonctionne avec UTF-16 (y compris les substituts) au moins depuis XP.
@Daniel: de Michael Kaplan lui-même: blogs.msdn. COM / B / MICHKAP / Archive / 2005/05/11 / 416552.aspx . Également en MSDN: msdn.microsoft.com/en-us /Library/ddd374069(vs.85).aspx
Personnellement, j'irais une route différente. P>
Quel que soit le format que vous choisissez, il devrait accueillir UNICODE, c'est une donnée. Cependant, vous n'avez certainement pas à vous sentir limité à l'utilisation d'un codage existant. P>
Un codage spécifique est censé communiquer facilement, mais depuis que UNIX par défaut sur UTF-8 et Windows à UTF-16, il est impossible d'avoir un encodage universel. Par conséquent, je suggérerais simplement d'utiliser votre propre représentation interne et d'appliquer une conversion appropriée en fonction du système d'exploitation que vous ciblez. Ceci étant baissé par une interface commune aux fonctions dont vous avez besoin et une mise en œuvre par système d'exploitation / codage. P>
Notez également que vous devriez pouvoir modifier le codage / décodage à la volée, quelle que soit la plate-forme que vous vous trouvez (par exemple, vous pourrez peut-être utiliser UTF-32 sur UNIX pour un fichier spécifique), une autre raison non utiliser un codage donné. p>
Pour résumer le montant: p>
ICU code> est génial li>
- Si vous le mettez en place vous-même et que vous souhaitez être un peu "standard", utilisez UTF-32 (4 octets par point) li>
- Si vous êtes serré en mémoire, 21 bits (<3 octets) sont suffisants pour encoder tous les points existants li>
ul>
La conversion peut sembler "intensive informatique" mais: p>
- Vous pouvez le faire en siste-sage li>
- C'est beaucoup plus rapide que d'I / O Li>
ul>
My 2 cts, comme on dit :) p>
Qu'entendez-vous par «à la fois les environnements Unicode et non Unicode»?
Le moyen le plus simple serait d'éviter tout traitement du texte. Quel est votre programme à faire?
@Nemanja: Je veux dire qu'il ne devrait y avoir qu'un seul programme, quel comportement devrait changer en fonction des paramètres de paramètres régionaux de l'environnement, si les paramètres sont UNICODE, le programme doit alors se comporter correctement à l'aide des chaînes UNICODE, si les paramètres sont non unicode (par exemple, ISO -8859-1), alors le programme devrait fonctionner normalement, sans aucune modification et besoin de recompilation.
@CHARDLES: L'une des fonctionnalités intéressantes que je veux avoir est de manipuler les noms de fichiers à lire des répertoires. Ceux-ci peuvent être unicode ... ou non.
Eh bien, vous devez mettre cela dans votre question, ce sont des informations assez critiques nécessaires pour fournir une réponse utile.