![]() |
Commandes de saut |
|
|
|
| | |
La commande de saut goto, qui permet de sauter à un autre endroit de son choix pouvant être déterminé dans le script au cours de son exécution, est marquée depuis longtemps au fer comme étant caractéristique d'une mauvaise programmation et de programmeurs de code décousu. Elle peut être aussi évitée en temps normal par des
boucles programmées correctement ou bien par des
instructions conditionnelles bien structurées.
#!/usr/bin/perl -w use strict; use CGI::Carp qw(fatalsToBrowser); print "Content-type: text/html\n\n"; print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n"; print "<html><head><title>Sortie du test</title>\n"; print "</head><body>\n"; print "<h1>Bonjour utilisateur</h1>\n"; goto MESSAGE; ENCOURAGEMENT: print "<p>Il fait si beau que l'on pourrait organiser quelque chose</p>"; goto FIN; MESSAGE: print "<p>Ce service n'est pas disponible pour l'instant</p>\n"; goto ENCOURAGEMENT; FIN: print "</body></html>\n"; |
Le script renvoie du code HTML au navigateur appelant. Pour trouver dans quel ordre les instructions print sont sorties, vous devez suivre les instructions goto. À chaque instruction goto est mentionnée une marque de saut, ce qu'on appelle une étiquette. Ce sont dans l'exemple, les noms écrits en majuscules. Sous ce nom on doit retrouver l'étiquette quelque part dans le script et ce, seule sur une ligne et suivie de deux points. Au dessous se poursuit alors l'exécution du script quand l'étiquette est atteinte.
|
|
La commande de saut next est conçue pour être employée dans des boucles. Le parcours actuel de la boucle est interrompu. La boucle suivante est lancée après une nouvelle évaluation de la condition de la boucle.
#!/usr/bin/perl -w
use strict;
use CGI::Carp qw(fatalsToBrowser);
print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Sortie du test</title>\n";
print "</head><body>\n";
my $clef;
my $valeur;
while (($clef, $valeur) = each(%ENV)) {
next unless $clef =~ /^HTTP_.*/;
print "<b>$clef</b> a la valeur <b>$valeur</b><br>\n";
}
print "</body></html>\n";
|
Le script en exemple sort dans le navigateur les
variables d'environnement CGI , seulement celles cependant qui commencent par HTTP_. Pour ce faire, le script lit le Hash
prédéfini %ENV dans une
boucle pour les hashes. Avec next et une
condition placée après ainsi qu'une
expression régulière correspondante /^HTTP_.*/ comme condition, qui est niée avec unless, l'instruction obtient que la commande print qui suit, ne soit pas interprétée, quand la variable d'environnement actuelle ne commence pas par HTTP_. De cette façon, ne seront donc sorties que les variables pour lesquelles c'est le cas.
|
|
continue - n'appartient pas aux commandes de saut au sens strict du terme, mais leur est étroitement apparenté étant donné que continue est atteint par un saut. Le mot clé introduit un bloc d'instructions distinct. À l'intérieur de ce bloc d'instructions qui est marqué comme d'habitude avec des parenthèses accolades { et }, vous pouvez noter des instructions de votre choix. Quand un tel bloc continue figure immédiatement derrière un bloc de boucle, il est exécuté à chaque exécution de la boucle et ensuite (excepté pour la toute première exécution de la boucle) exécuté directement avant la vérification de la condition de la boucle.
#!/usr/bin/perl -w
use strict;
use CGI::Carp qw(fatalsToBrowser);
print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Sortie du test</title>\n";
print "</head><body>\n";
my $i = 1;
while($i <= 100) {
next if ($i % 7 != 0);
print "$i est divisible par 7 <br>\n";
}
continue {
$i++;
}
print "</body></html>\n";
|
L'exemple sort dans le navigateur appelant tous les chiffres entre 1 et 100 qui sont divisibles par 7. Ici est utilisée une boucle while dont la condition demande si $i est plus petit ou égal à 100. Étant donné que $i est initialisé avec 1, le bloc de la boucle est donc atteint. $i n'est cependant pas incrémenté à l'intérieur du bloc de la boucle, cela conduirait à une désespérante boucle sans fin. Dans l'exemple le bloc continue placé après la parenthèse accolade de fermeture du bloc de la boucle sert à cela . À l'intérieur du bloc continue, $i est incrémenté.
À l'intérieur de la boucle, il est demandé avec la condition $i % 7 != 0, si la valeur actuelle de $i divisée par 7 a un reste égal à 0 (voir division modulo dans les
opérateurs de calcul). Par next est aussitôt lancé le passage de boucle suivant, si le nombre n'est pas divisible par 7 sans donner de reste, toutefois l'instruction du bloc continue est encore exécutée quelque soit le cas.
|
|
La commande de saut last interrompt immédiatement une boucle.
#!/usr/bin/perl -w
use strict;
use CGI::Carp qw(fatalsToBrowser);
print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Sortie du test</title>\n";
print "</head><body>\n";
while(1) {
my $maintenant = time;
print "$maintenant \n";
last if ($maintenant % 2 == 0);
}
print "</body></html>\n";
|
Le script en exemple recherche avec la fonction
time, à l'intérieur d'une boucle sans fin classique formulée avec while(1) ("La condition est toujours vraie"), la valeur du temps actuelle en secondes et la sauvegarde dans la scalaire $maintenant. Avec la condition $i % 2 == 0 il est demandé si la valeur actuelle de $maintenant divisée a un reste égal à 0 (voir division modulo dans les
opérateurs de calcul). Si la condition placée après l'instruction if est remplie, la commande last qui précède est exécutée. La boucle est alors interrompue. Au cas où le script est appelé à un moment où la valeur des secondes est impaire, la valeur actuelle des secondes est sortie jusqu'à ce que time renvoie la valeur des secondes immédiatement supérieure.
|
|
La commande de saut redo répète simplement encore une fois le parcours de la boucle actuelle. Pour cette répétition, la valeur de la boucle n'est pas évaluée encore une fois.
Ceci est \ un fichier avec une convention. une barre oblique inversée à la fin \ d'une ligne signifie: \ une nouvelle ligne! |
#!/usr/bin/perl -w
use strict;
use CGI::Carp qw(fatalsToBrowser);
open(FH,"<texte.txt");
my @lignes;
while(<FH>) {
chomp;
if(s/\\$//) {
$_ .= <FH>;
redo unless(eof(FH));
}
push(@lignes,$_."\n");
}
close(FH);
print "Content-type: text/html\n\n";
print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">', "\n";
print "<html><head><title>Sortie du test</title>\n";
print "</head><body><pre>\n";
print @lignes;
print "</pre></body></html>\n";
|
L'exemple montre une utilisation classique de redo. Il s'agit ici de regrouper plusieurs lignes sur la base d'une convention en une seule. Le fichier texte qui précède contient bien cinq lignes, mais à la fin doivent en résulter deux lignes seulement. Les lignes qui se terminent par une barre oblique inversée, doivent de poursuivre sur la ligne suivante.
Le script ouvre le fichier texte avec la fonction
open. Dans une boucle while il lit à chaque fois la ligne suivante du fichier. La condition de la boucle est ici <FH>. Cela signifie: portion suivante du fichier lié au descripteur de fichier FH et cela dans le contexte scalaire. Dans ce contexte la ligne suivante du fichier est alors livrée.
À l'intérieur de la boucle, le signe final de passage à la ligne de la ligne actuelle est retiré avec la fonction
chomp . Ensuite on recherche et remplace avec l'
expression régulière s/\\$// une barre oblique inversée éventuellement présente à la fin de la ligne. Dans le cas où une barre oblique inversée a effectivement été trouvée et remplacée, la condition pour le if est vraie, et le bloc d'instructions qui en dépend est exécuté. Dans ce bloc la ligne suivante est lue avec $_ .= <FH>; et elle est accrochée à la ligne actuelle. Ici est utilisée la
variable prédéfinie $_ et l'
opérateur pour concaténer des chaînes de caractères (.). Enfin, il est sauté à nouveau au début de la boucle avec redo, dans la mesure où n'est pas (unless) atteinte la fin du fichier (
eof).
redo fait en sorte que la condition de la boucle ne soit pas réévaluée. Aucune ligne suivante n'est donc lue. La variable $_, à laquelle se réfèrent tant l'instruction chomp; que l'expression régulière, s'est déjà vu affecter une nouvelle valeur à l'intérieur du bloc if. Pour la compréhension: avec chomp; on veut dire quelque chose comme: chomp($_);, et avec if(s/\\$//) quelque chose comme: if($_ =~ s/\\$//). Aussi bien le retrait du passage à ligne que l'évaluation de la présence d'une barre oblique inversée qui la termine, se réfèrent donc implicitement à la variable prédéfinie $_.
Quant dans l'exemple la condition if n'est plus vraie, le script aboutit là où la ligne actuelle est ajoutée dans le tableau @lignes avec la fonction
push. N'y sont sauvegardées à la fin que les deux lignes du fichier qui doivent rester par convention. Le script sort le contenu de @lignes à la fin, dans le navigateur appelant.
|
| |
© 2001 Stefan Münz / © 2003 Traduction
Serge François, 13405@free.fr
selfhtml@fr.selfhtml.org