Developpez.com - Autres
X

Choisissez d'abord la catégorieensuite la rubrique :

Sommaire > S'initier à Perl > Scalaires
        Qu'est ce qu'un scalaire ?
        Que peut contenir un scalaire ?
        Comment définir une variable scalaire ?
        Comment déclarer une variable scalaire ?
        Comment affecter une valeur à une variable scalaire ?
        Et si je n'affecte pas de valeurs à mes variables ?
        Quelles opérations peut-on réaliser sur ces variables ?
        Mais comment faire la différence entre entiers, flottants, chaînes, etc.. ?
        Que faire avec les valeurs numériques ?
        Et les chaînes de caractères ?
        Comment exprimer une chaîne de caractères ?
        Mais que peut-on faire avec les chaînes de caractères ?

        


Qu'est ce qu'un scalaire ?
auteur : 2Eurocents
Une variable ou un scalaire (traduction impropre et systématique de l'anglais 'scalar' qui signifie 'variable' ou 'quantité variable') est le plus petit élément d'information que puisse traiter PERL. En PERL, un scalaire se repère au premier caractère de son identifiant (de son nom). Ce premier caractère est obligatoirement le symbole 'dollar' ($). Le nom d'un scalaire peut être composé de chiffres, de lettres et de certains caractères spéciaux (_), mais il doit JAMAIS commencer par un chiffre. On a coutume de dire qu'il s'agit d'un élément atomique, au sens où il n'est pas possible simplement de le diviser en éléments plus petits (du grec atomos qui signifie indivisible - "tomos" pour couper avec le préfixe privatif "a").


Que peut contenir un scalaire ?
auteur : 2Eurocents
Une variable scalaire peut contenir à peu près n'importe quoi, PERL étant un langage dit faiblement typé. Les langages faiblement typés ne font pas la différence, a priori, entre nombres entiers, nombres à virgule flottante, caractères et chaînes de caractère. Cela ne pose cependant pas de problème en PERL, ainsi qu'on le verra plus loin ...


Comment définir une variable scalaire ?
auteur : 2Eurocents
Il suffit de l'utiliser, c'est à dire d'y faire référence en utilisant son identifiant (nom complet, avec le $ initial). Contrairement à de nombreux autres langages de programmation, PERL n'impose pas de déclaration préalable des variables. Ainsi, toute utilisation de variable crée automatiquement celle-ci. Pour pallier aux nombreux risques que cette absence de déclaration des variables peut faire peser sur le développement, il existe des options permettant d'imposer une syntaxe stricte avec déclaration préalable à tout usage. Ainsi, pour plus de sécurité, il est préférable d'écrire, au début du script :

use strict;
On parle alors d'utiliser les "strictures" - Si quelqu'un s'oppose à ce barbarisme, qu'il parle maintenant ou se taise à jamais.


Comment déclarer une variable scalaire ?
auteur : 2Eurocents
Les mots clefs de déclaration de variables sont my et our. Ces mots clefs sont valables pour tous types de variable, et pas uniquement pour les variables scalaires. La différence entre my et our sera abordée plus loin dans ce document. Dans l'immédiat, l'usage de my conviendra pour la plupart des cas. Ainsi, pour déclarer une variable $i, on écrira simplement :

my $i;

Comment affecter une valeur à une variable scalaire ?
auteur : 2Eurocents
L'opérateur d'affectation est tout simplement l'opérateur =. Ainsi, il est possible d'écrire :

my $i=0;
pour affecter une valeur initiale à la variable, dès son initialisation. Par la suite, on peut écrire :

$i=5; #voire : my $j=$i; #ou bien : $i='a'; $i='test de chaîne'; $i=3.1415;
A l'issue de ces trois dernières affectations, $i vaut le caractère "a", pour la première, la chaîne "test de chaîne" pour la seconde et 3.1415 (le nombre à virgule flottante) pour la troisième. Les nombres peuvent être exprimés en base décimale ($i = 100;), en octal (il suffit de commencer la valeur par un zéro : $i = 0144;) ou en hexadécimal (en commençant la valeur par un zéro suivi par un x : $i = 0x64;).


Et si je n'affecte pas de valeurs à mes variables ?
auteur : 2Eurocents
Les variables auxquelles aucune valeur n'a été affectée sont néanmoins initialisées automatiquement par l'interpréteur PERL. La valeur implicite d'initialisation est une valeur spécifique nommée undef. La valeur 'undef' est une valeur un peu magique :
  • dans des opérations arithmétiques, elle vaut zéro,
  • dans les opérations de chaînes de caractères, elle équivaut à la chaîne vide, mais attention, toutefois car son usage provoque des affichages de messages d'avertissement si les "warnings" sont actifs (use warnings; ou option -w du shebang),
  • il ne faut pas la tester de manière classique avec les opérateurs de comparaison (voir plus loin), mais au moyen d'une fonction spécifique : defined () qui retourne vrai si la variable est définie et faux si elle vaut undef,
  • il est possible de l'affecter soi-même à une variable déjà définie, soit par une affectation $variable=undef; soit par une fonction undef($variable);


Quelles opérations peut-on réaliser sur ces variables ?
auteur : 2Eurocents
Les variables auxquelles aucune valeur n'a été affectée sont néanmoins initialisées automatiquement par l'interpréteur PERL. La valeur implicite d'initialisation est une valeur spécifique nommée undef. La valeur 'undef' est une valeur un peu magique :
  • dans des opérations arithmétiques, elle vaut zéro,
  • dans les opérations de chaînes de caractères, elle équivaut à la chaîne vide, mais attention, toutefois car son usage provoque des affichages de messages d'avertissement si les "warnings" sont actifs (use warnings; ou option -w du shebang),
  • il ne faut pas la tester de manière classique avec les opérateurs de comparaison (voir plus loin), mais au moyen d'une fonction spécifique : defined () qui retourne vrai si la variable est définie et faux si elle vaut undef,
  • il est possible de l'affecter soi-même à une variable déjà définie, soit par une affectation $variable=undef; soit par une fonction undef($variable);
Quelles opérations peut-on réaliser sur ces variables ? Les principaux opérateurs arithmétiques sont disponibles. Ainsi, il est possible d'utiliser :
  • + pour l'addition ($a = $b + 75;),
  • - pour la soustraction (l'opérateur - existe aussi en version "unaire", pour signifier un nombre négatif) ($a = -75 -$b;),
  • * pour la multiplication ($a = $b * $c;),
  • / pour la division ($a = 83 / 17;),
  • % pour le modulo (reste de la division entière) ($b = 83 % 17;),
  • ** pour l'exponentiation (l'élévation à une puissance, comme $a = $b ** 3;)
  • ++ est un opérateur (unaire) de pré- ou post incrémentation de la variable sur laquelle il porte (++$a ou $a++),
  • -- est un opérateur (unaire) de pré- ou post décrémentation de la variable sur laquelle il porte (--$a ou $a--),
Il existe aussi des opérateurs spécifiques aux traitements sur les chaînes de caractères :
  • . (le point) est l'opérateur de concaténation de chaînes ($a = "abcd" . "efgh";).
  • x est l'opérateur de répétition qui répète la chaîne le précédant autant de fois qu'indiqué par le nombre suivant ($a = "*" x 40; pour obtenir quarante étoiles).
  • =~ est l'opérateur de mise en correspondance avec une expression rationnelle (gros chapitre du langage qui sera abordé ultérieurement).
Certains opérateurs sont qualifiés de "binaires bit à bit" :
  • ~ pour la négation bit à bit ($i = ~ $j;)
  • << est un opérateur de décalage bit à bit vers la gauche ($a = $b lt;lt; 3;),
  • >> est un opérateur de décalage bit à bit vers la droite ($a = $b >> 3;),
  • & effectue un ET bit à bit entre ses opérandes ($zero = 0x36 & 0xC9;),
  • | pour un OU bit à bit ($deux_cent_cinquante_cinq = 0x36 | 0xC9;),
  • ^ pour un OU EXCLUSIF entre deux valeurs,
Il existe aussi des opérateurs de test, de comparaison, et ces opérateurs existent sous deux formes, selon que l'on souhaite comparer des nombres entiers ou bien des chaînes de caractères :
  • == ou eq pour tester l'égalité numérique ou alphabétique,
  • < ou lt pour l'infériorité stricte,
  • <= ou le pour l'infériorité,
  • > ou gt pour la supériorité stricte,
  • => ou gt pour la supériorité,
  • != ou ne pour la différence.
  • <=> ou cmp sont des opérateurs spéciaux de comparaison, qui retournent -1, 0 et 1 selon lequel de leurs opérandes est le plus grand,
Et enfin, des opérateurs logiques complètent la panoplie :
  • && ou and permettent de réaliser la conjonction entre deux conditions (le ET logique),
  • || ou or permettent de réaliser la disjonction entre deux conditions (le OU logique),
  • xor permet de réaliser une disjonction exclusive (le XOR logique),
  • ! ou not permettent de réaliser la négation d'une condition.
La différence entre les opérateurs logiques similaires vient, entre autres, des différences de priorité. Ils ne sont cependant pas toujours utilisés dans le même contexte. Notamment, l'usage des opérateurs logique dans le style C (&&, ||) avec des listes (sujet abordés plus loin) risque de poser problème. Dans ce cas, l'usage des opérateurs en toutes lettres est plus sûr. Il existe encore d'autres opérateurs, dont les plus utiles sont :
  • ?: qui permet de réaliser un choix entre deux valeurs, selon le test d'une condition ($i = ($a == $b)?$a:$b; $i vaudra $a si $a et $b ont la même valeur, $b s'ils sont différents).
  • , qui procéde à l'évaluation de son membre de droite, puis à celle du membre de gauche, avant de garder le résultat de la dernière évaluation (ça parait compliqué et inutile, comme ça, mais quand on maîtrise bien, ça peut réellement être très puissant) ($i = ($j=100),($k=50); fait que $i et $j valent 100, $k vaut 50).
