SELFHTML/Quickbar  CGI/Perl  Éléments de langage Perl


Boucles et commandes de saut

Cette page est un document avec du texte et des informations

 Boucles avec while/until
 Boucles avec do..while/until
 Boucles avec for/foreach
 Commandes de saut en Perl

 

Boucles avec while/until

À l'aide de boucles while vous pouvez répéter des instructions de programme aussi longtemps que la condition formulée dans la boucle est remplie. Avec les boucles until vous pouvez répéter des instructions de programme jusqu'à ce que la condition formulée dans la boucle soit remplie.

Exemple1:

#!/usr/bin/perl

$i = 1;
print "d'abord la racine carrée de  1 à 10...\n\n";
while($i <= 10)
 {
  print "La racine carrée de ", $i, " est ", sqrt($i), "\n";
  $i++;
 }
$i = 1;
print "et maintenant le carré des nombres de  1 à 10...\n\n";
until($i > 10)
 {
  print "Le carré de  ", $i, " est ", $i * $i, "\n";
  $i++;
 }

Exemple2:

#!/usr/bin/perl

$fichieracces = "../../docs/access.log";
$acces = 0;
$succes = 0;
open(FICHIER, "<".$fichieracces) || "fichier non trouvé!\n";
 {
  while(<FICHIER>)
   {
    if(/HTTP\/1.0" 200/)  # rechercher d'après 'HTTP/1.0" 200' (= accès réussis)
     {
      $succes ++;
     }
    $acces ++;
   }
 }
print "De ", $acces,  $succes, " accès  ont réussi\n";

Explication:

Une boucle while (comme dans l'exemple 1 ci-dessus, première partie) commence avec le mot while (while = aussi longtemps que), suivi entre parenthèses accolades de la condition. Pour formuler une condition, vous avez besoin en règle générale d'  opérateurs de comparaison. Le contenu de la boucle est répété aussi longtemps que la condition de la boucle est vraie.

Une boucle until (comme dans l'exemple 1 ci-dessus, deuxième partie) commence avec le mot until (until = jusqu'a ce que). Il s'agit ici d'une autre formulation logique que pour while. Le contenu de la boucle est répété jusqu'à ce que la condition de la boucle soit vraie. À part ceci, les mêmes règles valent pour les boucles until que pour les boucles while. Veillez cependant à ce que la formulation de le condition de la boucle soit d'une logique absolue! Ainsi dans l'exemple, les conditions des boucles while($i <= 10) et until($i > 10) signifient-elles exactement la même chose.

L'exemple 2 ci-dessus montre un cas d'utilisation typique à Perl de la boucle avec while. Dans l'exemple, un fichier est lu ligne par ligne. Il s'agit d'un fichier log comme le crée un serveur WWW pour avoir la trace des accès. Dans ce cas spécial, il n'est pas besoin d'opérateur de comparaison pour la condition de la boucle. La boucle s'interrompt automatiquement quand toutes les lignes du fichier sont lues (à propos de cette règle voir aussi  lire et écrire des fichiers ainsi que, pour la recherche de chaînes de caractères, la partie  expressions régulières).

Dans les boucles, notez toujours les instructions dans des parenthèses accolades { et }, même si ce n'est qu'une seule instruction.

Attention:

Veillez, pour les boucles avec opérateurs de comparaison dans la condition de la boucle, qu'il y ait toujours au moins une possibilité pour mettre fin à la boucle après un temps raisonnable. Dans le cas contraire, vous créez une "boucle sans fin" qui peut mener à un "plantage" du système!

Pour éviter les boucles sans fin, vous avez besoin de quelque chose qui conduise à un moment quelconque à une sortie de la boucle. Fréquemment sont définis à cet effet des "compteurs" - dans l'exemple 1, la  variable scalaire simple $i. Cette variable scalaire simple a dans l'exemple une valeur initiale de 1, et est incrémentée à chaque passage dans la boucle de la valeur 1 par l'instruction $i++;, de telle sorte que la condition de la boucle sera remplie à un moment quelconque.

Une autre possibilité de contrôler et d'interrompre des boucles est proposée par les  commandes de saut.

 

Boucles avec do..while/until

Avec cette sorte de boucle, ce n'est pas la condition de la boucle qui est d'abord évaluée pour, d'après le résultat, exécuter un bloc d'instructions dans la boucle, mais c'est d'abord le bloc d'instructions qui est exécuté, à la suite de quoi la condition de la boucle est évaluée. La boucle est donc dans tous les cas exécutée au moins une fois, peu importe l'énoncé de la condition. Cela peut être judicieux si dans la condition de la boucle vous travaillez avec des variables dont vous ne connaissez pas la valeur exacte au départ de la boucle.

Exemple1:

#!/usr/bin/perl

$Nom = "Serge";
do
 {
  print $Nom, "\n";
  $Nom = "Virtuelle";
 }
while($Nom ne "Virtuelle")

Exemple2:

#!/usr/bin/perl

$Nom= "Serge";
do
 {
  print $Nom, "\n";
  $Nom= "Virtuelle";
 }
until($Nom eq "Virtuelle")

Explication:

Une boucle de ce type commence avec le mot clé do. Ensuite suit le bloc d'instructions de la boucle, placé comme d'habitude entre parenthèses accolades { et }. Après la parenthèse accolade de fermeture suit la condition de la boucle. La condition de la boucle peut être formulée avec while (aussi longtemps que) ou avec until (jusqu'à ce que). Ici entrent en vigueur les mêmes règles que pour les boucles avec while/until.

Attention:

Veillez aussi pour les boucles do..while/until à ne pas créer de boucles sans fin. Les deux exemples ci-dessus ont le même effet, à savoir la sortie une seule fois du nom "Serge". Les deux exemples ne se différencient que par la formulation de la condition de la boucle. Si dans ces deux exemples vous inversiez les  opérateurs de comparaison eq et ne, une boucle sans fin en résulterait dans les deux cas!

 

Boucles avec for/foreach

Les boucles avec for ou foreach se différencient des boucles avec while ou until en ce qu'elles prévoient déjà dans la condition de la boucle une condition d'interruption fixe. Pour cette raison, de telles boucles sont avant tout adéquates dans les cas où les valeurs initiale et finale sont d'emblée fixées.

Exemple1:

#!/usr/bin/perl

for($i=0;$i<=255;$i++)
 {
  printf("%4d = %2X",$i, $i);
  if($i % 8 == 0)
   { print "\n"; }
 }

Exemple2:

#!/usr/bin/perl

@Alphabet = (A..Z);
for(@Alphabet)
 {
  print $_, " est la ", $i+1, "ème lettre de l'alphabet \n";
  $i++;
 }

Exemple3:

#!/usr/bin/perl

foreach $i (1..100)
 {
  next if $i % 2 == 0;
  print $i, "\n" if $i % 3 == 0;
 }

Explication:

Une boucle for commence par le mot for, suivi entre parenthèses accolades de la formulation de la condition de la boucle. Pour les boucles for classiques, conformes à C, trois instructions sont notées dans la condition de la boucle. Dans la première instruction est défini et initialisé un compteur. Dans l'exemple 1, un compteur $i est défini et initialisé avec la valeur 0. La deuxième instruction contient la condition à partir de laquelle la boucle sera interrompue. Pour cela, vous avez besoin d'  opérateurs de comparaison. Dans la troisième instruction, le compteur de boucle est modifié de telle façon qu'il finira par remplir la condition notée dans la deuxième instruction. Dans l'exemple, $i est incrémenté de 1 à chaque passage de boucle, de sorte que sa valeur dépassera 255 à un moment ou à un autre et remplira ainsi la condition de la deuxième instruction.
L'exemple 1 utilise le compteur pour sortir à chaque boucle la valeur actuelle de $i sous sa forme hexadécimale. La requête if($i % 8 == 0) contient une division modulo et fait en sorte qu'après 8 sorties, une nouvelle ligne soit commencée. La sortie proprement dite a lieu à l'aide de la fonction printf (conforme à C), qui permet des sorties formatées proprement sur le périphérique de sortie standard. Cette fonction n'est en réalité pas très appropriée aux objectifs CGI (donc pour des sorties sous forme HTML).

L'exemple n°2 ci-dessus montre un cas Perl typique d'utilisation de la boucle for. Cette forme est très pratique pour traiter dans l'ordre l'un après l'autre les éléments d'une  liste ou d'un  hash. Dans l'exemple 2, une liste @Alphabet est définie avec toutes les majuscules de l'alphabet. Avec l'instruction for(@Alphabet), une boucle est fixée pour la liste. La boucle tournera automatiquement aussi souvent que la liste contient d'éléments. Pour adresser l'élément de la liste respectivement actif, la  variable prédéfinie $_ est employée dans la boucle. Dans cette variable est sauvegardé le contenu de l'élément de liste respectivement actuel.

Une autre construction Perl typique c'est la boucle avec foreach. Dans l'exemple n°3 ci-dessus, une telle boucle est mise en oeuvre. Dans ce type de boucle est défini comme condition de la boucle un passage sans équivoque, par exemple (de nombre..à nombre) ou des lettres (de lettre..à lettre). La boucle tournera automatiquement aussi souvent que tous les éléments du passage défini soient traités.
Si vous voulez mettre en place un compteur dans une boucle pour la procédure désirée, vous pouvez définir une variable compteur entre foreach et la condition de la boucle, comme dans l'exemple 3 ci-dessus la variable scalaire simple $i.
L'exemple ci-dessus sort tous les chiffres entre 1 et 100 qui sont impairs et divisibles par 3. Pour ceci, la  commande de saut next prête son aide.

 

Commandes de saut en Perl

Une opinion courante au sujet de Perl est que l'on ne peut pas programmer proprement de façon structurée avec. Certes, Perl met bien à disposition tout ce qui est nécessaire à une programmation structurée et même à une programmation orientée sur l'objet. Cependant, Perl est et reste un langage pour les scripts, dont les programmeurs ne se donnent souvent pas la peine de partager le déroulement en  sous-programmes distincts. Une alternative à la programmation structurée utilisée fréquemment est constituée par les commandes de saut à un autre endroit au choix dans le programme. Même à l'intérieur de boucles, les commandes de saut sont très appréciées, pour forcer par exemple le passage à la boucle suivante ou pour interrompre une boucle.

Exemple1:

#!/usr/bin/perl

# Devinez donc quel est le nombre donné par $i à la fin comme résultat

$i = 1;
goto resultat;
while($i < 1000)
 {
  ++$i;
  if($i % 3 == 0)
   {
    redo;
   }
  elsif($i % 7 == 0)
   {
    next;
   }
  elsif($i % 13 == 0)
   {
    last;
   }
 }
resultat:
print "resultat: ", $i;

Exemple2:

#!/usr/bin/perl

while($i < 10)
 {
  ++$i;
  if($i % 2 != 0)
   {
    redo;
   }
 }
continue
 {
   print $i, "\n";
 }

Explication:

Les commandes de saut suivantes sont disponibles en Perl:

goto saute à un autre endroit au choix dans le programme. Cet endroit doit cependant recevoir à cet effet une "étiquette" (comparable à une ancre dans un fichier HTML). Vous définissez une telle étiquette en notant un nom suivi de deux points. Dans l'exemple ci-dessus, est défini dans l'avant dernière ligne une étiquette nommée resultat:. Avec une commande goto comme au début de l'exemple, vous pouvez faire un saut à une telle étiquette.

redo est conçu pour une utilisation dans des boucles. Le parcours actuel de la boucle est interrompu. Le prochain parcours de boucle est lancé sans toutefois réévaluer la condition de la boucle. Si donc vous avez par exemple un compteur dans la condition de la boucle, La boucle redémarrera avec redo sans incrémenter le compteur.

next est également conçu pour l'emploi dans des boucles. Le parcours actuel de la boucle est interrompu. Le prochain parcours de boucle est lancé en évaluant la condition de la boucle.

last interrompt immédiatement une boucle.

continue est un cas spécial en Perl et se traite différemment qu'en C par exemple. L'exemple 2 ci-dessus montre un exemple d'utilisation typique. continue introduit un bloc d'instructions distinct, exactement comme une boucle. Dans ce bloc d'instructions, marqué comme d'habitude avec des parenthèses accolades { et }, vous pouvez noter des instructions de votre choix. Quand un tel bloc continue se trouve immédiatement derrière le bloc d'une boucle, il sera exécuté avec chaque passage de boucle. Avec une commande de saut comme redo dans le bloc d'instructions de la boucle, vous pouvez empêcher que le bloc continue soit exécuté. Dans l'exemple 2, on obtient avec cette construction que tous les chiffres pairs entre 1 et 10 soient sortis.

après: Opérateurs
avant: Instructions conditionnelles
 

SELFHTML/Quickbar  CGI/Perl  Éléments de langage Perl

© 1998 Stefan Münz / © 2001 Traduction  Serge François, 13405@free.fr