Variables, commentaires et syntaxe

 
Un script commence toujours par #!/usr/bin/perl   Ce repère particulier indique où se trouve l'interpréteur perl.
Les instructions se terminent obligatoirement par un ; (point-virgule)   Néanmoins on peut l'omettre sur la dernière instruction d'un bloc. La recommandation est d'en mettre un dans tous les cas.
On peut mélanger minuscules et majuscules dans les noms de variables, mais une variable en minuscules est différente de la même en majuscules   $MONTANT n'est pas la même variable que $montant ni que $MoNtAnT elle-même différente de $Montant.
On dit que les noms de variables sont sensibles à la casse.
Un nom de variable commence par un caractère qui caractérise le type de donnée :
  • $ scalaire (zone simple numérique ou alphanum)
  • @ matrice ou tableau (array en anglais)
  • % tableau associatif ou "hash" (on détaillera plus tard)
  $un $nom @liste %table

Attention : les éléments d'un tableau sont des scalaires. Par exemple les éléments du tableau @liste se notent $liste[0], $liste[1], etc... Eh oui! La numérotation des éléments d'un tableau commence à 0 et non pas à 1
Un nom de variable est limité à 255 en longueur et peut contenir :
  • Un premier caractère significatif du type de donnée
  • Des minuscules et/ou des majuscules
  • Des chiffres
  • Le caractère souligné _ (underscore)
Pourquoi 255 ? C'est la valeur maximum que peut prendre un octet lorsque tous ses bits sont à 1.
On peut donc raisonnablement penser que c'est parce que le descripteur interne de longueur de la variable est défini sur un octet. Si tu trouves que c'est pas suffisant essaye de bosser avec des noms de cette longueur tu m'en diras des nouvelles !
  $ville
@TABLE_type
$Variable_A_Nom_Long
Quelques noms de variables ne jouent pas le jeu, ils sont prédéfinis. Ils ont en général deux ou trois caractères (type compris) et utilisent les signes. Par exemple :
$]    numéro de version de perl.
$^T heure à laquelle le script a démarré. Exprimé en secondes depuis le 01/01/1970
Un commentaire commence au caractère # et s'étend jusqu'à la fin de la ligne   La première ligne #!/usr/bin/perl est bien un commentaire. C'est un cas particulier réservé à UNIX. Sous UNIX lorsqu'un utilisateur demande au noyau d'exécuter un fichier en mode texte, le noyau va regarder si la première ligne ne commence pas par : #! et si c'est le cas, exécute le programme qui se trouve après avec comme premier argument le script.
On peut mettre plus d'une instruction par ligne   Séparées bien sûr par un ; (point-virgule)
Une instruction peut s'étendre sur plusieurs lignes   Jusqu'au ; (point-virgule) de clôture de l'instruction
Un bloc d'instructions se définit entre accolades {} (brackets)   {$a=$a+1;
 $flag='OUI';}
Une chaine de caractères s'écrit entre ' ' (apostrophes on dit également quotes) ou entre " " (guillemets)
  • Entre quotes ' ' les variables ne sont pas interprétées
  • Entre guillemets " " les variables sont interprétées (on leur substitue leur contenu)
  Dans le cas des chaînes entre guillemets " " il y d'autres substitutions qui interviennent. Par exemple \n sera remplacé par un saut de ligne.


Hello World! - Le premier programme

 
Traditionnellement il semble que le premier programme que l'on écrive et l'on fasse tourner soit celui-ci. Alors ne faisons ni faux-bond ni attendre la tradition.  
#!usr/bin/perl
print "Hello world!\n";
Pour le mettre en oeuvre :
  • Crée le fichier hello.pl et met-y le petit chef-d'oeuvre
  • Ouvre une fenêtre DOS
  • Place toi dans le répertoire contenant hello.pl
    (commande DOS cd \rep1\rep2...)
  • Tape perl hello.pl
  • Admire...
  Remarque l'utilisation des " " pour permettre le remplacement de \n (saut de ligne).

