Cum se configurează smartphone-uri și PC-uri. Portal informativ

Perl: expresii și operații. P2.3.4.18 ȘI logic, SAU și SAU exclusiv

Expresiiîn PERL, ca și în alte limbaje de programare, sunt combinații de variabile, constante și operații care dau un rezultat semnificativ. Acest rezultat poate fi un scalar, o matrice sau o matrice asociativă.

Toate operațiunile PERL sunt împărțite în:

Operațiunile I/O sunt descrise în articolul „ Perl: descriptori de fișiere”, operațiuni cu expresii obisnuite — "Perl: expresii regulate”, secțiunea „Operații cu expresii regulate”.

Operații de comparare

Operații de comparare compară doi operanzi și returnează 1 sau 0 în funcție de rezultatul comparației. PERL conține două seturi de operatori de comparare: pentru compararea numerelor și pentru compararea șirurilor. Primul grup de operații își convertește mai întâi operanzii în numere și apoi îi compară. Al doilea grup de operații convertește operanzii în șiruri de caractere și îi compară în ordine lexicografică. Dacă este specificată directiva use locale, atunci compararea datei se face ținând cont de setarea locală.

Comparația numerelorComparație de șiruriNumeDescriere
A< b a lt b Mai puțin 1 dacă operandul din stânga este mai mic decât operandul din dreapta.
a>b a gt b Mai mult 1 dacă operandul din stânga este mai mare decât operandul din dreapta.
A<= b a le b Nu mai mult 1 dacă operandul din stânga este mai mic sau egal cu operandul din dreapta.
a => b a ge b Nu mai puțin 1 dacă operandul din stânga este mai mare sau egal cu operandul din dreapta.
a == b a eq b Egal 1 dacă operandul din stânga este egal cu operandul din dreapta.
a != b a ne b Nu este egal 1 dacă operandul din stânga nu este egal cu operandul din dreapta.
A<=>b un cmp b Comparaţie -1 dacă operandul din stânga este mai mic decât operandul din dreapta; 0 dacă sunt egale; 1 dacă operandul din stânga este mai mare decât operandul din dreapta.

Următorul exemplu

$a = 299;
$b = 30;
dacă ($a< $b)
{
print "Numărul $a este mai mic decât numărul $b\n";
}
dacă ($a lt $b)
{
print "Șirul $a este mai mic decât șirul $b\n";
}

va afișa mesajul: Linia 299 este mai mică decât linia 30.

Operații logice

PERL conține două seturi operatii logice , care sunt identice ca rezultat, dar au prioritate diferită. Vă rugăm să rețineți că rezultatele operațiilor AND și SAU diferă de cele din alte limbaje de programare.

Operatorii și , sau , xor și not au cea mai mică prioritate dintre toți operatorii PERL. Acest lucru le permite să fie folosite în partea dreaptă a declarațiilor fără paranteze suplimentare, de exemplu:

Deschideți HANDLE, „file.dat” sau die „Eroare: $!\n”;

Folosind || acest exemplu va necesita paranteze:

Deschide(HANDLE, „fișier.dat”) || die „Eroare: $!\n”;

Operații cu biți

Operații cu biți se aplică operanzilor reprezentați ca numere binare(adică, ca șiruri de biți) și returnează o valoare care indică rezultatul operației.

OperațiuneNumeDescriere
a&b ȘI pe biți Returnează un 1 la fiecare poziție de bit dacă pozițiile corespunzătoare ale ambilor operanzi sunt 1.
a | b SAU pe biți Returnează un 1 la fiecare poziție de bit dacă poziția corespunzătoare a cel puțin unui operand este 1.
a^b XOR pe biți Returnează un 1 la fiecare poziție de bit dacă poziția corespunzătoare a exact unui operand este 1.
~a Pe bit NU Operație unară. Inversează fiecare poziție de bit a operandului.
A<< b Schimbați la stânga Schimbări reprezentare binară operandul din stânga la stânga cu numărul de biți specificat de al doilea operand.
a >> b Schimbați la dreapta Mută ​​reprezentarea binară a operandului din stânga la dreapta cu numărul de biți specificat de al doilea operand.

Operațiile de schimbare se aplică numai operanzilor numerici, dar altora operații pe biți Se aplică atât numerelor, cât și șirurilor. Dacă unul dintre operanzii unei operații pe biți este un număr, atunci ambii operanzi sunt convertiți în numere întregi. Dacă ambii operanzi sunt șiruri, atunci aceștia sunt convertiți în șiruri de aceeași lungime și operația este efectuată pe fiecare bit al șirurilor rezultate. Acest lucru ne permite să aplicăm operații pe biți la operanzi de orice lungime. În acest caz, operațiunile | și ^ tastați șirul mai scurt la dreapta cu zero biți, iar operația & trunchiază șirul mai lung la dimensiunea celui mai scurt. Putem specifica în mod explicit tipul de operație folosind ghilimele pentru șiruri de caractere sau 0+ pentru numere. Exemple:

Tipărire 1.9 | 2; #3 (operand flotant trunchiat la un întreg)
imprimare 150 | „105”; #255 (0x96 | 0x69 este egal cu 0xFF)
tipăriți „150” | „105”; # „155” (în ASCII)
$a = 150;
$b = "105";
imprima 0+$a | 0+$b; # operanzi numerici
tipăriți „$a” | „$b”; # operanzi șir

