Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

caractères et UTF8.

8 réponses
Avatar
moi-meme
Il y a quelques temps j'ai fait un bout de C qui traite des chaînes de
caractères.

Marche bien merci.

Mais je suis passé à Debian Etch. Là dedans tout est en UTF8. C'est la cata
complète.
Google n'a pas été mon ami. Je lui ai sans doute mal parlé.

N'étant sans doute pas le premier y a t'il une bonne petite librairie pour
régler le problème ?
Comparer des caractères, donner la longueur d'une chaîne etc.

Enfin tous les trucs basiques.

A défaut de librairie, je suis preneur d'un lien me donnant des tuyaux.

Sinon il ne me reste plus qu'à faire des scripts avec des conversions
UFT8-ISO mais là je suis HS et honteux en plus.

Merci

C Hiebel

8 réponses

Avatar
Jean-Marc Bourguet
moi-meme writes:

Il y a quelques temps j'ai fait un bout de C qui traite des chaînes de
caractères.

Marche bien merci.

Mais je suis passé à Debian Etch. Là dedans tout est en UTF8. C'est la cata
complète.
Google n'a pas été mon ami. Je lui ai sans doute mal parlé.

N'étant sans doute pas le premier y a t'il une bonne petite librairie pour
régler le problème ?
Comparer des caractères, donner la longueur d'une chaîne etc.

Enfin tous les trucs basiques.

A défaut de librairie, je suis preneur d'un lien me donnant des tuyaux.

Sinon il ne me reste plus qu'à faire des scripts avec des conversions
UFT8-ISO mais là je suis HS et honteux en plus.


Je suis passé par là il y a quelques temps. Pour essayer de voir ce que
garantissent les normes, voir ,
et les discussions qui ont suivi.
J'étais dans un contexte C++, mais c'est un domaine où ce que dit la norme
C est à prendre en considération, et dont elle est plus ou moins traitée
(entre autres dans ).

Je suis toujours preneur de plus d'informations.

A+

--
Jean-Marc
FAQ de fclc: http://www.isty-info.uvsq.fr/~rumeau/fclc
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Antoine Leca
En news:47682b3c$0$32415$,
« moi-meme » va escriure:

Déjà et pour commencer sur les chapeaux de roues, utf8 est plutôt mal vu sur
Usenet, en particulier fr.* !

Il y a quelques temps j'ai fait un bout de C qui traite des chaînes de
caractères.

Marche bien merci.


Oui ? Ce qui veut dire ? Marche OK avec ÿ et char signé, char 16 bits, et ce
genre de tests idiots ? Pareil avec les caractères japonais ?

Parce que sinon, il faudrait préciser dans quelle mesure ton « bout de C
marche bien » ...


Mais je suis passé à Debian Etch. Là dedans tout est en UTF8. C'est
la cata complète.


