Chapitre 7 - Caractères et chaînes de caractères▲
7-1. Les caractères▲
7-1-1. Définition▲
Les caractères sont un ensemble de symboles comprenant les 26 lettres de l'alphabet latin en versions minuscule et majuscule, les 10 chiffres de 0 à 9, les différents symboles de ponctuation, l'espace et bien d'autres symboles encore. Ils sont au nombre de 256 au total.
En Caml, ils forment le type de données char
.
Il est possible de déclarer des constantes de type char
.
Exemple 1 :
2.
# let
espace =
' ';;
val
espace : char
=
' '
Les constantes littérales de type char
sont désignées entre deux apostrophes.
On peut aussi déclarer des variables mutables de type char
.
Exemple 2 :
2.
# let
c =
ref
'a';;
val
c : char
ref
=
{contents
=
'a'}
Il est possible d'écrire une donnée de ce type avec la procédure print_char
.
Exemple 3 :
2.
# print_char
(!c);;
a-
: unit =
()
7-1-2. Fonctions int_of_char et char_of_int▲
Les caractères sont numérotés de 0 à 255.
Exemple 4 :
Par exemple, le caractère ESPACE porte le numéro 32, le caractère A porte le numéro 64 et le caractère a porte le numéro 97.
La figure 7.1 donne pour les 128 premiers caractères leur numéro associé (code ASCII(14)).
NUL |
0 |
ESP |
32 |
@ |
64 |
‘ |
96 |
SOH |
1 |
! |
33 |
A |
65 |
a |
97 |
STX |
2 |
" |
34 |
B |
66 |
b |
98 |
ETX |
3 |
# |
35 |
C |
67 |
c |
99 |
EOT |
4 |
$ |
36 |
D |
68 |
d |
100 |
ENQ |
5 |
% |
37 |
E |
69 |
e |
101 |
ACK |
6 |
& |
38 |
F |
70 |
f |
102 |
BEL |
7 |
' |
39 |
G |
71 |
g |
103 |
BS |
8 |
( |
40 |
H |
72 |
h |
104 |
HT |
9 |
) |
41 |
I |
73 |
i |
105 |
LF |
10 |
* |
42 |
J |
74 |
j |
106 |
VT |
11 |
+ |
43 |
K |
75 |
k |
107 |
FF |
12 |
, |
44 |
L |
76 |
l |
108 |
CR |
13 |
- |
45 |
M |
77 |
m |
109 |
SO |
14 |
. |
46 |
N |
78 |
n |
110 |
SI |
15 |
/ |
47 |
O |
79 |
o |
111 |
DLE |
16 |
0 |
48 |
P |
80 |
p |
112 |
DC1 |
17 |
1 |
49 |
Q |
81 |
q |
113 |
DC2 |
18 |
2 |
50 |
R |
82 |
r |
114 |
DC3 |
19 |
3 |
51 |
S |
83 |
s |
115 |
DC4 |
20 |
4 |
52 |
T |
84 |
t |
116 |
NAK |
21 |
5 |
53 |
U |
85 |
u |
117 |
SYN |
22 |
6 |
54 |
V |
86 |
v |
118 |
ETB |
23 |
7 |
55 |
W |
87 |
w |
119 |
CAN |
24 |
8 |
56 |
X |
88 |
x |
120 |
EM |
25 |
9 |
57 |
Y |
89 |
y |
121 |
SUB |
26 |
: |
58 |
Z |
90 |
z |
122 |
ESC |
27 |
; |
59 |
[ |
91 |
{ |
123 |
FS |
28 |
< |
60 |
\ |
92 |
| |
124 |
GS |
29 |
= |
61 |
] |
93 |
} |
125 |
RS |
30 |
> |
62 |
^ |
94 |
~ |
126 |
US |
31 |
? |
63 |
_ |
95 |
DEL |
127 |
La fonction int_of_char
donne le code du caractère passé en paramètre.
Exemple 5 :
2.
3.
4.
5.
6.
# int_of_char
(' ');;
-
: int
=
32
# int_of_char
('A');;
-
: int
=
65
# int_of_char
('a');;
-
: int
=
97
Inversement, la fonction char_of_int
donne le caractère associé à l'entier passé en paramètre qui doit être compris entre 0 et 255.
Exemple 6 :
2.
3.
4.
# for
i
=
65
to
70
do
print_char
(char_of_int
(i
))
done
;;
ABCDEF-
: unit =
()
7-1-3. Comparaison de caractères▲
Les opérateurs =
, <
, <=
, >
et >=
permettent de comparer deux caractères.
Si c1 et c2 sont deux expressions de type CHAR, alors :
- c1
=
c2 est vrai si et seulement si les deux caractères c1 et c2 sont égaux ; - c1
<
c2 est vrai si et seulement si le numéro du caractère c1 est strictement plus petit que celui de c2 ; - c1
<=
c2 est vrai si et seulement si le numéro du caractère c1 est inférieur ou égal à celui de c2 ; - etc.
7-2. Les chaînes de caractères▲
7-2-1. Définition▲
Les chaînes de caractères sont des séquences finies de caractères. Le nombre de caractères composant une chaîne de caractères est la longueur de cette chaîne. Par la suite nous noterons
kitxmlcodelatexdvp|s| = \text{longueur de s}finkitxmlcodelatexdvpUne chaîne de longueur nulle ne comprend aucun caractère : c'est la chaîne vide.
En Caml, les chaînes de caractères forment le type string
et leur longueur est limitée à 224 - 6 = 16 777 210 caractères.
Il est possible de déclarer des variables de type string
.
Exemple 7 :
2.
3.
4.
# let
chaine1 =
"TIMO"
and
chaine2 =
"LEON"
;;
val
chaine1 : string
=
"TIMO"
val
chaine2 : string
=
"LEON"
Les constantes littérales de type string
sont désignées entre deux guillemets.
Il est possible d'écrire une donnée de ce type au moyen des procédures print_string
et print_endline
.
Exemple 8 :
2.
3.
4.
5.
6.
7.
8.
9.
# begin
print_string
("Bonjour, je m'appelle "
);
print_string
(chaine1);
print_endline
(chaine2);
print_endline
("Et vous, comment vous appelez-vous ?"
)
end
;;
Bonjour, je m'appelle TIMOLEON
Et vous, comment vous appelez-
vous ?
-
: unit =
()
Une chaîne de 1 caractère n'est pas un caractère. Et en particulier on ne peut affecter une valeur de type char
à une variable mutable de type string
.
2.
3.
4.
5.
6.
7.
8.
# let
s =
ref
""
;;
val
s : string
ref
=
{contents
=
""
}
# s :=
'a';;
This expression has type
char
but is here used with
type
string
# s :=
"a"
;;
-
: unit =
()
# s;;
-
: string
ref
=
{contents
=
"a"
}
7-2-2. Notation indicielle▲
Une chaîne de caractères est, par définition, composée de caractères. Ces caractères sont numérotés dans l'ordre à partir de 0, et ces numéros sont appelés indices. Le premier caractère a pour indice 0, le second a pour indice 1, etc. Le dernier caractère a pour indice kitxmlcodeinlinelatexdvp|s| - 1finkitxmlcodeinlinelatexdvp.
On accède au caractère d'indice i
d'une chaîne s avec la notation indicielle pointée :
s.[ i
]
Si s est une chaîne, alors s.[i
] est un caractère.
Exemple 9 :
2.
3.
4.
5.
6.
7.
8.
# chaine1.[0
];;
-
: char
=
'T'
# chaine1.[1
];;
-
: char
=
'I'
# chaine1.[2
];;
-
: char
=
'M'
# chaine1.[3
];;
-
: char
=
'O
'
Les chaînes de caractères sont des structures de données mutables. On peut modifier un caractère d'une chaîne de caractères à l'aide de la notation indicielle. Pour modifier le caractère d'indice i d'une chaîne s, on utilise la flèche <-
.
s.[i
] <-
(* une expression de type char *)
Exemple 10 :
2.
3.
4.
5.
6.
# let
c =
"TiMOLEON"
;;
val
c : string
=
"TiMOLEON"
# c.[1
] <-
'I';;
-
: unit =
()
# c ;;
-
: string
=
"TIMOLEON"
L'accès à un caractère d'une chaîne s n'est possible que si l'indice i
est compris entre 0 et kitxmlcodeinlinelatexdvp| s| - 1finkitxmlcodeinlinelatexdvp. Toute tentative d'accès à un caractère d'indice situé en dehors de cet intervalle déclenche l'exception Invalid_argument "index out of bounds".
2.
3.
4.
5.
6.
# let
chaine1 =
"TIMO"
;;
val
chaine1 : string
=
"TIMO"
# chaine1.[-
1
];;
Exception: Invalid_argument "index out of bounds"
.
# chaine1.[4
];;
Exception: Invalid_argument "index out of bounds"
.
Et voici le code d'une procédure équivalente à la procédure prédéfinie print_string
.
2.
3.
4.
5.
6.
(* ecrire_chaine(s) ecrit a l'ecran la chaine s
cette procedure est equivalente a print_string(s) *)
let
ecrire_chaine(s) =
for
i
=
0
to
String
.length
(s)-
1
do
print_char
(s.[i
])
done
7-2-3. Concaténation▲
La concaténation de deux chaînes de caractères s1 et s2 est l'opération consistant à mettre bout à bout ces deux chaînes. La chaîne ainsi obtenue est appelée concaténée de s1 et s2.
En Caml, c'est l'opérateur ^
qui permet d'exprimer la concaténation de deux chaînes de caractères.
Exemple 11 :
2.
# chaine1^
chaine2;;
-
: string
=
"TIMOLEON"
La longueur de la chaîne de caractères s1^s2 est égale à la somme des longueurs de chacune des deux chaînes
7-2-4. Comparaison de chaînes▲
Les opérateurs =
, <
, <=
, >
et >=
permettent de comparer deux chaînes de caractères.
Si s1 et s2 sont deux expressions de type STRING, alors :
- s1
=
s2 est vrai si et seulement si les deux chaînes de caractères s1 et s2 sont égales ; - s1
<
s2 est vrai si et seulement si la chaîne de caractères s1 vient strictement avant s2 dans l'ordre lexicographique ; - s1
<=
s2 est vrai si et seulement si la chaîne de caractères s1 vient avant s2 dans l'ordre lexicographique ou est égale à s2 ; - etc.
7-2-5. Quelques fonctions prédéfinies sur les chaînes▲
Hormis la première, les fonctions présentées ici ne sont pas à connaître par cœur.
Les fonctions prédéfinies sur les chaînes de caractères font toutes partie du module String. Leur nom est donc préfixé par le mot String (avec un S majuscule).
Longueur d'une chaîne
Exemple 12 :
2.
3.
4.
# String
.length
("TIMOLEON"
);;
-
: int
=
8
# String
.length
(""
);;
-
: int
=
0
Création d'une chaîne d'une taille donnée
où kitxmlcodeinlinelatexdvp\textbf{String.create}(s)finkitxmlcodeinlinelatexdvp est une nouvelle chaîne de kitxmlcodeinlinelatexdvpnfinkitxmlcodeinlinelatexdvp caractères non spécifiés.
Exemple 13 :
2.
# String
.create
(10
);;
-
: string
=
"<\135\236\183\024\017/\008\000\000"
Copie d'une chaîne
où kitxmlcodeinlinelatexdvp\textbf{String.copy}(s)finkitxmlcodeinlinelatexdvp est une nouvelle chaîne, copie de la chaîne kitxmlcodeinlinelatexdvpsfinkitxmlcodeinlinelatexdvp, c'est-à-dire une chaîne égale à kitxmlcodeinlinelatexdvpsfinkitxmlcodeinlinelatexdvp.
Exemple 14 :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
# let
s1 =
"tIMOLEON"
;;
val
s1 : string
=
"tIMOLEON"
# let
s2 =
String
.copy
(s1) ;;
val
s2 : string
=
"tIMOLEON"
# s1 =
s2 ;;
-
: bool
=
true
# s1.[0
] <-
'T' ;;
-
: unit =
()
# s1 ;;
-
: string
=
"TIMOLEON"
# s2 ;;
-
: string
=
"tIMOLEON"
En Objective Caml il n'y a pas de fonction string_of_char qui transforme un caractère en la chaîne constituée de ce seul caractère. C'est un excellent exercice que de réaliser cette fonction avec les fonctions présentées dans ce chapitre (cf exercice 7-3).
7-3. Exercices▲
Exercice 7-1
Sur le modèle de la procédure ecrire_chaine, réalisez une procédure nommée ecrire_vertical qui écrit verticalement la chaîne passée en paramètre. Par exemple, pour la chaîne vertical la procédure écrira à l'écran
v
e
r
t
i
c
a
l
Exercice 7-2
Sur le modèle de la procédure ecrire_chaine, réalisez une procédure nommée ecrire_chaine_a_l_envers qui écrit à l'envers la chaîne passée en paramètre. Par exemple, pour la chaîne repus la procédure écrira à l'écran super
Exercice 7-3 string_of_char
Réalisez la fonction
où kitxmlcodeinlinelatexdvpsfinkitxmlcodeinlinelatexdvp est la chaîne constituée du seul caractère passé en paramètre.
Par exemple on doit avoir
2.
3.
4.
5.
6.
# string_of_char('a') ;;
-
: string
=
"a"
# string_of_char('1
') ;;
-
: string
=
"1"
# string_of_char('+
') ;;
-
: string
=
"+"
Exercice 7-4 string_of_int
Réalisez la fonction
où kitxmlcodeinlinelatexdvpsfinkitxmlcodeinlinelatexdvp est la chaîne de caractères constituée des chiffres de l'écriture décimale de kitxmlcodeinlinelatexdvpnfinkitxmlcodeinlinelatexdvp.
Par exemple on doit avoir
2.
3.
4.
# string_of_int
(123
) ;;
-
: string
=
"123"
# string_of_int
(-
12
) ;;
-
: string
=
"-12"
Exercice 7-5 : Sous-chaînes
Une sous-chaîne d'une chaîne de caractères kitxmlcodeinlinelatexdvpsfinkitxmlcodeinlinelatexdvp est une chaîne composée de caractères consécutifs de kitxmlcodeinlinelatexdvpsfinkitxmlcodeinlinelatexdvp. Elles peuvent être caractérisées par l'indice de début et leur longueur.
Voici par exemple quelques sous-chaînes pour la chaîne kitxmlcodeinlinelatexdvpsfinkitxmlcodeinlinelatexdvp = TIMOLEON :
Sous-chaîne |
début |
longueur |
---|---|---|
T |
0 |
1 |
IMO |
1 |
3 |
LEON |
4 |
4 |
TIMOLEON |
0 |
8 |
Réalisez la fonction
où kitxmlcodeinlinelatexdvps.[deb..deb + long − 1]finkitxmlcodeinlinelatexdvp désigne la sous-chaîne de kitxmlcodeinlinelatexdvpsfinkitxmlcodeinlinelatexdvp débutant à l'indice kitxmlcodeinlinelatexdvpdebfinkitxmlcodeinlinelatexdvp et de longueur kitxmlcodeinlinelatexdvplongfinkitxmlcodeinlinelatexdvp, donc terminant à l'indice kitxmlcodeinlinelatexdvpdeb + long − 1finkitxmlcodeinlinelatexdvp.
Exemple 15 :
2.
3.
4.
5.
6.
7.
8.
# sous_chaine("TIMOLEON"
,0
,1
);;
-
: string
=
"T"
# sous_chaine("TIMOLEON"
,1
,3
);;
-
: string
=
"IMO"
# sous_chaine("TIMOLEON"
,4
,4
);;
-
: string
=
"LEON"
# sous_chaine("TIMOLEON"
,0
,8
);;
-
: string
=
"TIMOLEON"
Exercice 7-6 : Miroir
La chaîne miroir d'une chaîne s est la chaîne dont les caractères successifs sont ceux de la chaîne s dans l'ordre inverse. Par exemple, la chaîne miroir de TIMOLEON est NOELOMIT.
Réalisez la fonction
Exercice 7-7 : Palindromes
Un palindrome est un mot qui se lit de la même façon de gauche à droite et de droite à gauche. ICI, ETE, ELLE et RADAR sont des palindromes.
Réalisez un prédicat qui est vrai si et seulement si la chaîne passée en paramètre est un palindrome.
Exercice 7-8 Initialisations de tas de cartes
Les descriptions des tas de cartes sont des chaînes de caractères.
Question 1 : Initialisez le tas 1 avec une description de tas donnée par l'utilisateur.
Question 2 : Initialisez le tas 1 avec des trèfles dont le nombre est donné par l'utilisateur.
Question 3 : Même question mais chaque carte étant de couleur quelconque.
Exercice 7-9 : Initiale et autres
Question 1 : Réalisez une fonction initiale qui donne le caractère initial (c'est-à-dire le premier) d'une chaîne de caractères. Cette fonction a-t-elle des contraintes d'utilisation ?
Question 2 : Réalisez une fonction finale qui donne le caractère final (c'est-à-dire le dernier) d'une chaîne de caractères. Cette fonction a-t-elle des contraintes d'utilisation ?
Question 3 : Réalisez une fonction sauf_initiale qui donne la chaîne passée en paramètre sans son initiale. Cette fonction a-t-elle des contraintes d'utilisation ?
Exercice 7-10 : Préfixe
Une chaîne de caractères s1 est un préfixe d'une autre s2 si la chaîne s1 est le début de la chaîne s2. À titre d'exemple, les préfixes de 'TIMOLEON' sont '', 'T', 'TI', 'TIM', 'TIMO', 'TIMOL', 'TIMOLE' , 'TIMOLEO' et 'TIMOLEON'.
Réalisez de deux façons différentes une fonction qui teste si une chaîne (premier paramètre de la fonction) est un préfixe d'une autre (second paramètre de la fonction).
Exercice 7-11
Réalisez une fonction qui retourne le plus petit (au sens de l'ordre défini dans la section 7.1.3Comparaison de caractères) caractère de la chaîne de caractères passée en paramètre.