Execuția operațiilor pe biți este afectată de directivele de control aritmetic. În mod implicit, numerele întregi sunt considerate fără semn, astfel încât operația de schimbare la dreapta umple cei mai semnificativi biți ai rezultatului cu zerouri, iar operația ~0 returnează cel mai mare număr întreg pozitiv. Directiva use integer face ca numerele întregi să fie interpretate ca numere cu semn. Prin urmare, în domeniul său de acțiune, operația de schimbare la dreapta umple biții cei mai semnificativi ai rezultatului cu bitul semn al numărului, iar operația ~0 returnează numărul -1.

Operații unare

Plus unar

Plus unar(+) returnează operandul său. Singura utilizare semnificativă a acestei operațiuni este separarea numelui funcției de argumentele sale din paranteze. Luați în considerare acest exemplu:

Imprimare (10 + 20) / 10;

Contrar așteptărilor, acest operator imprimă nu numărul 3, ci numărul 30. Faptul este că parantezele din jurul argumentelor funcției au cea mai mare prioritate în PERL, adică operația de imprimare (10 + 20) este executată înainte de împărțirea cu 10. De dorit Rezultatul este obținut prin utilizarea unui plus unar înaintea parantezei, ceea ce reduce prioritatea acestora:

Imprimare +(10 + 20) / 10;

Minus unar

Minus unar(-) inversează semnul operandului numeric. Dacă operandul este un șir, atunci este returnat următorul rezultat:

  • dacă o linie începe cu un caracter „+” sau „-”, atunci, ca rezultat, acest caracter este înlocuit cu cel opus;
  • în alte cazuri, se returnează concatenarea caracterului „-” și șirul original.

În special, construcțiile -cuvânt și „-cuvânt” sunt echivalente.

Crearea unui link

Creșteți și descreșteți

Operațiile ++ și -- se numesc respectiv operații creştereȘi scăderea. Creșterea crește valoarea unei variabile numerice cu 1. Dacă este folosită ca prefix (++a), returnează valoarea operandului după ce o crește cu 1. Dacă este folosită ca postfix (a++), atunci acesta returnează valoarea operandului înainte de a-l mări cu 1. Dacă Operandul de increment este o variabilă șir care se potrivește cu modelul /^**$/ , atunci șirul este incrementat caracter cu caracter cu un wrap. Exemple:

Printează ++($x = "99"); # „100”
print ++($x = "a0"); # "a1"
print ++($x = "Az"); # "Ba"
print ++($x = "zz"); # "aaa"

Decrementarea se aplică numai variabilelor numerice și scade valoarea variabilei cu 1. Dacă această operație este folosită ca prefix (--a), atunci returnează valoarea operandului după decrementarea acestuia cu 1. Dacă este folosită ca prefix postfix (a--), apoi returnează operandul valoare înainte de a-l decrementa cu 1. Exemple:

Print --($x = 99); #98
print(($x = 99)--); #99
print --($x = "a0"); # -1

Operatori unari numiți

Operații aditive

Sunt două operatii aditive peste numere (adunare și scădere) și una peste șiruri (concatenare).

Tipăriți „1” + „2”; #3
tipăriți „1”. „2”; # „12”

Operații multiplicative

Sunt patru operatii multiplicative peste numere (înmulțire, împărțire, modulo și exponențiere) și una peste linii (repetare).

OperațiuneNumeDescriere
a*b Multiplicare Returnează produsul a doi operanzi numerici.
a/b Divizia Returnează coeficientul a doi operanzi numerici.
a % b Modulo rest Returnează restul întregului când operandul din stânga este împărțit la operandul din dreapta. Numerele flotante sunt rotunjite la numere întregi înainte de operare. Dacă b este negativ, atunci rezultatul este negativ.
a**b Exponentiație Returnează a la puterea lui b .
a x b Repetiţie Operandul din stânga trebuie să fie un șir sau o listă, operandul din dreapta trebuie să fie un număr. Returnează operandul a repetat de b ori.

Tipăriți „-” x 80; # imprimă o linie de contra
@one = (1) x 5; # @unii = (1, 1, 1, 1, 1)
@unii = (2) x @unii; # @unii = (2, 2, 2, 2, 2)

Operatori de atribuire

Operatori de atribuire atribuiți operandului din stânga rezultatul operației, care este determinat de operandul din dreapta și de operația în sine. Operația de bază de atribuire este a = b, ceea ce înseamnă: atribuiți valoarea operandului b variabilei a. Toți ceilalți operatori de atribuire sunt comenzi rapide către alți operatori combinați cu alocare, așa cum se arată în tabelul următor.

OperațiuneSens
a += b a = a + b
a -= b a = a - b
a .= b a = a. b
a *= b a = a * b
a /= b a = a/b
a %= b a = a % b
a x= b a = a x b
a**=b a=a**b
A<<= b a = a<< b
a >>= b a = a >> b
a &= b a = a & b
a |= b a = a | b
a ^= b a=a^b
a &&= b a = a && b
a ||= b a = a || b