Essaye de remplacer les " " par des ' ' puis tu reviens aux " " et tu supprimes \n



Données scalaires - Chaînes de caractères

 
Pourquoi scalaires ? Pour bien exprimer que ce sont des données qui contiennent des entitées réelles et uniques qui seront manipulées par le langage. Attention un tableau n'est pas une donnée scalaire mais il contient des données scalaires.  
  • Un nombre est un scalaire. Par exemple 24 ou bien 104.5
  • Une chaîne de caractère est un scalaire : 'Monsieur Dupond'
  • Le retour chariot est une donnée scalaire : "\r"
  • Une variable scalaire commence par le signe $
  Tu auras remarqué l'utilisation des ' ' et des " "
L'association \r n'est pas la seule. Il en existe de nombreuses. Voici les principales :
  • \n Nouvelle ligne (LF=Line Feed ou NL=New Line))
  • \r Retour chariot (CR=Carriage Return)
  • \t Tabulation (HT, TAB)
  • \f Saut de page (FF=Form Feed)
  • \b Retour arriere (Backspace)
  • \a Bip (BEL)
  • \e Escape (ESC)
  • \007 Toute valeur ASCII octale (07=Bip)
  • \x7f Toute valeur ASCII hexadecimale (7f=delete)
  • \l Convertit la lettre suivante en minuscule (l=low)
  • \u Convertit la lettre suivante en majuscule (u=upper)
  • \L Convertit les lettres suivantes en minuscule jusqu'à \E
  • \U Convertit les lettres suivantes en majuscule jusqu'à \E
 



Par exemple
$n="\u\LduPONt\E";
print "$n\n"; # Dupont
Nota: La barre \ quand elle n'a pas de signification particulière protège le caractère qui suit et lui confère sa propre valeur.
On peut donc protéger des caractères tels que $ ou \
  $a=64;
print "\$a\n"; --> $a
print  "$a\n"; --> 64


A ton avis comment imprimer \ ?
print "\\\n";
Gagné !

Une chaîne vide se note "" ou ''.

Une donnée scalaire est interprétée comme vraie (True) au sens booléen si ce n'est pas une chaîne vide ou le nombre 0 (ou son équivalent sous forme de chaîne : '0')

Il existe deux variétés de scalaires nuls : ceux qui sont définis et ceux qui ne le sont pas. Par exemple utiliser une variable non initialisée retourne une valeur nulle non définie (donc fausse (False) au sens booléen).

  $vide=''; # scalaire vide défini
$Nom='Etienne';
print "$nom\n";

n'imprime rien. $nom est indéfini du fait de l'erreur sur le nom de la variable.


Opérateurs

 

Comparaison

On utilisera pour des variables numériques :

== test d'égalité
!= test d'inégalité
<  test inférieur strictement
>  test supérieur strictement
<= test inférieur ou égal
>= test supérieur ou égal

On utilisera pour des chaînes de caractères :

eq  test d'égalité (EQual)
ne  test d'inégalité (Non Equal)
lt  test inférieur strictement (Less Than)
gt  test supérieur strictement (Greater Than)
le  test inférieur ou égal (Less or Equal)
ge  test supérieur ou égal (Greater or Equal)

Attention à bien utiliser les bons tests pour les bonnes variables. Pour t'en convaincre essaye donc ce petit programme :

#!usr/bin/perl -w
$a=8;$b=10;
if ($a<$b)    {print "vrai\n"} else {print "faux\n"};
if ($a lt $b) {print "vrai\n"} else {print "faux\n"};
$c='8';$d='10';
if ($c<$d)    {print "vrai\n"} else {print "faux\n"};
if ($c lt $d) {print "vrai\n"} else {print "faux\n"};

Lorsqu'on utilise la comparaison < on utilise des tests de type numériques qui comparent le nombre 8 au nombre 10 (dans le deuxième cas bien qu'ils soient définis comme chaînes de caractère, il y a conversion automatique). Ces tests numériques tiennent compte également du signe des opérandes.

