%%  Format et mise en page 

\def\presentation{
\voffset -.50in  \hoffset -.19in
\oddsidemargin 0in \evensidemargin 0in
\marginparwidth .75in \marginparsep 7pt \topmargin 0in
\headheight 12pt \headsep .25in
\footheight 18pt \footskip .35in
\textheight 9.5in \textwidth 6.5in
\columnsep 10pt \columnseprule 0pt }

\def\program#1{{\it{#1}}}
\def\programwithlink#1#2{{\it{{#1}/{#2}}}}
\def\href#1#2{#1\footnote{#2}}
\def\option#1{-#1}
\def\longoption#1{- -#1}
\def\filename#1{{\bf{#1}}}
\def\filepath#1{{\bf{#1}}}

\def\bookref#1{{\it{#1}}}
\def\errormessage#1{{\it{#1}}}
\def\directoryname#1{{\it{#1}}}
\def\command#1{{\it{#1}}}
\def\codeline#1{{\it{#1}}}
\def\function#1{{\it{#1}}}
\def\alert#1{{\bf{#1}}}
\def\commandarray#1{\begin{center}{\it{#1}}\end{center}}
\def\paperwithlink#1#2{{\it{#1}}}
\def\equline#1{\begin{math}#1\end{math}}

\documentclass[a4paper,11pt,twoside,openright]{book}
\voffset -.50in  \hoffset -.19in
\oddsidemargin 0in \evensidemargin 0in
\marginparwidth .75in \marginparsep 7pt \topmargin 0in
\headheight 12pt \headsep .25in
\textheight 9.5in \textwidth 6.5in
\columnsep 10pt \columnseprule 0pt 

\usepackage[francais]{babel}
\usepackage[french]{minitoc}
\usepackage{longtable}

\begin{document}


\setcounter{chapter}{2}

\chapter{Les tableaux}