Operatorul de atribuire returnează operandul din stânga și, prin urmare, poate fi folosit în partea stângă a următorului operator de atribuire. De exemplu

($a += 2) *= 3;

echivalent

$a += 2;
$a *= 3;

Atribuirea unei liste unei liste returnează o listă de variabile care au valori atribuite acestora. Atribuirea unei liste unui scalar returnează numărul de elemente din acea listă.

q-operații

În majoritatea limbajelor de programare, ghilimele sunt folosite pentru a forma constante de șir. Cu toate acestea, în PERL sunt operații care asigură interpolarea șirurilor și potrivirea modelelor. Vom chema astfel de operațiuni q-operații(din cuvânt englezesc ghilimele, adică ghilimele). PERL conține două seturi de operații q, enumerate în tabelul următor.

Citateq-operareSensInterpolare
"" q() Constant Nu
"" qq() Constant da
`` qx() Echipă Da (dacă delimitatorii nu sunt „”)
qw() Lista de cuvinte Nu
qr() Expresie uzuala Da (dacă delimitatorii nu sunt „”)
// m() Potrivire de model Da (dacă delimitatorii nu sunt „”)
s()() Substituţie Da (dacă delimitatorii nu sunt „”)
tr()() Transliterare Numai secvențe de evacuare

Aici, în loc de paranteze (), puteți utiliza orice caracter care nu este o literă, un număr sau un spațiu sau delimitatori perechi: (), , (),<>. Au fost date exemple de utilizare a constructelor q pentru a crea constante de șir clauza 6.2.3.2; Pentru utilizarea lor în expresiile regulate, vezi clauza 6.4.6 .

Alte operațiuni

Deaddressing

Operațiune de-adresarea are forma:

Operațiuni de conectare

Majoritatea operațiunilor cu expresii regulate operează pe variabila specială $_. Pentru potrivirea modelelor șiruri arbitrare sunt folosite operațiuni de legare, care arată astfel:

A =~ ba !~ b

unde a este orice expresie șir și b este un model de potrivire, înlocuire sau transliterare. Operația =~ returnează adevărat dacă potrivirea, înlocuirea sau transliterarea a avut succes și fals în caz contrar. Operația !~ returnează negația logică a rezultatului =~ . Pentru exemple de utilizare a acestor operații, vezi clauza 6.4.6 .

Setarea intervalului

Operațiune setarea intervalului are forma:

Acestea sunt de fapt două operațiuni diferite în funcție de context. În contextul unei liste, această operație returnează o listă de valori (a a+1 ... b) . Pentru coarde, gama se formează folosind creştere, De exemplu:

