7
votes

Convertir une large chaîne de charme en minuscule en C ++

Comment convertir une chaîne WCHAR_T de majuscule en minuscule en C ++?

La chaîne contient un mélange de caractères japonais, chinois, allemands et grecs.

J'ai pensé à utiliser de la serviette ...

http://msdn.microsoft.com/ EN-US / Bibliothèque / 8h19T214% 28VS.80% 29.aspx

.. Mais la documentation dit que:

La conversion du cas du serviteur est spécifique à la locale. Seuls les caractères correspondants pour les paramètres régionaux actuels sont modifiés au cas où.

EDIT: Peut-être que je devrais décrire ce que je fais. Je reçois une requête de recherche Unicode d'un utilisateur. Il est à l'origine dans l'encodage UTF-8, mais je la convertissez en un widecharar (je me trompe peut-être sur le libellé). Mon débogueur (VS2008) montre correctement les personnages japonais, allemands, etc. dans la "montre rapide variable". Je dois passer par un autre ensemble de données dans Unicode et trouver des correspondances de la chaîne de recherche. Bien que ce ne soit pas un problème pour moi de faire lorsque la recherche est sensible à la casse, il est plus problématique de le faire étudier insensible. Mon approche (peut-être naïf) pour résoudre le problème serait de convertir toutes les données d'entrée et de produire des données de sortie en minuscules, puis de le comparer.


2 commentaires

