spather@ittc.ukans.edu
hfernandes@april.org
Tcl a été conçu dès le début pour être un langage de commandes réutilisable. Ses auteurs avaient créé un ensemble d'outils interactifs, chacun nécessitant son propre langage de commandes. Comme ils étaient plus intéressés par les outils eux même que le langage de commandes utilisé par les outils, ces langages de commandes furent mis au point rapidement, sans porter attention à leurs cohérences.
Après l'implémentation de plusieurs langages de commandes "vite faits - mal faits" et quelques déboires avec chacun d'entre eux, ils décidèrent de se concentrer sur l'implémentation d'un langage de commandes général et robuste pouvant s'intégrer facilement dans d'autres applications. Ainsi naquit Tcl (Tool Command Language).
Depuis lors, Tcl est largement utilisé comme langage de commandes. Dans la plupart des cas, Tcl est utilisé de concert avec la librairie Tk (Tool Kit), un ensemble de commandes et procédures qui permet de programmer très facilement des interfaces graphiques.
Un des aspects le plus intéressant de Tcl est sa capacité d'extension. Si une application a besoin de fonctionnalités absentes de Tcl, de nouvelles commandes Tcl peuvent être ajoutées à l'aide du langage C et intégrées facilement. Puisque Tcl est si facile à étendre, beaucoup de personnes ont écrit des paquets d'extensions en les rendant disponibles sur internet.
La principale différence entre Tcl et des langages comme le C est que Tcl est un langage interprété et non un langage compilé. Les programmes écrits en Tcl sont en fait des fichiers texte constitués de commandes Tcl qui sont traitées par un interpréteur Tcl au moment de l'exécution. Un avantage que cela offre est qu'un programme Tcl peut générer lui-même des fichiers de commandes Tcl qui peuvent être évaluées à un autre moment. Cela peut être utile, par exemple, lors de la création d'une interface graphique avec un bouton qui accomplit différentes actions selon le moment.
Les sections suivantes décrivent les éléments principaux de programmes écrits en Tcl. Chaque section comprend une série d'exemples.
Les variables en Tcl, comme dans la plupart des autres langages, peuvent être vues comme des boîtes dans lesquelles différents types de données sont placés. Ces boîtes, ou variables, reçoivent des noms, qui sont utilisés pour accéder aux valeurs placées dans ces boîtes.
Contrairement au C, Tcl n'exige pas que les variables soient déclarées
avant d'être utilisées. Les variables Tcl sont simplement créées
lorsqu'on leur affecte une première valeur, en utilisant la commande
set
. Bien qu'elles n'aient pas besoin d'être supprimées, les
variables Tcl le sont avec la commande unset
.
La valeur placée dans une variable est accessible en préfaçant le nom de la variable par le symbole dollar ("$"). Cela s'appelle une substitution de variable (ou interpolation), c'est illustré dans les exemples ci-dessous.
Tcl est un exemple de langage "faiblement typé". Cela signifie que n'importe quel type de donnée peut-être placé dans n'importe quelle variable. Par exemple, la même variable peut être utilisée pour stocker un nombre, une date, une chaîne de caractères et même un autre programme Tcl.
Exemple 1
set foo "john" puts "Salut mon nom est $foo"
Salut mon nom est john
L'exemple 1 illustre l'utilisation de la substitution de variable. La
valeur "john" est assignée à la variable "foo", valeur ensuite
substituée par "$foo". Noter que la substitution de variable peut
s'opérer à l'intérieur d'une chaîne de caractères. La commande
puts
(décrite dans une prochaine section) est utilisée pour
afficher une chaîne de caractères.
Exemple 2
set mois 2 set jour 3 set annee 97 set date "$jour:$mois:$annee" put $date
3:2:97
Ici la substitution de variable est utilisée à plusieurs endroits :
les valeurs des variables "mois", "jour" et "annee" sont substituées
dans la commande set
qui assigne la valeur dans la variable
"date", la valeur de la variable "date" est ensuite substituée dans la
ligne qui affiche le résultat (NdT: Tcl ne supporte pas l'utilisation
de lettre accentuées dans les noms de variables).
Exemple 3
set foo "puts salut" eval $foo
salut
Dans cet exemple, la variable "foo" contient un autre (petit)
programme Tcl qui affiche simplement le mot "salut". La valeur de la
variable "foo" est substituée dans une commande eval
, qui a pour
effet de l'évaluer dans l'interpréteur Tcl (la commande eval
sera
décrite en détail dans une section prochaine.
Tcl permet différents types d'expressions comme les expressions
mathématiques et les expressions relationnelles. Les expressions TCL
sont généralement évaluées par la commande expr
comme illustré
dans les exemples suivants.
Exemple 4
expr 0 == 1
0
expr 1 == 1
1
Les exemples 4 et 5 illustrent l'utilisation d'expressions
relationnelles avec la commande expr
. La première expresion est
évaluée à 0 (faux) comme 0 n'est pas égal à 1, tandis que la seconde
expression est évaluée à 1 (vrai), comme, évidemment, 1 est égal à 1.
L'opérateur de relation "==" est utilisé pour faire la comparaison.
Exemple 6
expr 4 + 5
9
L'exemple 6 montre comment utiliser la commande expr
pour évaluer
une expression arithmétique. Ici le résultat est simplement la somme
de 4 et 5. Tcl dispose d'un jeu important d'opérateurs arithmétiques
et relationnels, chacun est décrit dans la page du manuel en ligne de
Tcl, section expr
.
Exemple 7
expr sin(2)
0.909297
Cet exemple montre que la commande expr
peut être utilisée pour
évaluer le résultat d'une fonction mathématique, ici le sinus d'un
angle. Tcl dispose de beaucoup d'autres fonctions mathématiques, aussi
décrites dans la page du manuel en ligne de tcl, section expr
.
De même que la substitution de variable, une substitution de commande peut être utilisée pour remplacer une commande Tcl par le résultat qu'elle retourne. Considérer l'exemple suivant :
Exemple 8
puts "J'ai [expr 10 * 2] ans, et mon QI est de [expr 101-100]"
J'ai 20 ans, et mon QI est de 1
Comme cet exemple le montre, les crochets sont utilisés pour accomplir la substitution de commande. Le texte entre crochet est évalué comme un programme Tcl, et son résultat est substitué à sa place. Dans ce cas, la substitution de commande est utilisée pour placer le résultat de deux expressions mathématiques dans une chaîne de caractères. La substitution de commande est souvent employée de concert avec la substitution de variable, comme le montre l'exemple 9 :
Exemple 9
set poids 6 puts "Si j'étais 2 pouces plus grand, je mesurerais [expr $poids + (2.0 / 12.0)] pieds"
Si j'étais 2 pouces plus grand, je mesurerais 6.16667 pieds
Dans cet exemple, la valeur de la variable "mon_poids" est substituée entre les crochets avant que la commande ne soit évaluée. C'est une bonne illustration du mécanisme récursif en une passe de décodage de Tcl. Lors de l'évaluation d'un tel bloc, l'interpréteur Tcl fait une passe sur ce bloc, et en faisant de la sorte procède à toutes les substitutions nécessaires. Une fois que cela est fini, l'interpréteur évalue l'expression obtenue. Si lors de sa passe sur le bloc, l'interpréteur rencontre des crochets (indiquant qu'une substitution de commande doit être effectuée), il décode récursivement le programme entre crochet de la même manière.
Dans la plupart des programmes, des mécanismes sont nécessaires pour
contrôler le flot d'exécution. Tcl offre des instructions de branchement
conditionnel (if-else
et switch
) ainsi que des opérateurs de
boucle (while
, for
et foreach
), les deux permettent de
modifier le flot d'execution en réponse à certaines conditions. Les
exemples suivants illustrent ces opérateurs.
Exemple 10
set ma_planete "Terre" if {$ma_planete == "Terre"} { puts "Je me sens bien chez moi." } elseif {$ma_planete == "Venus"} { puts "Ce n'est pas chez moi." } else { puts "Je ne suis ni de la Terre ni de Venus" } set temp 30 if {$temp < 25} { puts "Il fait un peu frais." } else { puts "C'est assez chaud pour moi." }
Je me sens bien chez moi. C'est assez chaud pour moi.
L'exemple 10 utilise deux fois l'instruction if
. Il initialise la
variable "ma_planete" avec la valeur "Terre", et ensuite utilise le
mot clef if
pour choisir quel message imprimer. La syntaxe
générale de l'instruction if
est la suivante :
if test1 bloc1 ?elseif test2 bloc2 elseif ...? ?else blocn?
Si l'expression test1
est évaluée à vrai alors le bloc1
est
exécuté. Sinon, et s'il existe des instructions elseif
, leurs
expressions de test sont évaluées et si vraies les blocs
correspondants sont exécutés. Si l'un des tests est vrai,
l'instruction if
se termine après l'exécution de son bloc
correspondant et ne fait plus d'autre comparaison. Si une instruction
else
est présente, son bloc est exécuté si aucun autre test
ne s'évaluait à vrai.
Une autre instruction de branchement conditionnel est switch
.
C'est une simplification de l'instruction if
qui est utile
lorsque l'on veut exécuter un bloc selon un ensemble de valeurs
possibles et connues d'une variable. C'est illustré dans l'exemple
11, qui utilise une instruction switch
pour imprimer une phrase,
selon la valeur de la variable "nb_jambes".
Exemple 11
set nb_jambes 4 switch $nb_jambes { 2 {puts "Cela peut être un humain."} 4 {puts "Cela peut être une vache."} 6 {puts "Cela peut être une fourmis."} 8 {puts "Cela peut être une araignée."} default {puts "Cela peut être n'importe quoi."} }
Cela peut être une vache.
L'instruction switch
a deux formes générales (formes qui sont
expliquées en details dans le manuel en ligne de Tcl). La forme
utilisée ici est comme suit :
switch ?options? expression {constante bloc ?constante bloc
...?}
L'argument expression
est comparé à chaque constante
et si
une comparaison est vraie, le bloc correspondant est exécuté, après
cela l'instruction switch
se termine. Si le mot clef
default
est présent, son bloc est exécuté si aucune autre
comparaison n'a réussi.
Il est souvent pratique d'exécuter de façon répétée certaines parties
d'un programme jusqu'à ce qu'une condition soit réalisée. Dans ce
but, Tcl dispose de trois instructions de boucle : while
,
for
et foreach
. Chacune est présentée avec un exemple ci
dessous.
Exemple 12
for {set i 0} {$i < 10} {incr i 1} { puts "Dans la boucle for, et i == $i" }
Dans la boucle for, et i == 0 Dans la boucle for, et i == 1 Dans la boucle for, et i == 2 Dans la boucle for, et i == 3 Dans la boucle for, et i == 4 Dans la boucle for, et i == 5 Dans la boucle for, et i == 6 Dans la boucle for, et i == 7 Dans la boucle for, et i == 8 Dans la boucle for, et i == 9
La syntaxe générale pour la boucle for
est la suivante :
for init test reinit bloc
L'argument init
est un script Tcl qui initialise la variable
de la boucle. Dans la boucle for
de l'exemple 12, la variable de
boucle est appelée "i", et l'argument init
l'initialise simplement
à 0. L'argument test
est un script Tcl qui est évalué pour
décider de rentrer ou non dans le bloc
de la boucle
for
. Chaque fois qu'il est évalué à vrai, le bloc
de la
boucle est exécuté. La première fois que ce script est évalué à faux,
la boucle se termine. L'argument reinit
spécifie un script qui
est appelé après chaque exécution du bloc
. Dans l'exemple 12, le
script reinit
incrémente de 1 la valeur de boucle "i". Ainsi dans
notre exemple, la boucle for
exécute son bloc
10 fois avant
que son argument test
soit évalué à faux, causant la fin de la
boucle.
Exemple 13
set i 0 while {$i < 10} { puts "Dans la boucle while, et i == $i" incr i 1 }
Dans la boucle while, et i == 0 Dans la boucle while, et i == 1 Dans la boucle while, et i == 2 Dans la boucle while, et i == 3 Dans la boucle while, et i == 4 Dans la boucle while, et i == 5 Dans la boucle while, et i == 6 Dans la boucle while, et i == 7 Dans la boucle while, et i == 8 Dans la boucle while, et i == 9
L'exemple 13 illustre l'utilisation de la boucle while
, de syntaxe générale :
while test bloc
Le concept de base derrière la boucle while
est que tant que le
script spécifié par l'argument test
est évalué à vrai, le script
bloc
est exécuté. La boucle while
dans l'exemple 13 a le
même effet que la boucle for
de l'exemple 12. Une variable de
boucle "i" est de même initialisée à 0 et incrémentée à chaque
exécution du bloc
. La boucle se termine lorsque la valeur de la
variable "i" atteind 10.
Noter que dans le cas de la boucle while
, l'initialisation et
réinitialisation de la variable de boucle ne font pas partie de la
déclaration while
elle-même. Aussi, l'initialisation de la
variable est faite avant la boucle, et la réinitialisation est incluse
dans le bloc
. Si ces déclarations n'étaient pas faites, le code
fonctionnerait sans doute encore, mais avec des résultats inattendus.
Exemple 14
foreach voyelle {a e i o u} { puts "$voyelle est une voyelle" }
a est une voyelle e est une voyelle i est une voyelle o est une voyelle u est une voyelle
La boucle foreach
, illustrée dans l'exemple 14, opère
différemment des autres types de boucles Tcl décrites dans cette
section. Alors que les boucles for
et while
s'exécutent
tant qu'une certaine condition est vraie, la boucle foreach
s'exécute une fois pour chaque élément d'une liste fixée. Sa syntaxe
générale est :
foreach varNom liste bloc
La variable varNom
prend successivement les valeurs spécifiées
dans la liste
, et le bloc
est exécuté à chaque fois. Dans
l'exemple 14, la variable "voyelle" prend successivement les valeurs
de la liste "{a e i o u}" (La structure d'une liste Tcl sera détaillée
dans une section suivante), et pour chaque valeur, le bloc
de la
boucle est exécuté, ici il déclenche l'impression à l'écran d'une
chaîne de caractères.
Les procédures en Tcl sont l'équivalent des fonctions en C. Elles peuvent prendre des arguments et peuvent retourner des valeurs. La syntaxe pour définir une procédure est la suivante :
proc nom listeArg bloc
Une fois qu'une procédure est créée, elle est considérée comme une
commande comme les commandes natives de Tcl. Comme telle, elle peut
être appelée en utilisant son nom
, suivit par une valeur pour
chacun de ses arguments. La valeur retournée par une procédure est
équivalente au résultat d'une commande native Tcl. Ainsi, la
substitution de commande peut être utilisée pour substituer la valeur
retournée par une procédure dans une autre expression.
Par défaut, la valeur retournée par une procédure est le résulat de la
dernière commande exécutée dans le bloc
. Cependant, pour
retourner une autre valeur, la commande return
peut être
utilisée. Si un argument est fourni avec la commande return
,
alors la valeur de cet argument devient le résultat de la
procédure. La commande return
peut être utilisée n'importe où
dans le bloc
de la procédure, causant la sortie immédiate.
Exemple 14
proc sum_proc {a b} { return [expr $a + $b] } proc v_abs {num} { if {$num > 0} { return $num } set num [expr $num * (-1)] return $num } set num1 12 set num2 14 set sum [sum_proc $num1 $num2] puts "La somme est $sum" puts "La valeur absolue de 3 est [v_abs 3]" puts "La valeur absolue de -2 est [v_abs -2]"
La somme est 26 La valeur absolue de 3 est 3 La valeur absolue de -2 est 2
Cet exemple crée deux procédures : "sum" et "v_abs". "sum_proc" prend deux arguments et retourne simplement la valeur de leur somme. "v_abs" retourne la valeur absolue d'un nombre. Après la définition des procédures, trois variables globales sont déclarées. La dernière de celles-ci, "sum" reçoit la valeur retournée par la procédure "sum_proc", appelée avec les valeurs des variables "num1" et "num2" comme arguments. La procédure "v_abs" est appelée deux fois, avec "3" comme argument puis avec "-2".
La procédure "sum_proc" utilise la commande expr
pour calculer la
somme de ces arguments. Le résultat de la commande expr
est
substitué dans la commande return
, en faisant la valeur de retour
de la procédure.
La procédure "v_abs" utilise une commande if
pour prendre deux
décisions différentes, selon le signe de l'argument. Si le nombre est
postif, sa valeur est retournée, et la procédure se termine
immédiatement, évitant le reste du code de la procédure. Sinon, le
nombre est multiplié par -1 pour obtenir sa valeur absolue, et cette
valeur est retournée. Le même effet peut être produit en deplaçant la
ligne qui multiplie la valeur par -1 dans une clause else
, mais
le but de cet exemple est d'illustrer l'utilisation de la commande
return
à différents endroits de la procédure.
Exemple 15
proc muet_proc {} { set mavar 4 puts "La valeur de la variable locale est $mavar" global mavarglobale puts "La valeur de la variable globale est $mavarglobale" } set mavargobale 79 muet_proc
La valeur de la variable locale est 4 La valeur de la variable globale est 79
La procédure "muet_proc" ne fait rien de spécial si ce n'est
d'illustrer l'usage du mot-clef global
pour accéder à des
variables globales. Elle ne prend pas d'argument, donc sa liste
d'arguments est vide. Note : bien que la procédure ne prenne pas
d'argument, la structure de liste vide doit être incluse.
La procédure crée dans un premier temps une variable locale, "mavar"
initialisée à 4 et l'affiche. Ensuite elle utilise le mot-cléf
global
pour gagner l'accès à la variable globale
"mavarglobale". La valeur de cette variable globale est ensuite
affichée.
Après la définition de la procédure, une variable gloable "mavarglobale" est créée, et reçoit une valeur de 79. La procédure "muet_proc" est ensuite appelée, donnant le résulat donné au-dessus.
Les listes en Tcl offrent un moyen simple de grouper un ensemble d'éléments, et de gérer ce groupe comme une seule entité. Si nécessaire, les éléments du groupe sont accessibles individuellement. En Tcl, les listes sont représentées comme des chaînes de caractères avec un format spécifique. Comme telle, elles sont utilisables partout où les chaînes de caractères le sont. Les éléments d'une liste sont aussi des chaînes de caractères, ainsi toute forme de donnée qui est représentable dans une chaîne de caractères peut être incluse dans une liste. (permettant d'imbriquer des listes).
Les exemples suivants illustrent plusieurs aspects importants des listes :
Exemple 16
set simple_liste "John Joe Mary Susan" puts [lindex $simple_liste 0] puts [lindex $simple_liste 2]
John Mary
L'exemple 16 crée un liste de quatre éléments, chacun consistant en un
mot. La commande lindex
est utilisée pour extraire deux éléments
de la liste : l'élément 0 et le 2e élément. Note : l'indexage d'une
liste commence à zéro. Il est aussi important de noter que la commande
lindex
, comme la plupart des autres commandes relatives aux
listes, prend comme premier argument une liste, et non le nom d'une
variable contenant une liste. Ainsi la valeur de la variable
"simple_liste" est substituée dans la commande lindex
.
Exemple 17
set simple_liste2 "Michael Samuel Sophie Stéphanie" set groupe_liste [list $simple_liste $simple_liste2] puts $groupe_liste puts [llength $groupe_liste]
{John Joe Mary Susan} {Michael Samuel Sophie Stéphanie] 2
L'exemple 17 est une continuation de l'exemple 16, et suppose que la
variable "simple_liste" (créée dans l'exemple 16) existe
toujours. Dans cet exemple, une nouvelle variable "simple_liste2" est
créée, et reçoit comme valeur une autre liste de quatre éléments. Une
liste groupée est ensuite formée en utilisant la commande list
,
qui forme simplement une liste à partir de ces arguments. La commandes
list
s'assure que la liste construite est cohérente, même si ses
arguments sont des listes ou des structures plus complèxes. En
affichant la valeur de "groupe_liste", on s'aperçoit que c'est une
liste de deux éléments, chacun étant eux-même des listes de quatre
éléments. La commande llength
est utilisée pour obtenir la
longueur de la liste, "groupe_liste", qui est 2 dans ce cas.
Ces exemples mettent en valeur deux méthodes pour créer des listes en
Tcl : en listant explicitement les éléments entre des guillemets ou en
utilisant la commande list
. Lister explicitement les éléments
fonctionne bien lorsque chaque élément est un seul mot. Cependant, si
l'élément contient des espaces alors cela devient un peu plus
délicat. Dans ces cas, la commande list
s'avère très utile.
Exemple 18
set maliste "Mercure Venus Mars puts $maliste set maliste [linsert $malistet 2 Terre] puts $maliste lappend malistet Jupiter puts $maliste
Mercure Venus Mars Mercure Venus Terre Mars Mercure Venus Terre Mars Jupiter
Dans l'exemple 18, une liste de 3 éléments est créée et assignée à la
variable "maliste". La commande linsert
est utilisée pour
insérer un nouvel élément dans liste. Note : comme pour la variable
llength
, la commande linsert
prend en premier argument une
liste et non le nom d'une variable contenant une liste. La commande
linsert
retourne une liste qui est la même que celle passée en
argument avec l'élément spécifié (le troisième argument) inséré à la
position spécifiée (le deuxième argument). Cette valeur de retour
doit être assignée à la variable "maliste" pour actualiser la liste
placée dans cette variable.
Une commande de liste qui se comporte différemment est la commande
lappend
. Elle prend comme premier argument le nom d'une
liste et ajoute à sa fin les arguments suivants, le tout est
assigné à cette variable. Ainsi la valeur de la variable est modifiée
directement par la commande. Comprendre la différence de
fonctionnement des commandes linsert
et lappend
est
fondamental pour utiliser correctement les listes.
Les commandes de listes présentées ici représentent seulement une petite partie de ce qui est disponible. Le manuel Tcl/Tk en ligne présente une description complète de toutes les commandes de listes.
Une autre façon de grouper des données est d'utiliser des tableaux. Un tableau est simplement une collection d'éléments dans laquelle eux reçoit un indice unique qui permet d'y accéder. Comme pour toutes les autres variables Tcl, un tableau n'a pas besoin d'être déclaré avant d'être utilisé, contrairement aux tableaux en C, leurs tailles n'ont pas besoin d'être précisées.
Un élément individuel d'un tableau peut être référencé en utilisant le
nom du tableau suivi immédiatement (entre parenthèses) de l'indice de
l'élément. Les éléments de tableau sont traités comme n'importe
quelle autre variable Tcl. Ils sont créés avec la commande set
,
et leurs valeurs peuvent être substituées en utilisant le signe dollar
("$"), comme c'est le cas pour les autres variables.
Exemple 19
set montableau(0) "Zéro" set montableau(1) "Un" set montableau(2) "Deux" for {set i 0} {$i < 3} {incr i 1} { puts $montableau($i) }
Zéro Un Deux
Dans l'exemple 19, un tableau appelé "montableau" est créé et
initialisé. Note : aucune commande spéciale est nécessaire pour créer
le tableau car il l'est par la commande set
qui affecte une
valeur au premier élément du tableau. La boucle for
affiche
simplement les valeurs stockées dans chacun des éléments du
tableau. Noter l'usage de la substitution dans l'indice de tableau et
le nom de tableau.
Exemple 20
set personne_info(nom) "André Dupont" set personne_info(age) "78" set personne_info(metier) "Artiste" foreach chose {nom age metier} { puts "$chose == $personne_info($chose)" }
nom == André Dupont age == 78 metier == Artiste
L'exemple 20 illustre un des aspects uniques des tableaux Tcl : les
indices de tableau ne sont pas nécessairement des entiers. En fait,
les indices de tableau peuvent être n'importe quelle valeur de chaîne
de caractères. Dans ce cas, le tableau "personne_info" est créé avec
trois éléments. Les indices pour ces éléments sont "nom", "age" et
"metier". La boucle foreach
affiche simplement chacun des
éléments du tableau.
Utiliser des tableaux avec des noms comme indice est une des façons d'abstraire des objets en Tcl. Dans l'exemple 20, le tableau "personne_info" peut être considéré comme un objet décrivant une personne. Chacun des éléments dans le tableau décrit un attribut fondamental de cet objet.
Un des problèmes de l'utilisation de tableau avec des noms comme
indices est que l'on doit se souvenir des noms de tous les éléments
pour parcourir le tableau. Dans l'exemple 20, les noms de tous les
éléments doivent être listés explicitement. Dans cet exemple, où il
n'y a que trois éléments, ce n'est pas un problème. Cependant, si le
tableau contient beaucoup plus d'éléments, les citer explicitement
chaque fois qu'un tableau doit être parcouru amène à un code lourd.
Cependant la commande array
offre une solution élégante à ce
problème :
Exemple 21
set personne_info(nom) "André Dupont" set personne_info(age) "78" set personne_info(metier) "Artiste" foreach chose [array names personne_info] { puts "$chose == $personne_info($chose)" }
metier == Artiste age == 78 nom == André Dupont
L'exemple 21 produit essentiellement le même résultat que l'exemple
20, mais il utilise la commande array
pour obtenir les noms des
éléments du tableau, au lieu de les lister explicitement. Les éléments
du tableau sont affichés dans un ordre différent que dans l'exemple
20, car la commande array
retournent les noms des éléments dans
un ordre différent que celui lors du listage explicite.
Plus généralement, l'objet de la commande array
est d'obtenir
différents types d'informations d'un tableau (comme sa taille ou les
noms de ses éléments) et d'effectuer des opérations sur des tableaux
(comme des recherches). La syntaxe générale de la commande array
est :
array option nomTableau ?arg arg ...?
L'argument option
spécifie quelle opération faire. Dans le cas de
l'exemple 21, l'argument option
avait la valeur "names". Cette
valeur d'argument demande à la commande array
de retourner une
liste des noms des éléments dans le tableau dont le nom est donné par
nomTableau
. Pour une liste complète des valeurs possibes de
l'argument option
ainsi qu'une description complète des
opérations correspondantes, consulter le manuel en ligne.
Comme les chaînes de caractères sont les types de données les plus
répandues dans Tcl, il est logique que Tcl fournisse un ensemble très
riche de fonctions pour les manipuler. La plupart des opérations sur
les chaînes de caractères se font avec la commande
string
. Commande qui a la forme, générale suivante :
string option arg ?arg ...?
La commande string
donne en fait accès à plusieurs fonctions
différentes. L'argument option
est utilisé pour les différencier.
L'exemple 22 crée une chaîne de caractères et utilise la commande
string
pour la manipuler et obtenir des informations à son
propos.
Exemple 22
set str "C'est une chaîne de caractères" puts "La chaîne de caractères est : $str" puts "La longueur de la chaîne de caractères est : [strting length $str]" puts "Le caractère à la position 3 est : [string index $str 3]" puts "Les caractères de la position 4 à 8 sont : [string range $str 4 8]" puts "La position de la première occurrence de la lettre \"a"\ est : [string first a $str]"
La chaîne de caractères est : C'est une chaîne de caractères La longueur de la chaîne de caractères est : 30 Le caractère à la position 3 est : s Les caractères de la position 4 à 8 sont : t une La position de la première occurrence de la lettre "a" est : 12
Dans l'exemple 22, une variable "str" est créée et initialisée à la
valeur "C'est une chaîne de caractères". La commande string
est
alors utilisée avec différentes options pour obtenir des informations
à-propos de la chaîne de caractères. Le manuel de Tcl/Tk en ligne
présente l'ensemble de ces options. Aussi, il existe d'autres commandes
relatives aux chaînes de caractères comme format
, regexp
,
regsub
et scan
.
En Tcl, la plupart des opérations d'entrée et de sortie se font
avec les commandes puts
et gets
. La plupart des exemples de
ce document ont utilisé la commande puts
pour afficher un
résultat sur la console. De la même façon, la commande gets
peut
être utilisé pour attendre une entrée de la console, et éventuellement
la stocker dans une variable. Sa syntaxe générale est la suivante :
gets channelId ?NomVar?
Le premier argument de la commande gets
est le nom d'un canal
ouvert, duquel on lit les données. Cela correspond au descripteur
de fichier en C. Si l'argument NomVar
est précisé, gets
place les données lues dans cette variable et retourne le nombre
d'octets lus. Si NomVar
n'est pas précisée alors gets
retourne simplement les données lues.
Exemple 23
puts -nonewline "Entrez votre nom :" set octetslus [gets sdtin nom] puts "Votre nom est $nom, et fait $octetslus caractères de longueur"
Entrez votre nom : Shyam Votre nom est Shyam, et fait 5 caractères de longueur
L'exemple 23 utilise à la fois les commandes puts
et gets
.
La commande puts
est utilisée avec le drapeau -nonewline
pour supprimer le retour chariot qui est normalement ajouté à la
sortie. Une variable "octetslus" reçoit le résultat de la commande
gets
qui lit le canal "stdin" (entrée standard). Les données
lues sont placées dans une variable "nom". Ainsi, "octetslus"
représente le nombre de caractères qu'un utilisateur entre depuis la
console.
Dans l'exemple 23, gets
est utilisée pour lire depuis le canal
"stdin" (créé automatiquement quand l'interpréteur Tcl est démarré)
qui correspond à l'entrée standard. La commande puts
peut aussi
être utilisée avec un identifiant de canal pour écrire dans un canal
spécifique. Cependant, si aucun identifiant de canal n'est spécifié à
la commande puts
, alors la sortie se fait sur la sortie standard
(c'est de cette façon que fut utilisé puts
dans beaucoup
d'exemples de ce document). En plus de l'entrée et de la sortie
standards, des canaux peuvent être créés pour lire depuis d'autres
types de fichiers. Comme illustré dans l'exemple 24, la commande
open
permet d'ouvrir un canal vers un fichier et d'obtenir un
identifiant pour ce canal. Cet identifiant est ensuite passé à la
commande gets
pour lire dans le fichier, ou à la commande
puts
pour écrire dans le fichier.
Exemple 24
set f [open "/tmp/myfile" "w"] puts $f "Nous habitons au Texas. Il fait déjà 110°F ici." puts $f "456" close $f
Aucun
Cet exemple utilise la commande open
pour ouvrir un canal vers un
fichier appelé "/tmp/myfile". La syntaxe de la commande open
peut
prendre trois formes, dont l'une est la suivante :
open nom ?accès?
L'argument accès
spécifie quel type d'accès (par exemple, accès
en lecture-seule ou lecture-écriture) est souhaité sur le fichier
donné par nom
. Voir le manuel Tcl en ligne de open
pour une
description complète des modes d'accès. Dans notre cas, un accès en
écriture uniquement est souhaité, aussi la valeur "w" (write) est
donnée à l'argument accès
.
La commande open
retourne un identifiant de canal qui peut être
utilisé par gets
et puts
pour lire et écrire dans le
fichier. Dans l'exemple 24, cet identifiant est placé dans la variable
"f". La commande puts
est ensuite utilisée pour écrire deux
chaînes de caractères dans ce fichier. Ensuite, la commande close
ferme le fichier.
L'exemple 25 lit le fichier créé dans l'exemple 24 et affiche son contenu.
Exemple 25
set f [open "/tmp/myfile" "r"] set ligne1 [gets $f] set long_ligne2 [gets $f ligne2] close $f puts "ligne 1 : $ligne1" puts "ligne 2 : $ligne2" puts "Longueur de la ligne 2 : $long_ligne2"
ligne 1 : Nous habitons au Texas. Il fait déjà 110°F ici. ligne 2 : 456 Longueur de la ligne 2 : 3
Le fichier "/tmp/myfile" est ouvert en lecture seule avec la commande
open
. La commande gets
est alors utilisée avec
l'identifiant de canal retourné par open
pour lire dans le
fichier. Le premier appel à gets
ne fournit pas dans la liste
des arguments une variable où placer les données lues par la commande,
aussi les données sont retournées. Une substitution de commande est
utilisée pour placer les données dans la variable "ligne1". Le
deuxième appel à gets
indique la variable où placer les données,
"ligne2". Dans ce cas, gets
retourne le nombre de caractère lut,
qui par substitution de commande est placé dans la variable
"long_ligne2". Une fois que toutes les données sont lues, le fichier
est fermé.
Dans ce cas, il était connu à l'avance que le fichier ne contenait que
deux lignes de données. Si la longueur du fichier n'est pas connue, la
commande eof
peut être utilisée avec une boucle while pour lire
les données jusqu'à ce que la fin du fichier soit atteinte.
Comme décrit en amont, Tcl utilise un mécanisme de décodage en une passe pour évaluer des scripts. Il est cependant parfois utile que l'interpréteur fasse plusieurs passes sur un script avant de l'évaluer. La possibilité de forcer l'interpréteur à décoder plus d'une fois un script permet de placer des scripts Tcl dans des variables, et de les interpréter plus tard. C'est le sujet de l'exemple 26 :
Exemple 26
set foo "set a 22" eval $foo puts $a
22
La variable "foo" est initialisée à la valeur "set a 22", qui est un
script Tcl. Ensuite, la valeur de la variable "foo" est substituée
dans la commande eval
. La commande eval
passe simplement ses
arguments à l'interpréteur Tcl pour une interprétation
supplémentaire. Lorsque l'interpréteur recontre le bloc "eval $foo",
le premier passage du décodage substitue simplement la valeur de la
variabe "foo" à la place de "$foo", ce qui donne l'expression "eval
set a 22". La commande eval
envoie ses arguments, "set a 22", à
l'interpréteur. Ce qui initialise la variable "a" à la valeur "22".
On peut penser que la commande eval
est superflue et simplement la remplacer par le bloc :
$foo
Cependant cela ne marche pas. Lorsque l'interpréteur rencontre le bloc "$foo", il le remplace simplement par la valeur de la variable "foo", et considère le décodage terminé. Aussi, "$foo" est remplacé par "set a 22" mais l'interpréteur n'évalue pas "set a 22", ce qui est nécessaire pour donner un sens au contenu de ce bloc (il doit réaliser que "set" correspond à la commande d'origine et qu'elle reçoit deux arguments, "a" et "22") et l'évaluer correctement.
Lorsqu'une erreur survient dans une commande Tcl, le script contenant la commande est arrêté et un message d'erreur s'affiche. Cependant, au lieu d'arrêter le script Tcl, il est préférable de simplement afficher un message d'erreur clair et de continuer l'exécution du script Tcl.
La commande catch
evite au système de gestion d'erreur de Tcl de
s'exécuter (et ainsi de stopper l'exécution lors d'une erreur) et
retourne simplement une valeur signifiante lorsqu'une erreur survient.
Cela permet au programme de définir son comportement lors d'une
erreur.
Exemple 27
set retval [catch {set f [open "pasdetelfichier" "r"]}] if{$retval == 1} { puts "Une erreur est apparue" }
Une erreur est apparue
La commande catch
reçoit comme argument un script Tcl. Elle
évalue ce script et si une erreur survient elle retourne 1, sinon 0.
Dans l'exemple 27, le script passé à catch
essaye d'ouvrir un
fichier nommé "pasdetelfichier". En supposant qu'un tel fichier
n'existe pas, la commande open
retourne une erreur. Comme
l'erreur survient dans un bloc catch
, le système de gestion
d'erreur de Tcl n'est pas invoqué, et la commande catch
retourne
simplement la valeur 1. Cette valeur de retour est assignée à la
variable "retval", qui est testée pour déterminer si une erreur est
apparue et eventuellement afficher un message d'erreur. La commande
catch
peut être utilisée de beaucoup d'autres façons, une seule a
été montrée ici. La manuel en ligne Tcl/Tk indique les autres.