Codage des caractères

_images/martine-ecrit-en-utf8.jpg

dernière mise à jour : 24-11-2014

Objectifs

  • comment les caractères sont-ils codés ?
  • codage ASCII
  • Unicode
  • UTF-32, UTF-8, ISO-8859
  • fonctions chr et ord de Python

Coder des caractères

Le codage des caractères est une convention qui permet, à travers un codage connu de tous, de transmettre de l’information textuelle, là où aucun support ne permet l’écriture scripturale.

Cela consiste à représenter chaque caractère, par un motif visuel, un motif sonore, ou une séquence abstraite. Les techniques des ordinateurs reposent sur l’association d’un caractère à un nombre.

(source Wikipedia)

Code ASCII

Commençons par le code ASCII qui est l’un des plus anciens codes utilisés en informatique.

Le code ASCII (American Standard Code for Information Interchange) définit un jeu de 128 caractères numérotés de 0 à 127. Sept bits suffisent donc à les coder. Cependant, comme la plupart des ordinateurs travaillent sur des données représentées sur un nombre de bits multiple de huit, les caractères ASCII sont codés sur un octet, le bit de poids fort étant 0.

_images/1000px-ASCII-Table-wide.svg.png

Le jeu de caractères ASCII comprend

  1. les 26 lettres de l’alphabet latin en versions majuscules et minuscules,
  2. les 10 chiffres,
  3. les symboles de ponctuation y compris l’espace,
  4. les couples de parenthèses, crochets et accolades
  5. et quelques autres symboles divers.

Tous ces caractères, parfois désignés comme caractères imprimables ont un code compris entre 32 pour l’espace et 126 pour le tilde (~).

Les autres caractères de code compris entre 0 et 31, plus le caractère de code 127, sont appelés caractères de contrôle. On y trouve entre autre la tabulation (notée \t dans les chaînes de caractères) de code 9 et le passage à la ligne (noté \n dans les chaînes) de code 10.

Des extensions au code ASCII

Outre l’anglais, le jeu de caractères du code ASCII permet d’écrire des textes techniques de toute langue utilisant l’alphabet latin, si on accepte d’ommettre les caractères accentués.

Cependant de telles ommissions, ne sont pas acceptables pour des textes de nature littéraire. C’est pourquoi de nombreuses extensions du code ASCII sont très vite apparues.

Parmi ces extensions citons la famille des codes ISO 8859.

Les codes ISO 8859 sont au nombre de 16 et désignés par ISO 8859-nn est un entier compris entre 1 et 16.

Tous ces codes définissent chacun un jeu de 224 caractères codés de 0 à 127 et de 160 à 255 (les codes de 128 à 159 sont inutilisés). Tous ces caractères peuvent et sont représentés sur un octet.

Les caractères de codes compris entre 0 et 127 sont ceux du code ASCII. Les codes ISO 8859 se distinguent par le jeu des caractères de 160 à 255.

Pour avoir les caractères accentués du français il faut utiliser l’ISO 8859-1 (parfois appelé LATIN-1) ou l’ISO 8859-15 (parfois appelé LATIN-15) qui ne se distingue du précédent que par le remplacement de quelques caractères dont le ¤ par . Avec ISO 8859-1 (ou ISO 8859-15), le é est codé 233.

Pour avoir une vue d’ensemble de ces codes, voir Wikipedia.

Unicode

Les diverses extensions du code ASCII, dont les ISO 8859, présentent l’inconvénient d’être incompatibles entre elles, et le plus souvent d’être spécialisées pour un jeu de caractères lié à une langue. Comment alors coder dans un même document des textes rédigés avec des alphabets aussi divers que les alphabets latin, cyrillique, grec, arabe, ... ?

Le mot paix de par le monde
arabe : السلم français : paix grec : ειρήνη
hébreu : שלום japonais : へいわ russe : мир
symbole : ☮ tchèque : mír thai : ความสงบสุข

