Logo de kxs.frCours d'informatique pour le lycée et la prépa

Chaînes de caractères

Introduction

Nous avons vu comment représenter des booléens, des entiers et des nombres à virgule flottante dans un ordinateur. Nous allons voir comment sont représentés les textes ou les chaînes de caractères.

Premier codage : ASCII

La première norme pour coder les caractères informatiques a été créée en 1963 et s’appelle donc ASCII (American Standard Code for Information Interchange). Elle associe un nombre sur 7 bits (de 0 à 127) aux lettres de l’alphabet, aux chiffres, aux symboles mathématiques et de ponctuation. 33 codes (les 32 premiers et le dernier) sont réservés à des caractères de contrôle et ne peuvent pas être représentés visuellement. Le code 32 correspond à l'espace. Voici une table recensant tous les caractères ASCII :

Table ASCII
Dec Hex Bin Caractère Dec Hex Bin Caract Dec Hex Bin Caract
000[Null] 432B101011+ 86561010110V
111[Start of Heading] 442C101100, 87571010111W
2210[Start of Text] 452D101101- 88581011000X
3311[End of Text] 462E101110. 89591011001Y
44100[Ene of Transmission] 472F101111/ 905A1011010Z
55101[Enduiry] 48301100000 915B1011011[
66110[Acknowledge] 49311100011 925C1011100\
77111[Bell] 50321100102 935D1011101]
881000[Backspace] 51331100113 945E1011110^
991001[Horizontal Tab] 52341101004 955F1011111_
10A1010[Linefeed] 53351101015 96601100000`
11B1011[Vertical Tab] 54361101106 97611100001a
12C1100[Form Feed] 55371101117 98621100010b
13D1101[Carriage Return] 56381110008 99631100011c
14E1110[Shift Out] 57391110019 100641100100d
15F1111[Shift In] 583A111010: 101651100101e
161010000[Data Link Escape] 593B111011; 102661100110f
171110001[Device Control 1] 603C111100< 103671100111g
181210010[Device Control 2] 613D111101= 104681101000h
191310011[Device Control 3] 623E111110> 105691101001i
201410100[Device Control 4] 633F111111? 1066A1101010j
211510101[Negative Acknowledge] 64401000000@ 1076B1101011k
221610110[Synchronous Idle] 65411000001A 1086C1101100l
231710111[Eng of Trans. Block] 66421000010B 1096D1101101m
241811000[Cancel] 67431000011C 1106E1101110n
251911001[End of Medium] 68441000100D 1116F1101111o
261A11010[Substitute] 69451000101E 112701110000p
271B11011[Escape] 70461000110F 113711110001q
281C11100[File Separator] 71471000111G 114721110010r
291D11101[Group Separator] 72481001000H 115731110011s
301E11110[Record Separator] 73491001001I 116741110100t
311F11111[Unit Separator] 744A1001010J 117751110101u
3220100000 754B1001011K 118761110110v
3321100001! 764C1001100L 119771110111w
3422100010" 774D1001101M 120781111000x
3523100011# 784E1001110N 121791111001y
3624100100$ 794F1001111O 1227A1111010z
3725100101% 80501010000P 1237B1111011{
3826100110& 81511010001Q 1247C1111100|
3927100111' 82521010010R 1257D1111101}
4028101000( 83531010011S 1267E1111110~
4129101001) 84541010100T 1277F1111111[DEL]
422A101010* 85551010101U

Lorsqu'on donne donne un code ASCII, on utilise généralement son codage hexadécimal.

1) Quel est la signification du code ASCII ci-dessous ?

41 53 43 49 49 20 69 73 20 73 77 61 67

2) Donner le code ASCII (en hexadécimal) de la chaîne ci-dessous :

« Vive le LOSC ! »

3) En Python la fonction ord() donne (entre autres) le code ASCII d’un caractère. Ce code est en décimal mais on peut le convertir en hexadécimal avec la fonction hex() et en binaire avec la fonction bin(). Créer un script qui parcourt une chaine de caractère et affiche chaque caractère avec son code ASCII en hexadécimal. Vérifier alors vos deux réponses précédentes.

Le codage ASCII ne permettant pas de représenter de nombreux caractères utilisés en Europe (les caractères accentués par exemple) une nouvelle norme vit le jour dans les années 80.

Une extension d’ASCII : ISO-8859-1

Aussi appelée latin-1 cette extension du codage ASCII permet d’ajouter de nombreux caractères utilisés dans les langues européennes. Elle utilise un bit supplémentaire et offre donc 256 possibilités :

Table ISO-8859-1 (ajout à la table ASCII)
Dec Hex Bin Caractère Dec Hex Bin Caract Dec Hex Bin Car
1288010000000[Padding Character] 171AB10101011« 214D611010110Ö
1298110000001[High Octet Preset] 172AC10101100¬ 215D711010111×
1308210000010[Break Permitted Here] 173AD10101101[­Soft hyphen] 216D811011000Ø
1318310000011[No Break Here] 174AE10101110® 217D911011001Ù
1328410000100[Index] 175AF10101111¯ 218DA11011010Ú
1338510000101[Next Line] 176B010110000° 219DB11011011Û
1348610000110[Start of Selected Area] 177B110110001± 220DC11011100Ü
1358710000111[End of Selected Area] 178B210110010² 221DD11011101Ý
1368810001000[Character Tab Set] 179B310110011³ 222DE11011110Þ
1378910001001[Char Tab with Justification] 180B410110100´ 223DF11011111ß
1388A10001010[Line Tabulation Set] 181B510110101µ 224E011100000à
1398B10001011[Partial Line Forward] 182B610110110 225E111100001á
1408C10001100[Partial Line Backward] 183B710110111· 226E211100010â
1418D10001101[Reverse Line Feed] 184B810111000¸ 227E311100011ã
1428E10001110[Single-Shift Two] 185B910111001¹ 228E411100100ä
1438F10001111[Single-Shift Three] 186BA10111010º 229E511100101å
1449010010000[Device Control String] 187BB10111011» 230E611100110æ
1459110010001[Private Use One] 188BC10111100¼ 231E711100111ç
1469210010010[Private Use Two] 189BD10111101½ 232E811101000è
1479310010011[Set Transmit State] 190BE10111110¾ 233E911101001é
1489410010100[Cancel character] 191BF10111111¿ 234EA11101010ê
1499510010101[Message Waiting] 192C011000000À 235EB11101011ë
1509610010110[Start of Protected Area] 193C111000001Á 236EC11101100ì
1519710010111[End of Protected Area] 194C211000010Â 237ED11101101í
1529810011000[Start of String] 195C311000011Ã 238EE11101110î
1539910011001[Single Graphic Character Introducer] 196C411000100Ä 239EF11101111ï
1549A10011010[Single Character Introducer] 197C511000101Å 240F011110000ð
1559B10011011[Control Sequence Introducer] 198C611000110Æ 241F111110001ñ
1569C10011100[String Terminator] 199C711000111Ç 242F211110010ò
1579D10011101[Operating System Command] 200C811001000È 243F311110011ó
1589E10011110[Private Message] 201C911001001É 244F411110100ô
1599F10011111[Application Program Command] 202CA11001010Ê 245F511110101õ
160A010100000 [Non-breaking space] 203CB11001011Ë 246F611110110ö
161A110100001¡ 204CC11001100Ì 247F711110111÷
162A210100010¢ 205CD11001101Í 248F811111000ø
163A310100011£ 206CE11001110Î 249F911111001ù
164A410100100¤ 207CF11001111Ï 250FA11111010ú
165A510100101¥ 208D011010000Ð 251FB11111011û
166A610100110¦ 209D111010001Ñ 252FC11111100ü
167A710100111§ 210D211010010Ò 253FD11111101ý
168A810101000¨ 211D311010011Ó 254FE11111110þ
169A910101001© 212D411010100Ô 255FF11111111ÿ
170AA10101010ª 213D511010101Õ 256100100000000Ā

4) En Python la fonction ord() donne également le code ISO-8859-1 d’un caractère. À l’aide du script de la question 3, donner le codage de la phrase suivante :

« Ça coûte des sous »

La norme ISO-8859-1 n’était toujours pas parfaite, il manquait par exemple le caractère « œ » pour le français et « ß » pour l’allemand. Il y eu encore d’autre normes pour s’adapter à ces spécificités. Les alphabets asiatiques avaient également leur propre codage. Avec le développement d’internet dans les années 90 et donc la cohabitation de nombreuses langues, le besoin d’un codage universel se faisait sentir.

Codage universel : UTF-8

Apparu en 1996 et adopté définitivement en 2003 l’UTF-8 permet de représenter tous les alphabets du monde. Bien sur UTF-8 a besoin de plus d’un octet pour représenter tout ça !

Unicode

UTF-8 utilise le point de code de chaque caractère. Le point de code d’un caractère est défini de manière unique par la norme unicode. Cette norme contient aujourd’hui 137 929 caractères. Les 256 premiers caractères sont les mêmes que l’ISO-8859-1. On écrit un point de code sous la forme « U+xxxx » ou « xxxx » est exprimé en hexadécimal. Ainsi U+00E0 est le code du « à » et U+0052 le code du « R » (voir les parties précédentes).

Il existe une vidéo sur Youtube faisant défiler les milliers de caractères unicode. Elle dure plus de deux heures :

5) Testez le script suivant pour vérifier que les premiers caractères d’unicode sont les mêmes que pour l’ISO-8859-1 (hex() convertit en hexadécimal et chr() affiche un caractère à partir de son unicode en décimal) :

for c in range(256):
    print(c,hex(c),chr(c))

6) Tester maintenant le script ci-dessous pour voir les 5000 premiers caractères unicode (cela prend du temps) :

for c in range(5000):
    print(c,hex(c),chr(c))

UTF-8

UTF-8 correspond à la façon dont on va écrire le code d’un caractère en mémoire. Les 127 premiers caractères sont codés sur un octet, ainsi UTF-8 est compatible avec l’ASCII. Les caractères suivants seront codés sur plusieurs octets (jusqu’à 4 octets).

Le principe de l'encodage UTF-8 est le suivant :

On peut résumer cela dans le tableau ci-dessous :

Codage utf-8
Caractères Représentation binaire utf-8 Signification
U+0000 à U+007F0xxxxxxx1 octet codant 7 bits
U+0080 à U+07FF110xxxxx 10xxxxxx2 octets codant 11 bits
U+0800 à U+FFFF1110xxxx 10xxxxxx 10xxxxxx3 octets codant 16 bits
U+10000 à U+10FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx4 octets codant 21 bits

Ainsi, les bits en vert doivent être mis bout à bout pour obtenir le code unicode d’un caractère.

7) Pourquoi utilise-t-on un nombre d’octets variable au lieu d’utiliser toujours 4 octets par caractère ?

8) Quel est le code UTF-8 du caractère « j » ?

9) Quel caractère correspond au code UTF-8 « C5 93 » (vous aurez besoin de la fonction chr() en Python qui donne le caractère correspondant à un code unicode en décimal)

10) Quel est le code UTF-8 du signe euro « € » ? (son code unicode est U+20AC, mais vous pouvez utiliser la fonction ord() qui donne aussi le code unicode décimal d’un caractère)

Aide pour les conversions en Python

Il est possible d'utiliser Python pour effectuer des conversions entre décimal, binaire et hexadécimal.

Écriture

Avant de convertir un nombre il faut pouvoir l'écrire dans différentes bases. La base dix étant la base par défaut, il n'y a rien à faire pour écrire un nombre en base 10 :

# 355 en base 10
355

Pour écrire un nombre en base 2, il faut le faire précéder par '0b'.

# 01110 en base 2
0b01110

Pour écrire un nombre en base 16 (hexadécimal), il faut le faire précéder par '0x'.

# A4F en base 16
0xA4F

Conversion vers décimal

La conversion se fait automatiquement, il suffit d'écrire le nombre dans la console :

# Hexadécimal vers décimal
>>> 0xA4F
2639
# Binaire vers décimal
>>> 0b01110
14

Conversion vers binaire

On utilise ici la fonction bin()

# Décimal vers binaire
>>> bin(1234)
'0b10011010010'
# Hexadécimal vers binaire
>>> bin(0xA4F)
'0b101001001111'

Conversion vers hexadécimal

On utilise ici la fonction hex()

# Binaire vers hexadécimal
>>> hex(0b01110)
'0xe'
# Décimal vers exadécimal
>>> hex(1234)
'0x4d2'