Une autre approche serait d'utiliser des algorithmes de comparaison qui ignorent l'affaire. Et le cas n'est pas votre seul problème. Sans normaliser la chaîne, la diacritique par exemple peut être considérée comme partie de l'un ( é , õ ) ou plusieurs caractères individuels ( 'e , < code> ~ o ). Une bonne normalisation (NFC / NFD / NFKC / NFKD) avant la comparaison est essentielle dans votre situation.


Abel, veuillez le poster comme une réponse appropriée afin qu'elle puisse être perçue comme elle devrait être. C'est à peu près la seule réponse correcte dans cette situation ...


4 Réponses :


3
votes

Vous avez un mauvais problème à la main. Un local japonais ne vous aidera pas à convertir allemand et vice versa. Il y a des langues qui n'ont pas le concept de captalisation ( touppper et des amis seraient un non-op ici, je suppose). Alors, pouvez-vous rompre votre chaîne en morceaux individuels de mots de la même langue? Si vous pouvez alors, vous pouvez convertir les pièces et les corroborer.


6 commentaires

Les Japonais et les autres langues idéographiques d'Asie de l'Est sont des exemples de langues principalement sans majuscule.


Non seulement cela, mais les langues individuelles peuvent avoir Différentes opinions sur la manière dont une lettre particulière doit être supérieure / moindre. Il n'y a tout simplement pas d'algorithme unique pour le faire correctement sur une chaîne unicode aléatoire sans connaître la langue.


Bien que je suis d'accord avec cette évaluation, UNICODE inclut les propriétés majuscules / minuscules indépendantes locales, son utilisation décrite dans 3.13 "Opreations par défaut" , qui sont doivent être utilisées en l'absence de couture pour langues particulières , la norme dit donc.


Cela fait. Le problème est que c'est juste pour, disons, 99% de tous les cas, mais vous aurez 1% de mal. Qui peut ou non être un problème. En général, il suffit de l'utiliser pour des identifiants comme des identifiants dans le code et peut-être même des noms de fichiers.


@Pavel: Ce qui signifie que vous ne pouvez pas le faire correctement tout le temps, mais vous pouvez le faire de manière cohérente tout le temps. Je sais que la masse inférieure à 'I' à 'I' est tort en turc, mais si vous normalisez simplement la chaîne de comparaison plutôt que d'imprimer le résultat, cela peut fonctionner très bien.


@David: Cela pourrait ne pas fonctionner bien. Dites que vous avez du texte "diyarbakır" dans le document d'origine et l'utilisateur entré "diationarbakir" de la chaîne de recherche. Vous utilisez les règles de boîtier UNICODE par défaut pour minuscules les deux chaînes; Le premier devient "Diyarbakır", le deuxième "Diyarbakir". Et maintenant, ils ne correspondent pas, et ils devraient vraiment avoir, si le texte est turc.



10
votes

Si votre chaîne contient tous ces caractères, le code de code doit être basé sur unicode. Si implémenté correctement, Unicode (chapitre 4 ' propriétés de caractère ') définit les propriétés de caractère, y compris si le caractère est majuscule et la mappage minuscule, etc.

donné que le préambule, le Towlower () fonction de est l'outil correct à utiliser. Si cela ne fait pas le travail, vous avez un problème de QOI (qualité de mise en œuvre) à discuter avec votre fournisseur. Si vous trouvez le vendeur insensible, alors regardez les bibliothèques alternatives. Dans ce cas, vous pourriez envisager ICU (composants internationaux pour Unicode).


5 commentaires

Les mappages de cas Unicode, comme spécifié dans le document que vous avez lié à, sont toujours partiellement dépendants de la région. Citation: "Specialcasing.txt - contient des mappages de cas supplémentaires qui correspondent à plusieurs caractères, tels que" ß "à" SS ". Contient également des mappages dépendants du contexte, avec des drapeaux pour les distinguer des mappages normaux, ainsi que < I> Certains mappages dépendants de la locale . ". Donc, tolower ne peut pas éviter d'être spécifique à la locale.


@Pavel Ce processus s'appelle "normalisation des chaînes UNICODE", ce qui garantit que ß et ss est traité égal (en fonction du formulaire de normalisation choisi) et unicode contient la langue neutre Algorithmes pour cela, tout en ignorant le souhait de traitement des paramètres régionaux ou de l'application.


@Abel: la normalisation n'est pas une solution complète. Par exemple, dans certaines langues latines, les diacritiques disparaissent sur des lettres majusculées, dans d'autres langues, elles ne le font pas. Il n'y a aucun moyen de dire à moins que vous sachiez quelle langue le texte est écrit. Ensuite, bien sûr, il y a le problème infâme de Turkish Dotless "I" - vous voulez © en minuscule vers i et i à lowecase to ı pour turc, mais vous voulez i à minuscule to i pour tout autre Langue alphabet latin.


@Pavel: C'est une excellente élaboration, je suis tout à fait d'accord. Non, la normalisation n'est pas parfaite, c'est plus une méthode de force brute simpliste, mais cela aide dans un bon groupe de situations. Probablement bon moment dans la discussion pour inclure un lien vers l'algorithme de collation Unicode, qui en discute en totalité (va beaucoup plus en minuscule / majuscule): Unicode.org/reports/tr10 et la cartographie de l'affaire Unicode: UNICODE.ORG/REPORTS/TR21/TR21-5.HTML


@JonathanLeffler: L'ICU est intéressant, mais peut-être surkill. J'irais probablement pour traiter l'Unicodedata.txt [compiler aux pièces non pertinentes et filtrant des pièces non pertinentes].



1
votes

Cette réponse montre comment travailler avec des facettes pour travailler avec plusieurs locaux. Si cela se trouve sous Windows, vous pouvez envisager d'utiliser des fonctions d'API Win32, si vous pouvez travailler avec C ++. NET (géré C ++), vous pouvez utiliser le char.TObower et string.tObower Fonctions, qui sont conformes Unicode.


0 commentaires

0
votes

consultez _wcslwr_l dans ( MSDN ).

Vous devriez pouvoir exécuter la fonction sur l'entrée de chacun des locaux.


2 commentaires

"Vous devriez pouvoir exécuter la fonction sur l'entrée de chacun des locaux." - Que se passe-t-il si deux localités dans la carte du même personnage différemment?


Comme mentionné dans d'autres commentaires, vous devez connaître la langue de chaque partie de la chaîne afin d'éviter ces cas. Il n'y a vraiment pas de tour ça. Je suggère simplement une fonction différente à utiliser pour gérer plus facilement le problème en exécutant l'opération sur la locale actuelle.