C’est pourquoi Unicode a vu le jour au début des années 1990.

Unicode, qui actuellement à sa septième version recense environ 110000 caractères, attribue à chacun d’eux un nom et un numéro (appelé point de code) le plus souvent exprimé sous la forme U+XXXX. En voici quelques exemples :

Caractère Nom Numéro (décimal)
A LATIN CAPITAL LETTER A U+0041 (65)
é LATIN SMALL LETTER E WITH ACUTE U+00E9 (233)
œ LATIN SMALL LIGATURE OE U+0153 (339)
ε GREEK SMALL LETTER EPSILON U+03B5 (949)
и CYRILLIC SMALL LETTER I U+0438 (1080)
ש HEBREW LETTER SHIN U+05E9 (1513)
س ARABIC SMALL SEEN U+0633 (1587)
THAI CHARACTER KHO KHWAI U+0E04 (3588)
HIRAGANA LETTER HE U+3078 (12408)
EURO SIGN U+20AC (8364)
PEACE SYMBOL U+262E (9774)

Les caractères de numéros compris entre 0 et 127 sont ceux du code ASCII. Ceux de code compris entre 160 et 255 sont ceux du code ISO 8859-1.

Différents encodages des caractères Unicode

Unicode se contente de recenser, nommer les caractères et leur attribuer un numéro. Mais il ne dit pas comment ils doivent être codés en informatique.

Plusieurs codages des caractères Unicode existent :

  • UTF-32 qui code chaque caractère sur 32 bits (soit quatre octets)
  • UTF-16 qui code chaque caractère sur 16 ou 32 bits (soit deux ou quatre octets)
  • UTF-8 qui code chaque caractère sur 8, 16, 24 ou 32 bits (soit un, deux, trois ou quatre octets).

Le plus couramment utilisé, notamment pour les pages Web, est UTF-8.

En Python

Depuis sa version 3, Python utilise Unicode pour le codage des caractères.

Deux fonctions de Python concernent le codage Unicode des caractères : chr et ord. Ces deux fonctions sont réciproques l’une de l’autre.

La fonction chr

Consultons l’aide sur cette fonction

>>> help (chr)
Help on built-in function chr in module builtins:

chr(...)
    chr(i) -> Unicode character

    Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.

L’aide nous apprend que cette fonction renvoie une chaîne de un caractère dont le numéro (ordinal) Unicode passé en paramètre est compris entre 0 et 0x10ffff.

>>> chr (97)
'a'
>>> chr (237)
'í'
>>> chr (1513)
'ש'
>>> chr (1605)
'م'
>>> chr (9774)
'☮'
>>> chr (12408)
'へ'

Avertissement

Certains entiers compris entre 0 et 0x10ffff sont des numéros de caractères spéciaux. Dans ce cas, ce caractère est présenté dans sa forme hexadécimale.

>>> chr (128)
'\x80'

cette réponse montre que l’entier 128 est le numéro d’un caractère spécial.

Avertissement

D’autres entriers ne sont pas attribués à un caractère. Ils sont réservés. C’est le cas par exemple des entiers de l’intervalle 0xd800-0xdfff. Pour de tels entiers la fonction chr renvoie un caractère marqué par le préfixe \u.

>>> chr (0xda01)
'\uda01'

Avertissement

un autre phénomène peut se produire. Le caractère obtenu par la fonction chr se présente sous forme d’un carré contenant des chiffres hexa, comme par exemple dans ce qui suit :

>>> chr (6047)
'ស'

Cela se produit lorsque le dispositif qui produit l’affichage ne connaît pas le glyphe associé au caractère. Un glyphe est une représentation graphique d’un signe typographique.

Pourtant, il existe bien un caractère Unicode de numéro 6047 : c’est le caractère KHMER LETTER SA (U+179F) (notez que dans notre exemple, le carré contient les chiffres 179F puisque 6047 = 0x179F). L’image ci-dessous montre le glyphe de ce caractère.