Et il existe aussi des formes abrégées des principaux opérateurs réfléchis (même variable présente des deux côtés de l'affectation). Ces opérateurs posent les mêmes difficultés de maintenance ou de compréhension du code qu'en C. On trouve : +=, -=, *=, /=, .=, <<=, etc.


Mais comment faire la différence entre entiers, flottants, chaînes, etc. ?
auteur : 2Eurocents
PERL sait très bien faire la différence tout seul. En fait, en fonction des opérateurs utilisés, PERL détermine automatiquement la façon dont il faut traiter le contenu des variables. C'est la notion de "contexte". Il existe deux contextes principaux : contexte scalaire et contexte de liste. Le contexte scalaire, lui, possède des nuances : contexte scalaire numérique, contexte scalaire de chaîne et contexte scalaire booléen. Lorsque l'on utilise des opérateurs numériques ou des fonctions numériques (que l'on verra plus tard), PERL modifie automatiquement le contexte pour traiter les variables comme des nombres. Qui plus est, si l'un de ces nombres contient un . (le séparateur décimal), par exemple, tous les nombres en jeu dans l'opération sont automatiquement promus comme nombres flottants. Attention, toutefois, car l'évaluation de chaînes de caractères en contexte numérique peut provoquer des résultats inattendus. Ainsi, l'évalutation suivante peut tout à fait donner un résultat, qui s'il est cohérent du point de vue de PERL n'en est pas moins faux :

$i = "2eurocents" + "Code 100 sous 6"; print $i."\n";
produira 2, car "2eurocents" est évalué à 2 en contexte numérique et "code 100 sous 6" n'arrive pas à être évalué (le premier mot n'est absolument pas numérique).

$i = "2eurocents" + "100sous6"; print $i."\n";
produira 102, "2eurocents" est toujours évalué à 2 et "100sous6" est évalué à 100, c'est à dire à toute la portion numérique initiale de la chaîne. Heureusement, l'intérprèteur PERL peut nous aider par des messages d'avertissements lors de telles opérations, si la directive warnings a été utilisée (paramètre -w du shebang ou clause use warnings;). Cela peut être un avantage, comme un inconvénient. Il importe que le programmeur teste au préalable les cas où cela peut lui poser des problèmes de cohérence car le langage ne le fera pas pour lui. Ainsi, en PERL, il est possible de faire aussi bien :

$volume = "10 l" + "5 dm³";
qui est cohérent, que :

$mélange = "3 choux" + "18 paires de carottes";
qui n'a absolument aucun sens, pour le plus grand bonheur pédagogique de toute une génération d'instituteurs. Heureusement, le programmeur sait ce qu'il fait, la plupart du temps ... le vrai danger vient le l'utilisateur, tout le monde le sait ! En fait, ces préoccupations valent surtout pour les variables sur lesquelles l'utilisateur peut avoir le contrôle (zones saisies, données provenant de fichiers, etc.).


Que faire avec les valeurs numériques ?
auteur : 2Eurocents
Bien que PERL ne soit pas réellement performant dans le domaine du calcul numérique (on verra pourquoi d'ici peu), il est tout à fait possible de mener quelques opérations. Les opérateurs arithmétiques sont disponibles, on l'a vu, mais il y a aussi quelques fonctions :
  • abs() pour les valeurs absolues,
  • atan2() pour la tangente inverse, ainsi que cos() et sin() pour les amoureux de la trigonométrie,
  • log() et exp() pour le logarithme népérien et les puissances de e,
  • sqrt() pour les racines carrées,
  • int() pour tirer les parties entières,
  • hex() ou oct() pour des changements de base numérique,
  • rand() et srand() permettent d'utiliser et d'initialiser le générateur de valeurs pseudo-aléatoires


Et les chaînes de caractères ?
auteur : 2Eurocents
Quoi, les chaînes de caractères ? En fait, en PERL, les chaînes de caractères sont des scalaires comme les valeurs numériques. Pour être parfaitement rigoureux, on devrait même dire que les valeurs numériques sont des scalaires comme les chaînes de caractères ! En effet, PERL stocke toutes ses variables sous la forme de chaînes, ainsi que les programmeurs expérimentés peuvent s'en apercevoir en manipulant les fonctions pack/unpack ... PERL ne fait même pas la différence entre caractères imprimables ou valeurs binaires : tout cela constitue des valeurs scalaires valides.


Comment exprimer une chaîne de caractères ?
auteur : 2Eurocents
Une chaîne de caractères est un scalaire dont la valeur est exprimée entre quotes. Nos claviers étant généreusement dotés de simple comme de doubles quotes, nous avons le choix de l'expression. Lorsque la chaîne de caractères est exprimée entre doubles-quotes, l'interpréteur PERL poursuit son travail à l'intérieur et y interprète ce qu'il y rencontre. Il est ainsi possible d'y insérer des éléments tels que d'autres scalaires (préfixés par un $), des caractères spéciaux exprimés en notation "backslash" (tels que \n pour le saut de ligne, \r pour le retour de chariot, \t pour la tabulation, ...), etc.

$monde="world !\n"; $politesse="Hello $monde"; print $politesse;
Dans le cas ou l'on souhaiterai accoler un scalaire et du texte fixe dans une chaîne de caractère, sans espace intermédiaire, il est nécessaire d'exprimer le scalaire différemment afin d'aider PERL à trouver les limites de son nom. On met ainsi le nom du scalaire entre accolades :

$racine="programm"; $_1e_pers_sing="Je ${racine}e"; $_2e_pers_sing="Tu ${racine}es"; $_3e_pers_sing="Il ${racine}e"; $_1e_pers_plur="Nous ${racine}ons"; $_2e_pers_plur="Vous ${racine}ez"; $_3e_pers_plur="Ils ${racine}ent";
Il est possible de bloquer le travail d'interprétation de PERL en protégeant certains caractères par une barre oblique inversée. Ainsi, pour insérer des doubles-quotes, un dollar, un arrobas ou une barre inversée, il faut exprimer respectivement \", \$, \@ et \\. De la même manière, pour exprimer certains caractères spéciaux dont on connait le code ASCII, il est possible d'exprimer ce dernier numériquement, à la suite d'un anti-slash : \0 (caractère NULL) ou \7 (caractère BELL) par exemple. Lorsque la chaîne est exprimée entre simple quotes, l'interpréteur PERL les prend telles quelles, sans examiner leur contenu. Seuls les caractères ' et \ ont besoin d'y être protégés (' doit être écrit \', pour ne pas être confondu avec la fin de chaîne, et \ doit être protégé en \\ puisqu'il peut avoir un rôle spécial dans la protection de '). Ainsi, "col1\tcol2\tcol3\n" représente un texte de 3 colonnes séparées par des tabulations et terminé par un saut de ligne. 'col1\tcol2\tcol3\n' représente ce texte tel quel, avec les \, les t qui les suivent et le n final.


Mais que peut-on faire avec les chaînes de caractères ?
auteur : 2Eurocents
La vraie puissance de PERL, on le dit souvent, réside dans le traitement des chaînes de caractères. C'est particulièrement vrai dans l'application des expressions rationnelles, qui seront vues ultérieurement. Hors ce gros morceau du langage, de nombreux traitements sont possibles, que ce soit par le biais des opérateurs ou par des fonctions spécifiques :
  • L'opérateur de concaténation : "Bonjour "."le monde"
  • L'opérateur de multiplication : "Bonjour " x 3
  • chop () supprime et renvoie le dernier caractère d'une chaîne de caractère.
  • chomp () supprime le dernier caractère d'une chaîne, uniquement s'il s'agit d'une fin de ligne (mais ne renvoie pas celui ci !).
  • reverse () retourne une chaîne de caractères (aimez-vous les palindromes ?).
  • uc(), lc(), ucfirst() et lcfirst () sont des fonctions de changement de casse des chaînes passées en paramètre. uc() passe la chaîne en majuscules (upper case) et lc() en minuscules. Les variantes *first ne traitent que la première lettre.
  • oct() et hex () font des conversions de bases numériques. Ah, mais on en a déjà parlé quand on parlait des fonctions numériques ... Oui, mais en perl, tout est chaîne de caractères, donc en fait, les fonctions numériques travaillent sur des chaînes qu'elles convertissent pour le traitement.
  • chr() et ord () font des conversions code ASCII/caractère. Ainsi, chr(65)="A" et ord("A")=65.
  • length(), index(), rindex() et substr() sont des fonctions classiques de traitement de chaînes. La fonction length() renvoie la longueur de la chaîne ; les fonctions index() et rindex() renvoient la position de la première ou de la dernière occurence d'une sous-chaîne dans une chaîne, avec éventuellement une position de début de recherche ; substr() retourne une portion d'une chaîne donnée, à partir d'une position fixée et d'une longueur précisée. Cette dernière fonction, substr() est intéressante à plus d'un titre car elle peut aussi servir à faire un remplacement de portion de chaîne, éventuellement de longueur variable. Elle est utilisée, dans ce cas, comme réceptacle d'une affectation : my $chaîne="Bonjour tout le monde"; substr ($chaîne, 3, 4) = " appétit"; remplace "jour" (position 3, longueur 4 dans la chaîne) par " appétit ". La chaîne est agrandie et tout est pour le mieux. Ce mécanisme fonctionne aussi parfaitement avec les scalaires contenant des buffers binaires ... Qui veut patcher ?
  • pack() et unpack() sont des fonctions très avancées qui permettent toutes sortes de codages et décodages de valeurs binaires, décimales, héxadécimales, tant sur des nombres que sur des chaînes. Elles sont très utilisées dès que vous avez à coder/décoder des valeurs binaires provenant de dialogues directs avec différents matériels, protocoles, systèmes ...
  • print(), printf() et sprintf() sont, bien sûr, des fonctions de dialogue. Elles permettent de dialoguer aussi bien avec la console, qu'avec des fichiers. La fonction print affiche simplement ses paramètres, là où les fonctions printf et sprintf permettent des formattages complexes, comme leurs homologues en C dont elles sont issues.
  • tr/// (ou y///) est une fonction spéciale permettant de transformer, dans une chaîne, tous les caractères d'un ensemble en caractères d'un second ensemble. Elle est apparentée aux expressions rationnelles.
D'autres fonctions sont disponibles, pour traiter toutes sortes de scalaires, et lorsque ce n'est pas suffisant, le langage peut être étendu par l'usage de modules, ainsi qu'on le verra par la suite.


        

Consultez les autres F.A.Q's

Ce document issu de www.developpez.com est soumis à la licence GNU FDL traduit en français ici
Permission vous est donnée de distribuer, modifier des copies de cette page tant que cette note apparaît clairement.
Contacter le responsable de la rubrique Autres