Foreach (1..10)
{
# bucle de 10 ori
}
@a = @a[$#a-4 .. $#a]; # decupează ultimele cinci elemente
@a = ("abc".."abe"); # @a = ("abc", "abd", "abe")

Într-un context scalar, această operație se comportă ca un declanșator care are două stări și returnează adevărat sau fals. Fiecare din operațiuni... își stochează propria stare. Este fals atâta timp cât operandul său din stânga este fals. Odată ce operandul din stânga este adevărat, această operație este adevărată atâta timp cât operandul din dreapta este fals. După ce operandul corect este evaluat la adevărat, această operație returnează din nou false.

Rezultatul nu devine fals până la următoarea apelare a acestei operații. Operația.. poate testa operandul din dreapta și deveni fals în același timp în care este evaluată când devine adevărat, dar va returna adevărat o dată. Dacă dorim ca acesta să nu evalueze operandul potrivit până la următoarea accesare, trebuie să folosim formularul

Altfel, operațiunile... și... sunt identice. Operandul din dreapta nu este evaluat în timp ce operația este falsă, iar operandul din stânga nu este evaluat când operația este adevărată. Valoarea de returnare a acestei operațiuni este linie goalăîn starea falsă și numerele întregi consecutive începând cu 1 în starea adevărată. Numărul de ordine este resetat pentru noul interval. LA ultimul număr se adaugă linia „E0”. Dacă oricare dintre operanzi este o constantă, atunci este implicit comparat cu variabila specială $. (conținând numărul linia curentă fila curenta). Se deschide următorul exemplu fisierul datși își imprimă liniile de la prima la a cincea.

Deschideți HANDLE, „filename.ext”;
in timp ce ( )
{
print if (1..5);
}

Funcționare condiționată

Funcționare condiționată este o operație ternară care are forma:

Test? valoare1: valoare2

unde test , value1 și value2 sunt orice expresie. Dacă testul este adevărat, atunci operația returnează value1 , în caz contrar returnează value2 . Exemplu:

Printf „Am %d alte %s.\n”, $n, ($n == 1) ? "g" : (($n< 5) ? "га" : "зей");

Această operație poate fi utilizată în partea stângă a unei operațiuni de atribuire dacă atât valoarea1 cât și valoarea2 sunt variabile, de exemplu:

($test ? $a: $b) = $c;

Operațiune virgula

Operațiune virgula face ca valorile a două expresii să fie evaluate secvențial și returnează a doua dintre ele. Arată ca:

Expr1, expr2

unde expr1 și expr2 sunt orice expresii. În liste, virgula servește ca separator pentru elementele listei.

PERL conține un sinonim pentru această operație a formei

Expr1 => expr2

Această formă este utilizată de obicei pentru elementele de listă pereche, de exemplu, la inițializarea tablourilor asociative. În plus, dacă operandul din stânga al operației => este un cuvânt, atunci acesta este interpretat ca șir (vezi clauza 6.2.7)

Ordinea operațiunilor

La evaluarea expresiilor, PERL ia în considerare prioritatea operațiunilor: Operațiile cu prioritate mai mare sunt executate mai întâi. Pentru a schimba ordinea operațiunilor, utilizați parantezele: Expresia inclusă în ele are cea mai mare prioritate. Următorul tabel listează toate operațiunile PERL în ordinea descrescătoare a priorității; operațiunile situate în același rând al tabelului au prioritate egală și se efectuează fie de la stânga la dreapta, fie de la dreapta la stânga, așa cum este indicat în tabel.

OperațiuneAsociativitatea
termeni și liste stânga
-> stânga
++ -- Nu
** dreapta
! ~\+ (unar) - (unar) dreapta
=~ !~ stânga
*/%X stânga
+ - . stânga
<< >> stânga
numiţi operatori unari Nu
< > <= >= lt gt le ge Nu
== != <=>eq ne cmp Nu
& stânga
| ^ stânga
&& stânga
|| stânga
.. ... Nu
?: dreapta
= op= dreapta
, => stânga
nu dreapta
și stânga
sau xor stânga

Există mai multe moduri de a compara obiecte în Perl. Puteți verifica egalitatea valorilor folosind operatorul infix === . Pentru obiectele imuabile (ale căror valori nu pot fi modificate, literale. De exemplu, literalul 7 va fi întotdeauna 7), aceasta comparație obișnuită valorile. De exemplu, „hello”==="hello” este întotdeauna adevărat, deoarece ambele șiruri sunt imuabile și au același sens.

Pentru obiectele mutabile, === compară identitatea acestora. === returnează adevărat dacă argumentele sale sunt aliasuri ale aceluiași obiect. Sau două obiecte sunt identice dacă sunt același obiect. Chiar dacă ambele tablouri @a și @b conțin aceleasi valori dacă containerele lor sunt obiecte diferite, vor avea identități diferite și nu vor fi identice în comparație === :

@a meu = 1, 2, 3; my @b = 1, 2, 3; spune @a === @a; # 1 spune @a === @b; # 0 # identitatea este folosită aici să spunem 3 === 3; # 1 spune "a" === "a"; #1 my $a = "a"; spune $a === "a"; #1

Operatorul eqv returnează True dacă două obiecte sunt de același tip și au aceeași structură. Deci, pentru @a și @b date în exemplu, @a eqv @b este adevărată deoarece @a și @b conțin aceleași valori. Pe de altă parte, „2” eqv 2 va returna False deoarece argumentul din stânga este un șir, iar argumentul din dreapta este un număr și astfel sunt de diferite tipuri.

La fel cum == își convertește argumentele în numere, operatorul infix eq compară egalitatea șirurilor, conversia argumentelor în șiruri, dacă este necesar.

Dacă $ salutare eq „bună ziua” (spuneți „bun venit”; )

Alți operatori compară șiruri de caractere lexicografic.

De fapt, o formă mai convenabilă este pentru !== , care, la rândul său, este o concatenare a operatorului meta! iar operatorul infix == . Aceeași explicație este valabilă pentru ne și!eq.

Operatorii de comparare în trei direcții iau doi operanzi și returnează Order::Crease dacă operandul din stânga este mai mic, Order::Lace dacă sunt egali, Order::Descrease dacă operandul din dreapta este mai mic (Order::Increase , Order::Same și Order: :Decrease sunt enumerari (vezi). Pentru comparații numerice, utilizați operatorul<=>, iar pentru coarde este leg (din engleza l esser, e qual, g reater). Operatorul cmp infix este, de asemenea, un operator de comparație care returnează trei rezultate de comparație. Particularitatea sa este că depinde de tipul de argumente: numerele sunt comparate ca<=>, șiruri ca picior și (de exemplu) perechi comparând mai întâi cheile și apoi valorile (dacă cheile sunt egale).

Spune 10<=>5; # +1 spune 10 picior 5; # deoarece „1” lt „5” spune „ab” piciorul „a”; # +1, comparație lexicografică

O utilizare tipică a operatorilor de comparație în trei căi menționați este sortarea. Metoda .sort pe liste primește un bloc sau o funcție care compară cele două argumente ale sale și returnează valori negative dacă sunt mai mici decât, 0 dacă argumentele sunt egale și mai mari decât 0 dacă primul argument este mai mare decât al doilea. Aceste rezultate sunt apoi utilizate în sortare pentru a forma rezultatul.

Spune ~ .fel; # output: abstract concret spune ~

.sort: -> $a, $b ( uc($a) leg uc($b) ); # output: abstract Concrete

Diferiți operatori de comparare își expun argumentele la anumite tipuri înainte de a le compara. Acest lucru este util atunci când este necesară o comparație specifică, dar tipurile de parametri sunt necunoscute. Perl 6 oferă un operator special care vă permite să faceți comparații Do The Right Thing folosind ~~, operatorul de comparare inteligentă.

If $pints-drunk ~~ 8 ( spuneți „Du-te acasă, te-ai săturat!”; ) if $country ~~ „Suedia” (spuneți „Chifteluțe cu lingonberries și cartofi elan, vă rog.” ) dacă $group-size ~~ 2..4 (spuneți „Trebuie să aveți între 2 și 4 persoane pentru a rezerva acest tur.”; )

Operatorul de comparație inteligentă decide întotdeauna ce fel de comparație să efectueze în funcție de tipul valorii din partea dreaptă. În exemplele anterioare, aceste comparații au fost comparații numerice, șiruri și, respectiv, intervale. Acest capitol a demonstrat funcționarea operatorilor de comparare: numere - == și șiruri de caractere eq. Cu toate acestea, nu există niciun operator pentru compararea intervalelor. Aceasta face parte din capabilitățile de comparare inteligentă: tipurile mai complexe vă permit să realizați idei neobișnuite prin combinarea comparațiilor cu altele.

Potrivirea inteligentă funcționează apelând ACCEPT pe operandul din dreapta și trecând operandul din stânga ca argument. Expresia $răspuns ~~ 42 echivalează cu apelarea 42.ACCEPTE($răspuns) . Aceste informații vă vor fi utile pe măsură ce citiți capitolele ulterioare despre clase și metode. De asemenea, veți scrie lucruri care pot efectua potriviri „inteligente”, implementând metoda ACCEPTĂ pentru a „funcționa conform așteptărilor”.

Pentru a compara datele scalare sau valorile variabilelor scalare, Perl oferă un set de operatori binari care evaluează relațiile de egalitate, mai mare decât, mai mare sau egală, etc. între operanzii lor, motiv pentru care acest grup de operatori este numit și operatori relaţionali. Perl folosește diferite operații pentru a compara datele numerice și datele șir. Toate sunt prezentate în tabel. 4.1.

Tabelul 4.1. Operațiuni de relație

Operațiune Numeric Şir Sens
Egalitatea == echivalentul Adevărat dacă operanzii sunt egali, fals în caz contrar
Inegalitate != ne Adevărat dacă operanzii nu sunt egali, fals în caz contrar
Mai puțin < lt Adevărat dacă operandul din stânga este mai mic decât operandul din dreapta, fals în caz contrar
Mai mult > GT Adevărat dacă operandul din stânga este mai mare decât operandul din dreapta, fals în caz contrar
Mai puțin sau egal <= le Adevărat dacă operandul din stânga este mai mare sau egal cu operandul din dreapta, fals în caz contrar
Mai mult sau egal >= GE Adevărat dacă operandul din dreapta este mai mare sau egal cu operandul din stânga, fals în caz contrar
Comparaţie <=> cmt 0 dacă operanzii sunt egali
1 dacă operandul din stânga este mai mare decât operandul din dreapta
-1 dacă operandul din dreapta este mai mare decât cel din stânga

Rezultatul operațiilor relaționale (cu excepția ultimei comparații) este True, valoarea 1, sau False, șirul gol „”.

cometariu
Valoarea adevărată în operațiile aritmetice este interpretată ca număr 1, iar în operațiunile cu șiruri ca șirul „1”. Valoarea falsă în operațiile aritmetice este interpretată ca număr 0, iar în operațiunile cu șiruri ca șirul gol " ".

Operații relaționale numerice

Operațiile de relații numerice sunt aplicate datelor numerice, unde unul sau ambii operanzi pot fi specificați printr-un șir care conține un număr zecimal valid. În operațiile relaționale numerice, dacă orice operand este specificat printr-un șir al cărui conținut nu reprezintă un număr zecimal valid, valoarea acestuia este setată la o și este afișat un avertisment care indică faptul că operandul nu este utilizat corect în operația relațională numerică (dacă Perl modul de avertizare este activat). Semnificația operațiilor relaționale pentru datele numerice corespunde operațiilor matematice uzuale de comparare a numerelor (exemplul 4.7).

123 > 89; # Rezultat: 1 (adevărat)

123 < 89; # Результат: "" (ложь)

123 <= 89; # Результат: "" (ложь)

89 <= 89; # Результат: 1 (истина)

23 >= 89; # Rezultat: "" (fals)

23 <=>89; # Rezultat: -1 (operandul din dreapta este mai mare decât operandul din stânga)

89 <=>23; # Rezultat: 1 (operandul din dreapta este mai mare decât operandul din stânga)

Utilizarea operațiilor de comparare numerică nu este dificilă, totuși, atunci când se compară pentru egalitatea numerelor zecimale cu virgulă mobilă, pot apărea efecte de rotunjire din cauza numărului limitat de cifre semnificative din mantisa reprezentării numerelor reale într-un computer și conducând la „ incorectă” operare a operațiunilor de comparare din punctul de vedere al utilizatorului . Exemplul 4.8 ilustrează o situație similară.

#! peri -w
$z = 0,7;

$zz = 10+0,7-10; # Variabila $zz conține numărul 0,7

# Tipăriți șirul „z equals zz” dacă valorile variabilelor $z și $zz sunt egale imprimați „z equals zz\n” dacă ($z == $zz);

Când încercăm să rulăm Exemplul 4.8, suntem surprinși să aflăm că programul nostru nu va imprima nimic. Ce s-a întâmplat? Soluția constă în operatorul de calcul al valorii variabilei $zz. La efectuarea operațiunilor aritmetice, erorile de rotunjire au ca rezultat o valoare de 0,69999999999999 (puteți introduce instrucțiunea $zz variabilă print și verifica acest lucru), deși aproape de 0,7, nu este exact egală cu aceasta. Prin urmare, operația de comparare a funcționat corect!

Sfat
Nu utilizați operatorul de comparare pentru egalitatea numerelor reale. Este posibil ca rezultatul acestuia să nu corespundă cu ceea ce este așteptat din punct de vedere matematic. Dacă trebuie să verificați egalitatea a două numere reale, atunci este mai bine să comparați valoarea absolută a diferenței lor cu un număr foarte mic (în funcție de precizia necesară):

abs($a-$b)<= 0.00000001; # Проверка равенства

Operații relaționale cu șiruri

Compararea datelor șirurilor se bazează pe ordonarea lor conform tabelului de coduri ASCII, adică un caracter cu un cod ASCII mai mic precede un caracter cu un cod ASCII mai mare. Comparațiile de șiruri sunt efectuate caracter cu caracter de la stânga la dreapta. Aceasta înseamnă că, dacă primele caractere ale liniilor sunt egale, atunci se compară al doilea, iar dacă sunt egale, se compară al treilea etc. În plus, dacă liniile sunt de lungimi diferite, atunci numărul de caractere cu codul o care lipsește pentru egalitate se adaugă la sfârșitul liniei de lungime mai mică. Trebuie remarcat faptul că, spre deosebire de alte limbaje de programare, în Perl spațiile albe din urmă sunt semnificative atunci când se compară șirurile de caractere. Exemplul 4.9 prezintă comparații de șiruri care ilustrează regulile subliniate.

„A” Este „a”; # Rezultat: adevărat (codul „A” este \101, codul „a” este \141)
„a” Este „aa”;
# cu codul \000, care este mai mic decât codul \141
# al doilea caracter „a” din șirul operandului din dreapta)
„a” Este „a”; # Rezultat: adevărat (caracterul este adăugat la șirul „a”
# cu codul \000, care este mai mic decât codul \040
# spațiu de sfârșit al șirului de operand drept)
„12” Este „9”; # Rezultat: adevărat (cod "1" - \061, cod "9" - \071)
„9” echivalentul 09”; # Rezultat: fals (cod " " - \040, cod "O" - \060)

Să acordăm atenție ultimelor două operații de comparare a literalelor șir. Conținutul operanzilor lor poate fi convertit în numere corecte și, prin urmare, li se aplică operații relaționale numerice similare. Cu toate acestea, rezultatul lor va fi semnificativ diferit de rezultatul efectuării operațiunilor de relații cu șiruri. Când utilizați operația< в предпоследнем выражении результат будет Ложь, а если в последнем выражении применить операцию ==, то результат будет Истина. Об этом всегда следует помнить, так как Perl автоматически преобразует символьные данные в числовые там, где это необходимо.

În această parte vom vorbi despre instrucțiuni și bucle condiționate.

Declarații condiționale

Ca întotdeauna, să începem imediat cu exemple.

$a = deplasare ;
dacă ($a > 10) (
imprimați „a > 10 \n";
}

Această construcție ar trebui să fie dureros de familiară programatorilor în limbaje asemănătoare C, așa că nu există prea multe de comentat aici. Permiteți-mi să spun că, spre deosebire de C, nu puteți omite bretele aici. Mai precis, există o cale, dar mai multe despre ea mai jos. Construcțiile if-else și if-else-if-... în Perl arată astfel:

$a = deplasare ;
dacă ($a > 10) (
imprimați „a > 10 \n";
) altfel (
tipăriți „a<= 10\n";
}

dacă ($a > 0 ) (
# Fă ceva
) elsif ($a == 0 ) (
# Fă ceva
) altfel (
# Fă altceva
}

În general, totul este așa cum ne așteptăm, cu o singură excepție. Nu există „altfel dacă” în Perl - în schimb ar trebui să utilizați elsif și numai atât. Elsif poate fi repetat de mai multe ori, altfel nu este necesar, iar bretele nu pot fi omise.

Spre deosebire de alte limbaje de programare, Perl oferă și o declarație unless. Următoarele două bucăți de cod fac același lucru:

cu excepția cazului în care ($a == 0 ) (
# "...cu excepția cazului în care a este zero"
...
}

dacă ($a != 0 ) (
# aceeași
# ...
}

Cu excepția cazului în care poate fi folosit în combinație cu elsif și else, dar nu există „elsunless” în Perl.

Perl are capacitatea de a reduce cantitatea de cod dacă doar o linie de cod trebuie executată atunci când este îndeplinită o condiție. Următoarele exemple fac același lucru:


dacă ($a > $b) (
ieșirea 1;
}


cu excepția cazului în care ($b == $c ) (
ieșirea 2;
}

# dacă condiția este adevărată, terminați scriptul cu codul 1
ieșire 1 dacă ($a > $b) ;
# dacă b == c, continuați execuția scriptului
ieșirea 2 dacă nu ($b == $c ) ;

Cu toate acestea, nu trebuie să utilizați paranteze în ultimul exemplu:

# dacă condiția este adevărată, terminați scriptul cu codul 1
ieșire 1 dacă $a > $b ;

Dacă scrieți în Java/PHP sau în alt limbaj asemănător C, această construcție va fi cel mai probabil neobișnuită pentru dvs., dar în practică este foarte convenabilă. În rusă, de obicei spunem și „încheiați programul dacă ...”, și nu „dacă ... atunci ...”.

La fel ca C/C++ și PHP, Perl are operator ternar?:. Funcționează în mod similar cu constructul if-else, numai în interiorul expresiilor:

dacă ($a > $b) (
$a = $a / $b ;
) altfel (
$a = $b / $a ;
}

# cod similar folosind operatorul semnului de întrebare
# o linie de cod în loc de cinci
$a = $a > $b ? $a / $b: $b / $a ;

Aș dori să spun și câteva cuvinte despre operatorii de comparație. Operatori de comparațieîn limbajul Perl ele sunt împărțite în două grupuri - cele care compară numere și compară șiruri.

După cum vă amintiți, scalarii în Perl pot fi interpretați fie ca șiruri de caractere, fie ca numere. De exemplu, numărul 123 este mai mare decât numărul 45, dar șirul „123” este mai mic decât șirul „45”. Acesta este ceea ce a necesitat mai multe grupuri de operatori de comparare. Comparația șirurilor în Perl se face în același mod ca și în alte limbaje de programare moderne, așa că sper că acest lucru nu ridică întrebări.

Bucle pentru, foreach, while/until, do..while/until

Bucla for este foarte familiară tuturor programatorilor:

# tipăriți șirul „0 1 2 3 4”
pentru ($i = 0; $i< 5 ; $i ++ ) {
imprima "$i" ;
}

Următoarele sunt scrise între paranteze separate prin punct și virgulă:

  1. Cod executat înainte de începerea buclei.
  2. Stare in curs de testare înainte de început(și nu la sfârșit, așa cum cred mulți oameni) a fiecărei iterații. Dacă este fals, bucla se termină.
  3. Cod executat după fiecare iterație.

Ca și în cazul instrucțiunilor condiționate, nu puteți omite acolade în bucle (există și o notație specială pentru aceasta - vezi mai jos).

Bucla foreach ar trebui să fie foarte familiară programatorilor PHP:

@arr = (0, 1, 2, 3, 4);
# tipăriți șirul „0 1 2 3 4”
foreach $i (@arr ) (
imprima "$i" ;
}

Corpul buclei foreach este executat pentru fiecare element al tabloului specificat în paranteze. O caracteristică importantă a foreach este în variabila $i nu copiat elementul de matrice @arr, așa cum cred mulți oameni. Variabila $i din corpul buclei este elementul de matrice în sine. Astfel, următorul cod incrementează valoarea fiecărui element al matricei @arr cu unul:

$i = 19880508 ;
foreach $i (@arr ) (
$i++;
}
# $i este încă 19880508

foreach poate fi folosit și pentru a lucra cu hashuri:

% hash = (
aaa => 1 ,
bbb => 2,
) ;
# funcția keys returnează o matrice care conține toate cheile hash
foreach $k (chei %hash ) (
tipăriți „$k => $hash($k) \n";
}

În Perl pentru buclă fiecare are o formă scurtă:

# dacă ați uitat ce face operatorul qw,
# reveniți la prima parte a „Noțiuni de bază pentru programarea Perl”
pentru $i (qw/1 2 3/ ) (
imprima "$i" ;
}

Adică, practic peste tot, în loc de foreach, poți pur și simplu să scrii pentru. Perl nu va confunda acest lucru cu o buclă for reală, deoarece aceasta din urmă necesită punct și virgulă și așa mai departe.

Buclele While, until și do funcționează exact la fel ca în C++ sau Pascal/Delphi:

# imprimați „1 2 3 4 5” în patru moduri diferite

$i = 0 ;
în timp ce ($i< 5 ) { # atâta timp cât $i este mai mic de cinci
print ++ $i . " " ;
}
imprimare " \n"; # linie nouă

$i = 0 ;
până când ($i == 5 ) ( # până când $i este egal cu cinci
print ++ $i . " " ;
}
imprimare " \n";

$i = 0 ;
face (
print ++ $i . " " ;
) în timp ce ($i< 5 ) ; # verificați la sfârșitul buclei
imprimare " \n";

$i = 0 ;
face (
print ++ $i . " " ;
) până la ($i == 5 ) ;
imprimare " \n";

Prin analogie cu declarațiile if și unless, există o formă scurtată de bucle de scriere:

$i = 0 ;
print ++ $i . " " în timp ce ($i< 5 ) ;
imprimare " \n";

$i = 0 ;
print ++ $i . " " până la ($i == 5 ) ;
imprimare " \n";

tipăriți „$_” pentru (qw/1 2 3 4 5/ ); # poti si foreach(qw/1 2 3 4 5/);
imprimare " \n";

Observați ultima buclă foreach. Ne amintim că aceasta este prescurtarea foreach, nu o buclă for, nu? Acesta din urmă, de altfel, nu are o intrare scurtă. Deci, numele variabilei cu care vom accesa elementele matricei nu a fost specificat aici. Nu poate fi folosit în notația scurtă foreach. În acest caz, se folosește o variabilă specială - $_. Următorul exemplu funcționează și el:

pentru (qw/1 2 3 4/ ) (
tipăriți „$_” ;
}

Apropo, poate fi rescris după cum urmează.

Și am învățat cum numerele și șirurile sunt convertite unul în celălalt din mers. Ne-am uitat chiar la expresie condiționată dacă, dar nu am învățat încă cum să comparăm doi scalari. Despre vom vorbi in aceasta parte.

Dacă avem două variabile $x și $y, pot fi ele comparate? Sunt 1, 1,0 și 1,00 egali? Dar „1.00”? Ce este mai mare, „foo” sau „bar”?

Două seturi de operatori de comparație

Există două seturi de operatori de comparare în Perl. La fel ca în cazul operatorilor binari de adunare (+), concatenare (.) și repetare (x) pe care i-am studiat deja, și aici operatorul determină cum se comportă operanzii și cum sunt comparați.

Aceste două seturi de operatori sunt:

Valoarea șirului numeric == eq este egală cu != ne este egală cu< lt меньше >gt mai mult<= le меньше или равно >= ge mai mare sau egal cu

Operatorii din stânga compară valori numerice, iar în dreapta (coloana din mijloc) comparați valorile pe baza tabelului ASCII sau a localizării curente.

Să ne uităm la câteva exemple:

Utilizați strict; folosiți avertismente; utilizare5.010; if (12.0 == 12) (spuneți „ADEVRAT”; ) else (spuneți „FALSE”; )

În acest caz cel mai simplu, Perl va tipări TRUE deoarece operatorul == compară două numere, deci lui Perl nu îi pasă dacă sunt scrise ca numere întregi sau numere în virgulă mobilă.

În următoarea comparație situația este puțin mai interesantă

"12.0" == 12

această expresie este de asemenea adevărată, deoarece operatorul == al lui Perl convertește un șir într-un număr.

2 < 3 истинно, так как < сравнивает два числа. 2 lt 3 также истинно, ведь 2 находистя перед 3 в Tabel ASCII. 12 > 3 este evident adevărat. 12 gt 3 va returna FALSE

Acest lucru poate părea surprinzător pentru unii la prima vedere, dar dacă vă gândiți bine, Perl compară șiruri caracter cu caracter. Așadar, compară „1” și „3”, și deoarece sunt diferite și „1” vine înaintea „3” în tabelul ASCII, în acest moment Perl decide că valoarea șirului 12 este mai mică decât valoarea șirului 3.

Trebuie să fiți întotdeauna sigur că comparați valoarea exact așa cum este necesar!

„foo” == „bar” va fi adevărat

Acest lucru va emite, de asemenea, un avertisment dacă (!) avertismentele sunt activate prin intermediul avertismentelor de utilizare . Motivul pentru aceasta este că folosim două șiruri ca numere într-o comparație numerică ==. După cum sa menționat în partea anterioară, Perl se uită la un șir care începe la capătul din stânga și îl convertește în numărul pe care îl găsește acolo. Deoarece ambele șiruri încep cu litere, ele vor fi convertite la 0. 0 == 0, deci expresia este adevărată.

Pe de alta parte:

„foo” eq „bar” fals

Prin urmare, trebuie să fiți întotdeauna sigur că comparați valoarea exact așa cum este necesar!

Același lucru se va întâmpla la comparație

„foo” == „” va fi adevărat

„foo” eq „” va fi fals

Rezultatele din acest tabel pot fi utile:

12.0 == 12 TRUE „12.0” == 12 TRUE „12.0” echivalent 12 FALSE 2< 3 ИСТИНА 2 lt 3 ИСТИНА 12 >3 ADEVĂRAT 12 gt 3 FALS! (atenție, poate să nu fie evident la prima vedere) "foo" == "" ADEVĂRAT! (Oferă un avertisment dacă este folosită pragma „avertismente”) „foo” eq „” FALSE „foo” == „bar” TRUE! (Oferă un avertisment dacă este folosită pragma „avertismente”) „foo” eq „bar” FALSE

Și, în sfârșit, un exemplu în care puteți cădea în capcana primirii unor date de la utilizator și, întrerupând cu grijă alimentarea liniei la sfârșit, verificați dacă linia este goală.

Utilizați strict; folosiți avertismente; utilizare5.010; printează „input:”; numele meu $ = ; chomp $nume; if ($nume == "") ( # incorect! aici trebuie să utilizați eq în loc de == ! spuneți „ADEVĂRAT”; ) else ( spuneți „FALSE”; )

Dacă rulăm acest script și introducem „abc”, vom obține un răspuns ADEVĂRAT deoarece perl a decis că „abc” este același cu șirul gol.

Cele mai bune articole pe această temă