\section{G\'en\'eralit\'es}

Les tableaux en PERL sont identifi\'es par le symbole @ \`a l'image du {\textdollar} pour les 
variables. Comme ces derni\`eres, les tableaux ne sont pas typ\'es et un m\^eme tableau peut m\'elanger 
des \'el\'ements de diff\'erents types. Comme en C, le plus petit indice 
d'un tableau est l'indice 0. Il n'est par contre pas n\'ecessaire de d\'eclarer la taille 
d'un tableau avant son utilisation. 

Le petit programme suivant va servir \`a illustrer notre propos.

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&\#!/usr/bin/perl\\
2.&\\
3.&@particule = ("photon", "boson", 0, 0, 1);\\
4.&print ("nom : ".{\textdollar}particule[0]."{\textbackslash}n");\\
5.&print ("statistique : ".{\textdollar}particule[1]."{\textbackslash}n");\\ 
6.&print ("masse : ".{\textdollar}particule[2]." MeV{\textbackslash}n");\\
7.&print ("charge : ".{\textdollar}particule[3]."{\textbackslash}n");\\
8.&print ("spin :".{\textdollar}particule[4]."{\textbackslash}n");\\
\hline
\end{longtable}
\end{center}


La ligne 3 cr\'ee un tableau appel\'e particule. Pour initialiser ce dernier 
nous avons choisi une des techniques possibles qui consiste \`a lui affecter une liste 
d'\'el\'ements. La liste est d\'efinie entre parenth\`eses et chaque \'el\'ement est s\'epar\'e 
du suivant par une virgule.

Les choses se compliquent dans les lignes suivantes. En effet, pour acc\'eder \`a l'un des 
\'el\'ements, la syntaxe n'est pas \'evidente. L'indice de l'\'el\'ement auquel nous souhaitons acc\'eder est ajout\'e entre crochets \`a la fin du nom du tableau (comme dans les langages ayant une syntaxe proche du C). En revanche le symbole @ est devenu {\textdollar}. La logique de ce changement se comprend par le fait que nous ne manipulons plus le tableau  mais seulement un \'el\'ement, soit une variable. Cette subtilit\'e est la seule difficult\'e li\'ee \`a la manipulation des tableaux. 

Nous avons vu comment remplir un tableau en lui affectant une liste. Nous citerons deux autres m\'ethodes. La plus \'evidente est l'affectation \'el\'ement par \'el\'ement:\\

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&{\textdollar}particule[0] = "photon";\\
2.&{\textdollar}particule[1] = "bosons";\\
\hline
\end{longtable}
\end{center}


L'autre technique consiste \`a ajouter un \'el\'ement \`a la fin du tableau gr\^ace \`a l'instruction \function{push}:\\

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&push (@particule, "photon");\\
2.&push (@particule, "boson");\\
\hline
\end{longtable}
\end{center}

 


\section{Parcourir un tableau}


Si nous vous posions la question de la technique \`a employer pour parcourir successivement tous les \'el\'ements d'un tableau (du premier au dernier \'el\'ement sans saut), l'id\'ee qui vous viendrait imm\'ediatement \`a l'esprit est d'avoir une variable allant de 0 au dernier indice du tableau. C'est effectivement une des techniques possibles:\\

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&\#!/usr/bin/perl\\
2.&\\
3.&@energies = (1, 4, 9, 16, 25, 36, 49, 64);\\
4.&{\textdollar}i = 0;\\
5.&while ({\textdollar}i {\textless} 8)\\
6.&\hspace{0.25cm}\{\\
7.&\hspace{0.5cm}print ("energie ".{\textdollar}i.": ".{\textdollar}energies[{\textdollar}i]."{\textbackslash}n");\\
8.&\hspace{0.5cm}{\textdollar}i++;\\
9.&\hspace{0.25cm}\}\\
\hline
\end{longtable}
\end{center}


A priori, le nombre d'\'el\'ements dans le tableau n'est pas connu au moment o\`u nous \'ecrivons le programme. La ligne 5 est particuli\`ere au cas que nous traitons. En toute g\'en\'eralit\'e, nous pouvons conna\^itre \`a tout instant le nombre d'\'el\'ements dans un tableau gr\^ace \`a la syntaxe \codeline{{\textdollar}\#nom\_du\_tableau}. Ainsi il serait judicieux de r\'e\'ecrire la ligne 5 comme \codeline{while ({\textdollar}i {\textless}= {\textdollar}\#energies)}.

Il existe une autre technique, plus simple, pour parcourir un tableau. Ceci se fait gr\^ace \`a l'instruction \function{foreach}\\

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&\#!/usr/bin/perl\\
2.&\\
3.&@energies = (1, 4, 9, 16, 25, 36, 49, 64);\\
4.&foreach {\textdollar}valeur (@energies)\\
5.&\hspace{0.25cm}\{\\
6.&\hspace{0.5cm}print ({\textdollar}valeur."{\textbackslash}n");\\
7.&\hspace{0.25cm}\}\\ 
\hline
\end{longtable}
\end{center}


A chaque it\'eration, \function{foreach} affecte \`a la variable (ici \codeline{{\textdollar}valeur}) la valeur suivante du tableau dont le nom est indiqu\'e entre parenth\`eses. \function{foreach} poss\`ede un seul d\'efaut. Il n'est pas possible d'imbriquer un \function{foreach} dans un \function{foreach} d'un m\^eme tableau. PERL n'indiquera aucune erreur de syntaxe mais le programme n'aura pas le r\'esultat escompt\'e.



\section{Trier les tableaux}

Les tableaux peuvent \^etre tri\'es gr\^ace \`a la commande \function{sort}. Cette commande est extr\^emement puissante et nous ne donnerons ici que son utilisation de base, renvoyant le lecteur au chapitre 15 de [1]  ou aux pages man (man perlfunc ou man perlfaq4).

Pour un tableau nomm\'e \codeline{@tableau}, \codeline{sort (@tableau)} renvoie un tableau tri\'e par ordre croissant des \'el\'ements de \codeline{@tableau}, les \'el\'ements \'etant compar\'es entre eux par les techniques de comparaison entre cha\^ines de caract\`eres. Regardons le programme suivant:\\

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&\#!/usr/bin/perl\\
2.&\\
3.&@particules = ("photon","electron","proton","neutron","muon","pion");\\
4.&@particulestriees = sort (@particules);\\
5.&foreach {\textdollar}tmp (@particulestriees)\\
6.&\hspace{0.25cm}\{\\
7.&\hspace{0.5cm}print ({\textdollar}tmp." ");\\
8.&\hspace{0.25cm}\}\\
9.&print ("{\textbackslash}n");\\
\hline
\end{longtable}
\end{center}

  
Cette technique est certes int\'eressante, mais en physique, nous aurons plus souvent affaire \`a des nombres et nous avons vu que trier des nombres comme des cha\^ines de caract\`eres n'est pas une tr\`es bonne id\'ee. Pour trier un tableau de nombre, il faut proc\'eder comme suit

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&sort \{{\textdollar}a {\textless}={\textgreater} {\textdollar}b\} (@tableau);\\
\hline
\end{longtable}
\end{center}


Ce qu'il y a entre accolades et qui est situ\'e entre l'instruction \function{sort} et le tableau \`a trier n'est ni plus ni moins qu'une petite fonction qui d\'ecrit comment comparer deux \'el\'ements \codeline{{\textdollar}a} et \codeline{{\textdollar}b} (ces noms de variables sont impos\'es par PERL pour une fonction de comparaison). La puissance de la fonction \function{sort} r\'eside dans la possibilit\'e de d\'efinir cette fonction. Pour ceux qui se poseraient la question, le symbole \codeline{{\textless}={\textgreater}} est en fait un raccourci d\'esignant la fonction qui compare deux \'el\'ements et qui retourne -1 si le premier est plus petit que le deuxi\`eme, 0 s'ils sont \'egaux et 1 sinon. 

L'int\'er\^et de cette technique va vous appara\^{\i}tre imm\'ediatement si vous devez trier le tableau dans l'ordre d\'ecroissant. Il vous suffit pour cela d'inverser codeline{{\textdollar}a} et \codeline{{\textdollar}b} dans la fonction de tri. Mais vous pouvez faire bien plus!


(N.B.: le reste de cette section peut \^etre r\'eserv\'ee \`a une seconde lecture).

Si vous devez trier les \'el\'ements d'un tableau par rapport \`a un autre, il y a plusieurs m\'ethodes possibles. Nous en d\'ecrirons une qui n'est certes pas la plus rapide mais qui a le m\'erite de laisser entrevoir les possibilit\'es offertes par le fait que la fonction de comparaison soit red\'efinissable.\\

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&\#!/usr/bin/perl\\
2.&\\
3.&@masses = (938.3, 939.6, 0.511);\\
4.&@noms = ("proton", "neutron", "electron");\\
5.&@indices = (0, 1, 2);\\
6.&@indicestries = sort \{{\textdollar}masses[{\textdollar}a] {\textless}={\textgreater} {\textdollar}masses[{\textdollar}b]\} (@indices);\\
7.&foreach {\textdollar}tmp (@indicestries)\\
8.&\hspace{0.25cm}\{\\
9.&\hspace{0.5cm}print ({\textdollar}noms[{\textdollar}tmp]." (".{\textdollar}masses[{\textdollar}tmp]." MeV){\textbackslash}n");\\
10.&\hspace{0.25cm}\}\\
\hline
\end{longtable}
\end{center}


L'id\'ee qui est employ\'ee dans ce programme est de cr\'eer un tableau contenant un indice associ\'e \`a chaque particule (ligne 5). A la ligne 6, nous trions ce tableau non pas en comparant les \'el\'ements mais les masses associ\'ees \`a chacun de ces indices. Le tri s'effectue donc en comparant les masses, mais c'est bien le tableau d'indices qui est tri\'e. Une fois le tableau d'indices tri\'e, nous nous en servons pour afficher dans l'ordre croissant des masses les noms des particules.
   


\section{Les tableaux associatifs: les tables de hash}


(N.B.: cette section peut \^etre r\'eserv\'ee \`a une seconde lecture)

En r\`egle g\'en\'erale, nous avons l'habitude de manipuler des tableaux \`a l'aide d'indices entiers positifs (strictement ou non suivant les langages). Pourtant, il peut s'av\'erer qu'une indexation par des cha\^{\i}nes de caract\`eres pourait \^etre beaucoup plus pratique. Si nous reprenons l'exemple des particules et de leur masse, il serait pratique d'indexer par rapport au nom. Les tables de hash sont l\`a pour combler cette lacune. Regardons l'exemple suivant:

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&\#!/usr/bin/perl\\
2.&\\
3.&{\textdollar}particules\{"proton"\} = 938.3;\\
4.&{\textdollar}particules\{"neutron"\} = 939.6;\\
5.&{\textdollar}particules\{"electron"\} = 0.511;\\
6.&while (({\textdollar}nom, {\textdollar}masse) = each(\%particules))\\
7.&\hspace{0.25cm}\{\\
8.&\hspace{0.5cm}print ({\textdollar}nom." (".{\textdollar}masse." MeV){\textbackslash}n");\\
9.&\hspace{0.25cm}\}\\
\hline
\end{longtable}
\end{center}


Le symbole qui d\'efinit la table de hash est le pourcent \codeline{\%}. Pour acc\'eder aux \'el\'ements d'une table de hash, ce symbole devient un \codeline{{\textdollar}} comme c'est le cas pour un tableau \`a la seule diff\'erence que l'indice est indiqu\'e entre accolades et non entre crochets. Ainsi, ligne 3, 4 et 5, nous affectons \`a la table de hash \codeline{\%particules} les diff\'erentes masses en se servant des noms des particules comme indices. Pour parcourir la table de hash, nous utilisons la fonction \function{each}. Cette derni\`ere prend comme argument la table de hash et retourne au fur et \`a mesure l'indice (appel\'e g\'en\'eralement cl\'e pour une table de hash) et la valeur correspondante dans un tableau \`a deux \'el\'ements. C'est ce que nous faisons ligne 6. Le tableau retourn\'e par \function{each} est r\'ecup\'er\'e dans \codeline{({\textdollar}nom, {\textdollar}masse)} qui permet d'affecter la cl\'e \`a \codeline{{\textdollar}nom} et la valeur \`a \codeline{{\textdollar}masse}. Notez qu'en incluant cette affectation dans un \function{while} comme nous l'avons fait, cela permet de faire une boucle jusqu'\`a ce que tous les \'el\'ements aient \'et\'e it\'er\'es.

Si vous ex\'ecutez le programme, vous allez obtenir un affichage du type:

\begin{center}\begin{longtable}{|rl|}
\hline
&{\it neutron (939.6 MeV)}\\
&{\it proton (938.3 MeV)}\\
&{\it electron (0.511 MeV)}\\
\hline
\end{longtable}
\end{center}


Comme vous pouvez le constater, l'ordre dans lequel nous avons rentr\'e les \'el\'ements n'est pas celui dans lequel ils apparaissent. PERL ordonne les \'el\'ements de la table de hash de la fa\c{c}on optimale pour lui d'effectuer une recherche. Ne pr\'esupposez donc jamais de l'ordre des \'el\'ements d'une table de hash. 

Pour terminer ce rapide tour d'horizon des tables de hash, signalons deux commandes utiles \function{keys} et \function{value} qui permettent de r\'ecup\'erer dans un tableau respectivement les cl\'es et les valeurs d'une table de hash.



\section{Tableaux r\'eserv\'es}


(N.B.: cette section peut \^etre r\'eserv\'ee \`a une seconde lecture)

A l'image des variables r\'eserv\'ees, il existe un certain nombre de tableaux et tables de hash r\'eserv\'es en PERL. En voici la liste exhaustive:\\

\codeline{@\_, @ARGV, @LAST\_MATCH\_END, @+, @LAST\_MATCH\_START, @-, @F, @INC, \%INC, \%ENV, \%SIG}\\

Pour le d\'etail de ces tableaux, nous vous invitons \`a consulter la page man perlvar. 

Nous regarderons plus particuli\`erement deux de ces tableaux. Il y a tout d'abord le tableau par d\'efaut \codeline{@\_}. Il s'agit du pendant de la variable par d\'efaut pour les tableaux et s'utilise de la m\^eme mani\`ere. Le petit programme suivant vous montre l'utilisation du tableau par d\'efaut:\\

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&\#!/usr/bin/perl\\
2.&\\
3.&@\_ = ("proton","neutron","electron");\\
4.&foreach ()\\
5.&\hspace{0.25cm}\{\\
6.&\hspace{0.5cm}print ({\textdollar}\_."{\textbackslash}n");\\
7.&\hspace{0.25cm}\}\\
\hline
\end{longtable}
\end{center}
 

Le deuxi\`eme tableau, beaucoup plus int\'eressant, est \codeline{@ARGV}. Lorsque vous tapez une ligne de commande, vous pouvez ajouter des arguments g\'en\'eralement s\'epar\'es par un espace. Chacun de ces arguments est pass\'e au programme via le tableau \codeline{@ARGV}. Le petit programme suivant va vous montrer le fonctionnement de \codeline{@ARGV}:\\

\begin{center}
\begin{longtable}{|rl|}
\hline
1.&\#!/usr/bin/perl\\
2.&\\
3.&foreach {\textdollar}argument (@ARGV)\\
4.&\hspace{0.25cm}\{\\
5.&\hspace{0.5cm}print ({\textdollar}argument."{\textbackslash}n");\\
6.&\hspace{0.25cm}\}\\
\hline
\end{longtable}
\end{center}
    

Maintenant rendez ex\'ecutable votre script (que nous appelerons \filename{argument.pl}) et ex\'ecutez le avec une liste d'arguments comme \command{./argument.pl essai 1 3.14}. Le programme affiche \`a la suite chaque argument.

Cette technique est tr\`es utile et vous permet d'\'eviter d'\'ecrire en dur dans le script certains param\`etres susceptibles d'\^etre chang\'es entre deux ex\'ecutions sans utiliser \codeline{{\textless}STDIN{\textgreater}}, la sortie standard n'\'etant pas forc\'ement la m\'ethode la plus adapt\'ee pour scripter vos scripts, c'est-\'a-dire appeler vos scripts depuis un autre (ce qui pourrait passer pour du vice mais qui se r\'ev\`ele parfois pratique).


\section{Exercices}


\begin{itemize}
\item Cr\'eez un tableau de nombres al\'eatoires dont la taille sera pass\'ee comme premier argument. Puis cherchez le minimum et le maximum par deux m\'ethodes: une rapide \`a ex\'ecuter et une autre plus lente mais s'\'ecrivant de la mani\`ere la plus compacte possible.
\item Reprendre l'exemple du tri  crois\'e mais utilisez cette fois une table de hash pour r\'eduire la taille du code et ne pas passer par un tableau d'indices.
\end{itemize}




\end{document}