Lorsqu'on utilise la comparaison lt on utilise des tests de type chaînes de caractères qui comparent la valeur ASCII de chaque caractère de chaque chaîne. Dans notre exemple la chaîne '8' qui contient un caractère est comparée à la chaîne '10' qui en contient deux. La chaine la plus courte est étendue à la longueur voulue en rajoutant des blancs à droite, ce qui fait que le caractère 8 est comparé au caractère 1 (et non pas le nombre 8 au nombre 10) d'où la réponse du programme.

 

Attention à bien doubler le signe égal dans les comparaisons pour éviter la confusion avec l'opérateur d'affectation.

Affectation

Elle est réalisée par le signe =

$a+=2; est équivalent à $a=$a+2; c'est également valable pour - / * (et d'autres encore)

 

 

$a=4;
$couleur='rouge';

Nous n'en dirons pas plus dans le contexte des notions élémentaires.

Arithmétique

+ Addition     - Soustraction

 

++ Auto-incrémentation. Placé avant une variable il y a incrémentation AVANT de retourner la valeur, placé APRES il y a d'abord retour de la valeur puis incrément.

$a=7;
$b=++$a;
print "\$b=$b \$a=$a\n"; # $b=8 $a=8
$a=7;
$b=$a++;
print "\$b=$b \$a=$a\n"; # $b=7 $a=8

L'auto-incrémentation a un comportement dit "magique" vis à vis des chaines de caractères. Essayez le programme suivant :

$c='zy';
print "\$c=$c \$d=$d \$e=$e\n";
$d=++$c;
print "\$c=$c \$d=$d \$e=$e\n";
$e=$d++;
print "\$c=$c \$d=$d \$e=$e\n";
 











Après avoir testé et compris... essaye donc de changer la valeur de $c de 'zy' en 'xzy'

-- Auto-décrémentation. Attention elle ne possède pas le pouvoir "magique".

 

** Puissance.

 

* Multiplication.

 

/ Division.

 

% Modulo. Pour ceux qui ne savent pas, c'est le reste de la division. Par exemple $a%$b représente le reste de la division $a par $b.

 

Pratique pour les années bissextiles mais attention aux années centenaires!

Unaires

On dit unaires parce qu'ils s'appliquent à un seul terme, celui situé immédiatement à droite.

! Non logique. On peut également l'écrire not. Si l'expression est vraie elle devient fausse et vice-versa.

- Négation arithmétique. Rendre un nombre négatif.

~ Négation bit à bit. Pour chaque bit à 1 on met 0 et pour chaque bit à 0 on met 1. Autrement dit on fait le complément à 1.

 

 

if (!($a==1 && $b==0)) .....
ou bien
if (not($a==1 and $b==0)) .....

Sur ce propos il faudra que nous ayons une discussion sur l'art et la manière d'écrire du perl.

En attendant remarque bien les parenthèses qui entourent la condition, elles sont obligatoires pour le champ d'application du not, et celles qui entourent le not, elles sont obligatoires pour la syntaxe du if.

Logiques

& Et logique bit à bit

| OU logique inclusif bit à bit

^ OU logique exclusif bit à bit

&& on peut utiliser and à la place. C'est le ET logique rapide. Cela signifie que si l'opérande gauche est faux, l'opérande droit n'est même pas évalué.

|| on peut utiliser or à la place. C'est le OU logique rapide. Cela signifie que si l'opérande gauche est vrai, l'opérande droit n'est même pas évalué.

 

 

En fait on utilisera la logique bit à bit dans une optique de calcul et la logique rapide dans les comparaisons de tous les jours.

Et maintenant voyons ça du côté de chez Bool :

    ET         OU       OUX   (en réalité on dit AND OR et XOR)
1 1 0 0    1 1 0 0    1 1 0 0
1 0 1 0    1 0 1 0    1 0 1 0
--------    --------    --------
1 0 0 0    1 1 1 0    0 1 1 0