_images/khmer_letter_sa.png

La fonction ord

C’est la fonction réciproque de la fonction chr.

>>> help (ord)
Help on built-in function ord in module builtins:

ord(...)
    ord(c) -> integer

    Return the integer ordinal of a one-character string.

D’après cette aide, lorsqu’on lui passe un caractère (une chaîne de un caractère), la fonction ord renvoie un entier associé à ce caractère : c’est son numéro Unicode.

Voici quelques exemples :

>>> ord ('A')
65

Le numéro Unicode du caractère A est 65 (0x41). C’est son code ASCII.

>>> ord ('é')
233

Le numéro Unicode du caractère é est 233 (0xe9). C’est aussi son code ISO-8859-1.

Ordre sur les chaînes de caractères

Les numéros Unicode permettent de définir un ordre sur l’ensemble des caractères.

Un caractère \(c_1\) est dit inférieur ou égal à un caractère \(c_2\), si le numéro Unicode du premier est inférieur ou égal à celui du second.

\[c_1 \leq c_2 \Longleftrightarrow \texttt{ord}(c_1) \leq \texttt{ord}(c_2).\]
>>> chr(8364)
'€'
>>> chr(9774)
'☮'
>>> chr(8364) <= chr(9774)
True

(moralité : la paix est supérieure à l’euro.)

Étant donné que les codes des lettres de l’alphabet latin vont de 65 pour le A à 90 pour le Z, cette relation d’ordre coincide avec l’ordre alphabétique.

>>> 'A' <= 'B' <= 'C' <= 'D'
True

Mais attention, l’ordre alphabétique traditionnel n’est pas respecté entre lettres majuscules et minuscules.

>>> 'Z' <= 'a'
True

L’ordre sur les caractères s’étend aux chaînes de caractères : c’est l’ordre lexicographique. Cet ordre est une généralisation de l’ordre alphabétique utilisé pour ordonner les mots dans un dictionnaire.

>>> 'TIMOLEON' <= 'Timoleon'
True
>>> 'calbuth' <= 'TIMOLEON'
False

Dans l’ordre lexicographique, la chaîne vide est inférieure ou égale à toute autre chaîne.

>>> '' <= 'Timoleon'
True

Exercices

Exercice Numéros Unicode

Pour chacune des chaînes de caractères du tableau Le mot paix de par le monde, déterminez sa longueur ainsi que les numéros Unicode de ses caractères.

Exercice alphabets

Consultez la page de Wikipedia consacrée à Unicode. Choisissez un alphabet de votre choix et construisez la liste des caractères de cet alphabet.

Exercice quelques prédicats

  1. Réalisez un prédicat nommé est_lettre_majuscule qui renvoie True si le caractère passé en paramètre est une lettre majuscule de l’alphabet latin non accentuée et False sinon.
  2. Réalisez un prédicat nommé est_lettre qui renvoie True si le caractère passé en paramètre est une lettre de l’alphabet latin non accentuée et False sinon.
  3. Réalisez un prédicat nommé est_alphanumerique qui renvoie True si le caractère passé en paramètre est une lettre de l’alphabet latin non accentuée ou un chiffre et False sinon.

Exercice mettre en majuscule

  1. Étudiez la différence existant entre le numéro d’une lettre majuscule non accentuée de l’alphabet latin, et celui de la lettre minuscule correspondante.

  2. Réalisez une fonction qui renvoie une chaîne de caractères identique à celle passée en paramètre si ce n’est que toutes les lettres latines minuscules ont été remplacées par la majuscule correspondante.

    >>> en_majuscule ('Timoleon est un homme politique grec du IVème siècle av. J.C.')
    'TIMOLEON EST UN HOMME POLITIQUE GREC DU IVèME SIèCLE AV. J.C.'
    

Conclusion