Là aussi, un peu de précision pourrait nous éclairer.
Une catastrophe, pour moi c'est les serveurs en rade, ou absence de courant
électrique (je n'habite pas en France) ; et elle n'est complète que si en
plus on est lundi matin, je n'ai pas pris mon café, _et_ mon boss a
justement besoin d'envoyer un courier urgent pour un appel d'offres avant 10
heures.
En es-tu là ?
Alors peut-être que revenir à [nom du système précédent]...OK j'arrête


N'étant sans doute pas le premier y a t'il une bonne petite librairie
pour régler le problème ?


La manière standard de faire est d'utiliser des wchar_t pour représenter les
caractères (à distinguer des bytes).
Il y a plein de choses dans la bibliothèque standard :
- mbtowc et compagnie, et aussi mbrtowc et compagnie, une variante
probablement identique dans ton cas
- fgetwc, fputwc, fwprintf etc. pour les entrées-sorties
- wcs*() qui remplace les fonctions en str*()

Évidemment, si tu as écrit des versions personnelles de manipulations de
chaînes de caractères, il faut les convertir en wchar_t. En général c'est
trivial (dans la plupart des cas c'est une recompilation avec des trucs du
préprocesseur pour changer les noms, équivalent à faire recherche/remplace
sur le source), mais parfois les algorithmes doivent être retouchés ; parmi
les choses qui ne marchent pas, il y a les opérations utilisant des indices
de type caractère, comme par exemple une table qui convertirait un unsigned
char en un indicateur majuscule/minuscule/chiffre/fin_de_ligne.


Il y a aussi ICU, mais c'est probablement comme tuer une mouche avec une
ogive nucléaire.


Et d'abord, quel est exactement le problème ?

Comparer des caractères, donner la longueur d'une chaîne etc.

Enfin tous les trucs basiques.


Voyons ces trucs.

Comparer : que veux-tu apprendre sur tes chaînes ?
Dans la norme C tu as strcmp() et strcoll(); les deux donne l'information
identiques/différentes, mais il ne s'agit pas de cela car cela fonctionne
aussi en UTF-8 (enfin au problème de la canonisation près, mais celui-là on
va le mettre de côté pour le moment).
Donc on en arrive à comparer deux chaînes différentes ; strcmp() retourne
une information « bête », c'est-à-dire inexploitable au niveau
lexicographique ; là encore, s'il ne s'agit pas de faire de la
lexicographie, par exemple pour trier un arbre binaire, cela va fonctionner
idem avec UTF-8 (une propriété sympathique de UTF-8 « bien formé » est que
l'encodage est bijectif [le TF, pas le jeu de caractères Unicode] ; en plus
je crois que les résultats sont inchangés en signe par rapport à Latin-1).
Si par contre tu veux des informations lexicographiques, par exemple a < à <
B, alors en Latin-1 tu utiliseras strcoll(), et miracle, cela marche aussi
en UTF-8 (OK, il faut quand même avoir ajouté l'appel à setlocale() au début
de main. Et si cela ne marche pas, bugreport.)
Donc, si tu as un problème maintenant pour comparer, c'est probablement que
le problème existait avant.


Donner la longueur d'une chaîne.
Je suppose que tu veux savoir le nombre de caractères, pas le nombre
d'octets. Avec UTF-8, je vois deux méthodes : la méthode gros bourrin,
mbstowcs()/fgetws() puis wcslen() ; ou le code suivant (non testé) :

size_t utf8len(unsigned char const *s) {
size_t l=0;
if( !s )/*optionnel*/
while( *s ) if( (*s & 0xC0) != 0x80 ) ++l;
return l;
}

On peut aussi tester
while( *s ) l += (*s ^ 0x40) < 0xC0;
qui est équivalent (flippe le bit 6, pour mettre les octets de continuation
0x80-0xBF _derrière_ les octets de début de multiplets 0xC0-0xFD; puis
compte un pour les caractères qui débute un multiplet, et zéro pour les
octets de continuation. Donc au total compte les multiplets).


Pour etc., j'attend d'avoir des précisions.

Voilà. Le reste est à l'avenant. Il faut reprendre les opérations de chaînes
de caractères une à une, et se poser la question « en quoi l'existence de
multiplet va-t-il influencer le résultat ? »
Et à mon sens, par rapport aux multiplets « classiques » (genre les jeux de
caractères d'Extrême-Orient), UTF-8 est plutôt une facilité qu'une
complication, qui permet de par sa nature plus régulière des optimisations
du genre de celle ci-dessus.


A défaut de librairie, je suis preneur d'un lien me donnant des
tuyaux.


Cela dépend complétement du temps que tu penses investir dans ce sujet.
Unicode est un sujet super vaste, donc il est nécessaire de bien définir ses
ambitions pour arriver à quelque chose.
Exemple typique : une comparaison insensible à la casse. Avec US-Ascii ou
Latin-1, il suffit (à º et ª près) de forcer le bit 6 à un lorsque c'est une
lettre. Ce truc (qui ne marche pas avec Latin-9, 'coz ¼/½ et ¾/ÿ, pour
commencer) est inopérant en Unicode, mais si on se penche dessus on en vient
rapidement à se poser des question comme « qu'est-ce que la casse » (par
exemple pour les lettres de l'alphabet phonétique). Comme je suppose que
l'alphabet phonétique ou les utilisations dérivées de celui-ci en Afrique ne
n'intéresse pas, il est indispensable de réduire le champ.
Autre question, que faire des accents ?


Sinon il ne me reste plus qu'à faire des scripts avec des conversions
UFT8-ISO mais là je suis HS et honteux en plus.


La méthode GNU (que je vois de plus en plus souvent mise en ½uvre, même si
cela me semble aberrant), c'est
man iconv

Au moins tu seras en bonne compagnie.


Antoine

Avatar
Eric Levenez
Le 19/12/07 11:38, dans <fkasbg$6ip$, « Antoine
Leca » a écrit :

Déjà et pour commencer sur les chapeaux de roues, utf8 est plutôt mal vu sur
Usenet, en particulier fr.* !


Cela a évolué et il est maintenant accepter, bien heureusement. Il est loin
le temps où des providers comme Free se permettaient de refuser l'UTF-8.

--
Éric Lévénez -- <http://www.levenez.com/>
Unix is not only an OS, it's a way of life.

Avatar
moi-meme
Antoine Leca wrote:

En news:47682b3c$0$32415$,
« moi-meme » va escriure:

Déjà et pour commencer sur les chapeaux de roues, utf8 est plutôt mal vu
sur Usenet, en particulier fr.* !

comme je l'ai dit je subis :-(


Marche OK avec ÿ et char signé, char 16 bits, et
ce genre de tests idiots ? Pareil avec les caractères japonais ?
Non ce sont des chars "à l'ancienne" genre ISO8859-1 (ou 9 ou 15) tout en 8

bits.


Parce que sinon, il faudrait préciser dans quelle mesure ton « bout de C
marche bien » ...


a tourné moultes fois dans des circonstances locales (le contexte que je
m'étais imposé).


Là aussi, un peu de précision pourrait nous éclairer.
Une catastrophe, pour moi c'est les serveurs en rade, ou absence de
courant électrique (je n'habite pas en France) ; et elle n'est complète
que si en plus on est lundi matin, je n'ai pas pris mon café, _et_ mon
boss a justement besoin d'envoyer un courier urgent pour un appel d'offres
avant 10 heures.
En es-tu là ?


Beaucoup moins grave que la fonte des glaces au pöle Nord. Faut
relativiser : pour une vieille dame : la grippe de son chien c'est pire
qu'un tsunami.

La manière standard de faire est d'utiliser des wchar_t pour représenter
les caractères (à distinguer des bytes).
Il y a plein de choses dans la bibliothèque standard :
- mbtowc et compagnie, et aussi mbrtowc et compagnie, une variante
probablement identique dans ton cas
- fgetwc, fputwc, fwprintf etc. pour les entrées-sorties
- wcs*() qui remplace les fonctions en str*()
merci, je vais un tour de ce côté.



Évidemment, si tu as écrit des versions personnelles de manipulations de
chaînes de caractères, il faut les convertir en wchar_t. En général c'est
trivial (dans la plupart des cas c'est une recompilation avec des trucs du
préprocesseur pour changer les noms, équivalent à faire recherche/remplace
sur le source), mais parfois les algorithmes doivent être retouchés ;
parmi les choses qui ne marchent pas, il y a les opérations utilisant des
indices de type caractère, comme par exemple une table qui convertirait un
unsigned char en un indicateur majuscule/minuscule/chiffre/fin_de_ligne.


et par là aussi.



Il y a aussi ICU, mais c'est probablement comme tuer une mouche avec une
ogive nucléaire.


je ne mérite pas ICU.


Voyons ces trucs.

Comparer : que veux-tu apprendre sur tes chaînes ?
Dans la norme C tu as strcmp() et strcoll(); les deux donne l'information
identiques/différentes, mais il ne s'agit pas de cela car cela fonctionne
aussi en UTF-8 (enfin au problème de la canonisation près, mais celui-là
on va le mettre de côté pour le moment).
Donc on en arrive à comparer deux chaînes différentes ; strcmp() retourne
une information « bête », c'est-à-dire inexploitable au niveau
lexicographique ; là encore, s'il ne s'agit pas de faire de la
lexicographie, par exemple pour trier un arbre binaire, cela va
fonctionner idem avec UTF-8 (une propriété sympathique de UTF-8 « bien
formé » est que l'encodage est bijectif [le TF, pas le jeu de caractères
Unicode] ; en plus je crois que les résultats sont inchangés en signe par
rapport à Latin-1). Si par contre tu veux des informations
lexicographiques, par exemple a < à < B, alors en Latin-1 tu utiliseras
strcoll(), et miracle, cela marche aussi en UTF-8 (OK, il faut quand même
avoir ajouté l'appel à setlocale() au début de main. Et si cela ne marche
pas, bugreport.) Donc, si tu as un problème maintenant pour comparer,
c'est probablement que le problème existait avant.


Donner la longueur d'une chaîne.
Je suppose que tu veux savoir le nombre de caractères, pas le nombre
d'octets. Avec UTF-8, je vois deux méthodes : la méthode gros bourrin,
mbstowcs()/fgetws() puis wcslen() ; ou le code suivant (non testé) :

size_t utf8len(unsigned char const *s) {
size_t l=0;
if( !s )/*optionnel*/
while( *s ) if( (*s & 0xC0) != 0x80 ) ++l;
return l;
}

On peut aussi tester
while( *s ) l += (*s ^ 0x40) < 0xC0;
qui est équivalent (flippe le bit 6, pour mettre les octets de
continuation 0x80-0xBF _derrière_ les octets de début de multiplets
0xC0-0xFD; puis compte un pour les caractères qui débute un multiplet, et
zéro pour les octets de continuation. Donc au total compte les
multiplets).


Pour etc., j'attend d'avoir des précisions.

Voilà. Le reste est à l'avenant. Il faut reprendre les opérations de
chaînes de caractères une à une, et se poser la question « en quoi
l'existence de multiplet va-t-il influencer le résultat ? »
Et à mon sens, par rapport aux multiplets « classiques » (genre les jeux
de caractères d'Extrême-Orient), UTF-8 est plutôt une facilité qu'une
complication, qui permet de par sa nature plus régulière des optimisations
du genre de celle ci-dessus.


Cela dépend complétement du temps que tu penses investir dans ce sujet.
Unicode est un sujet super vaste, donc il est nécessaire de bien définir
ses ambitions pour arriver à quelque chose.
la satisfaction personnel : le temps ne compte pas (je suis


Exemple typique : une comparaison insensible à la casse. Avec US-Ascii ou
Latin-1, il suffit (à º et ª près) de forcer le bit 6 à un lorsque c'est
une lettre. Ce truc (qui ne marche pas avec Latin-9, 'coz ¼/½ et ¾/ÿ, pour
commencer) est inopérant en Unicode, mais si on se penche dessus on en
vient rapidement à se poser des question comme « qu'est-ce que la casse »
(par exemple pour les lettres de l'alphabet phonétique). Comme je suppose
que l'alphabet phonétique ou les utilisations dérivées de celui-ci en
Afrique ne n'intéresse pas, il est indispensable de réduire le champ.
Autre question, que faire des accents ?


La méthode GNU (que je vois de plus en plus souvent mise en ½uvre, même si
cela me semble aberrant), c'est
man iconv
c'est ce que je veux éviter.



Au moins tu seras en bonne compagnie.
la compagnie de qui ?

Unixiens ou neuneu ?
Mon ego est déjà bien bas : maintenant il est sous-terre.

Un beau cadeau à digérer. Noël en avance :-)
J'imprime et je traite ligne par ligne.
Je ne vais sans doute pas revenir polluer avant l'année prochaine.
merci pour tous les tuyaux.
Bonnes fêtes

C Hiebel

Avatar
Antoine Leca
[ HS sur fclc, redirigé vers fr.usenet.8bits ]

En news:C38EC41F.C028B%, Eric Levenez va escriure:
Le 19/12/07 11:38, dans <fkasbg$6ip$, « Antoine


à propos de news:47682b3c$0$32415$,


Déjà et pour commencer sur les chapeaux de roues, utf8 est plutôt
mal vu sur Usenet, en particulier fr.* !


Cela a évolué et il est maintenant accepter, bien heureusement.


Bon d'abord, j'ai ici l'occasion de dire que c'est tant mieux !

Cependant, avant de poster, j'avais été faire un tour rapide sur fu8, et je
n'y ai pas vu exactement ce que rapporte Éric. Tout au plus ai-je lu dans
news: «
[DOC] Tables de caracteres utilisees dans la hierarchie fr.* » qu'Olivier
nous autorise [merci] à utiliser UTF-8 lorsque « c'est utile à la bonne
compréhension de ce que l'on veut écrire », tout en précisant que « Les jeux
de caractères fortement recommandés » n'incluent pas UTF-8.
D'où la forme de ma remarque (s'agissant d'un message sans aucun caractère
exotique, tout au plus dix voyelles accentuées).

Est-on sur la même longueur d'ondes ?


Antoine

--
PS sans importance:
Il est loin le temps où des providers comme Free se permettaient
de refuser l'UTF-8.


:-)
Et pour un peu y' rajouterait que j'suis un papy ;-)


Avatar
Antoine Leca
En news:47691bfc$0$20135$, c hiebel va escriure:

Un conseil, évite absolument d'utiliser ton mél « normal » sur Usenet. Tout
contrevenant est passible de la mise en place rapide d'une solution
anti-spam performante...

J'imprime et je traite ligne par ligne.
Je ne vais sans doute pas revenir polluer avant l'année prochaine.


Il ne s'agit pas de pollution. Mais comme tu l'as compris, le sujet est
vaste et qui plus est très mal défriché, donc aux questions vagues les
réponses sont de même.
Si tu as un petit morceau de code qui te donne du fil à retordre, c'est tout
de suite beaucoup plus facile (à condition d'accepter le rapport
signal/bruit du forum).


Antoine

Avatar
moi-meme
Antoine Leca wrote:

En news:47691bfc$0$20135$, c hiebel va escriure:

Un conseil, évite absolument d'utiliser ton mél « normal » sur Usenet.
Tout contrevenant est passible de la mise en place rapide d'une solution
anti-spam performante...


pour l'instant pas de problème. Mon trafic sur les forums est faible.
Ma femme qui navigue sur des trucs plus "grand public" est beaucoup plus
polluée que moi (sur Windows mais je ne sais pas si cela est lié).

Mais comme tu l'as compris, le sujet est
vaste et qui plus est très mal défriché, donc aux questions vagues les
réponses sont de même.
je viens voir les spécialistes sur ce forum pour une question ponctuelle

d'où mon ignorance du sujet. J'ai cherché des posts qui traitaient de
l'UTF8 sans regarder "l'ambiance". Je ne connais pas les "tabous".

Si tu as un petit morceau de code qui te donne du fil à retordre, c'est
tout de suite beaucoup plus facile (à condition d'accepter le rapport
signal/bruit du forum).


Il faut d'abord que je sorte la paire de pince. Si cela ne marche pas promis
je reviendrais mais pas tout de suite : il va y avoir d'autres urgences ...
bien agréables.

Merci encore.
C Hiebel

Avatar
O_TEXT
Mais je suis passé à Debian Etch. Là dedans tout est en UTF8. ...

N'étant sans doute pas le premier y a t'il une bonne petite librairie pour
régler le problème ?


ICU, notamment libicu36 .

en utilisant:
UChar* u_strFromUTF8 (...)

Il doit également exister d'autre solutions.

Comparer des caractères,


int32_t unorm_compare (const UChar *s1, int32_t length1, const UChar
*s2, int32_t length2, uint32_t options, UErrorCode *pErrorCode)
Compare two strings for canonical equivalence.

http://www.icu-project.org/apiref/icu4c/unorm_8h.html

Ou encore:

u_strcmp

http://www.icu-project.org/apiref/icu4c/ustring_8h.html#bdb8af67ab5198b9db020afa9c3114b3

donner la longueur d'une chaîne


u_strlen ( const UChar * s )

http://www.icu-project.org/apiref/icu4c/group__ustring__ustrlen.html#gc4d8a5581fc5bde71d62ebd0a7a84ec5

etc.
Enfin tous les trucs basiques.


On peut faire d'autres choses:

http://www.icu-project.org/apiref/icu4c/


A défaut de librairie, je suis preneur d'un lien me donnant des tuyaux.

Sinon il ne me reste plus qu'à faire des scripts avec des conversions
UFT8-ISO mais là je suis HS et honteux en plus.


Voir recode, file -i et iconv ?