Et maintenant ce qui suit est destiné à faire comprendre aux non matheux la différence entre ET, OU et OU exclusif.

ET

Pierre et Jean jouent à la belote. Mais comme chacun sait pour faire une partie il faut être être quatre. Ils attendent donc 2 adversaires. Si Albert ET Marc viennent ils feront leur partie sinon ils continueront à s'em...

OU

Paul, Pierre et Jean jouent encore à la belote. Ils attendent le quatrième. Si Albert OU Marc viennent ils feront leur partie (et c'est le cinquième qui s'em...), sinon ils continueront leur partie à 3 (pas folichon...)

OU exclusif

Paul, Pierre et Jean jouent toujours à la belote. Ils attendent toujours un quatrième. Si Albert OU Marc viennent ils feront leur partie mais comme ils sont polis si les deux viennent ensemble ils ne joueront pas (en fait ils feront une petit tarot à 5), si personne ne vient ils continueront leur partie à 3 (toujours pas gai gai...)
 

 

Ici on va parler un peu des conditions composées associées à la négation.

C'est un problème qui se pose un jour à tout programmeur. Et si l'un d'entre eux te dit qu'il n'a jamais fait l'erreur, ne le croie sutout pas : c'est un menteur!

On va partir d'une phrase simple comme "S'il pleut j'irai faire une balade sinon dodo".

Et puis on va compliquer un peu. En langage parlé de tous les jours nous pourrions dire : "S'il ne pleut pas ou il ne grêle pas j'irais faire une balade sinon dodo" et tout le monde comprend, c'est sans ambiguité.

Les ennuis commencent lorsqu'on veut traduire ce genre de phrase (la deuxième bien sûr) dans un programme. On va écrire par exemple :

#!usr/bin/perl
$temps='.....'; # utilise soleil, pluie grele
if ($temps ne 'pluie' or $temps ne 'grele')
     {$action='balade';}
else {$action='dodo';}
print "temps=$temps alors $action\n";

Et teste le en utilisant respectivement soleil, pluie et grele. Ca ne marche pas. Pourquoi ?

Et bien parce que ce n'est pas le bon opérateur qui relie les conditions. Utilise and à la place de or et tout fonctionnera normalement.

Sans avoir testé tu n'est pas convaincu ? Très bien. On va mettre l'erreur en évidence en prenant le contraire de la phrase :

Effectivement c'est tout aussi juste de dire "S'il pleut, dodo sinon balade" que "s'il ne pleut pas, balade sinon dodo".

Appliquons le contraire à notre cas : "S'il pleut ET s'il grele j'irai au dodo sinon balade" on voit bien là que ce ET n'est pas bon (il ne peut pas pleuvoir et grêler à la fois! ). C'est un OU qu'il aurai fallu ce qui implique que dans la phrase initiale il aurait fallu dire : "S'il ne pleut pas ET s'il ne grêle pas j'irais faire une balade sinon dodo".

En conclusion méfie-toi du langage parlé, surtout avec des négations. Si tu as un doute prends le contraire de ta phrase c'est souvent plus simple.

Dans les contraires ET et OU s'inversent, égal et différent aussi, ainsi que plus grand et plus petit, une double négation s'annule, et les actions se permutent. Ainsi écrit cela a l'air bien compliqué, mais avec du bon sens c'est simple.

 

 

Divers

. (point) Concaténation de 2 chaînes 'ABC'.'DE' représente la chaîne 'ABCDE'

x Répétition. "ab"x10 représente la chaîne "ab" répétée 10 fois.

Il reste des opérateurs, mais ils débordent le cadre des notions élémentaires.

 


La circonférence du cercle - Le deuxième programme

 
Nous sommes mûr pour écrire notre deuxième programme :  


#!/usr/bin/perl -w

##
# circonférence d'un cercle
##

sub PI {3.1415926535};

print ("\nBonjour,\n");
print ("nous allons calculer la circonférence d'un cercle.\n");
print ("Veuillez entrer le rayon (exemple 1.8) :\t");

chomp($r = <STDIN>);
$circ = 2*$r*PI;

print ("\nLa circonférence d'un cercle de rayon $r vaut : $circ\n");

Dans cet exemple ce qui est intéressant c'est la ligne
chomp($r=<STDIN>); Le reste on connait ou on intuite.

<STDIN> réalise une lecture du clavier. Une lecture du clavier se termine par l'appui sur la touche entrée qui génére le caractère "newline" (notre fameux \n). Ce caractère est gênant, il faut l'éliminer. On peut imaginer pas mal de techniques mais il en est une qu'il faut employer.

Il s'agit de la fonction chomp(), particulièrement adaptée à cet usage et qui réalise la suppression du caractère de droite, si celui-ci est égal à la variable $/ (également connue sous le nom de $INPUT_RECORD_SEPARATOR) initialisée par défaut avec "newline" (LF ou NL). Attention la fonction chomp() travaille directement sur la variable qu'elle modifie et retourne le nombre de caractères supprimés.

Anciennement, c'était la fonction chop(), qui était utilisée. Cette fonction supprime systématiquement le caractère de droite et renvoie celui-ci.

 








Remarque comment se définit la constante PI. On reparlera de cette technique plus tard, elle fait partie de la "culture perl".

En attendant ca n'a rien à voir avec perl mais voici un petit truc pour retenir le nombre PI. Victor Hugo a écrit tout un poème dont le nombre de lettre de chaque mot correspond à un chiffre du nombre PI. Voici le premier vers "Que j'aime à faire connaitre ce nombre utile aux sages" et attention aux sages est au pluriel !!!








Notion de bloc - Instructions if et unless

 

Des instructions ayant un lien logique entre elles peuvent être groupées. On dit dit alors qu'elles forment un bloc. Un bloc est délimité par des accolades {}.

Le lien logique peut-être par exemple le fait qu'elles soient exécutées sous le contrôle d'une instruction. On parle alors de la portée (scope en anglais) de cette instruction. On pourrait dire aussi "champ d'action".

 

l'instruction if

3 façons d'écrire des if.

  • if (....) {....}
  • if (....) {....} else {....}
  • if (....) {....} elsif (....) {....} ... else {....}
  • - Entre les () qui sont obligatoires on trouve une condition.

    - Entre les {} qui sont obligatoires on trouve un bloc d'instructions.

    - Bien entendu on peut imbriquer des if dans les blocs d'instructions. Evite néanmoins de faire des conditions trop complexes. Utilise plutôt la syntaxe avec elsif.

     

     

    Souviens-toi :

  • Utilise eq, ne, lt, gt, le, ge pour les tests sur les chaînes de caractères
  • == != < > <= >= s'il s'agit de nombres
  • unless

    Tu sais écrire un if ? Alors tu sais écrire unless C'est pareil ! Unless inverse seulement le résultat des tests. Par exemple :

    $a=1;if ($a==1) {print 'un';} else {print 'pas un';} imprimera 'un'

    en remplaçant if par unless le programme imprimera 'pas un'.

     

     

    Autrement dit :

  • if correspond au test : "si l'expression de controle est vraie ...".
  • unless correspond au test : "si l'expression de controle est fausse ...".


  • Un petit jeu en guise d'exercice

     
    Tu as bien gagné le droit de te détendre un peu. :o)
    #!usr/bin/perl -w
    use integer;
    print "Entre un niveau de difficulte de 1 a 10 : ";
    chomp($niv = <STDIN>);
    $n=int(rand(9999999999/10**(10-$niv)));
    print "Retient ton code : $n";
    sleep(2);
    print "\b"x40," "x40,"\n";
    print "Rentre ton code : "; chomp($code = <STDIN>);
    if ($code == $n) {print "Gagne\n";}
       else          {print "Perdu\n";}
    
     





    Si tu n'a pas tout compris va voir les explications.

    Ce petit programme clôture les notions dites élémentaires. On va passer à quelques concepts un peu plus évolués.