94
Fundamentele programării (I) - Java DE MIHAI SCORȚARU · 10 MAI 2015 Începem acum cu adevărat seria de articole dedicate prezentării fundamentelor programării. Acesta este primul articol din versiunea Java a seriei. Dacă vă uitați la articolele corespunzătoare din versiunile dedicate celorlalte limbaje, veți observa că sunt foarte asemănătoare. Vă rugăm să nu ne acuzați de copy & pasteExistă un motiv întemeiat! Vrem să fie asemănătoare. Vrem să arătăm elementele comune ale limbajelor. Nu are rost să reformulăm doar de dragul de a prezenta lucrurile puțin diferit. De ce Java? Motivul principal pentru care Java este unul dintre limbajele alese este acela că limbajul este, în momentul scrierii articolului, cel mai folosit în industria software. Nu este un prim loc detașat și probabil nu va rămâne în frunte pentru totdeauna. Totuși, credem că va avea o viață destul de lungă și cunoașterea sa este utilă. După un start care va părea mai dificil comparativ cu alte limbaje, veți vedea că lucrurile devin din ce în ce mai simple. Se spune că în Java lucrurile funcționează de la sine, totul este intuitiv și șansele de a greși sunt mai mici. Va trebui să aveți puțină răbdare. Elementele de bază prezentate în cadrul acestui prim articol vor părea exagerat de complicate. Din fericire, trebuie să știți doar că se poate face, că așa se face și nu de ce trebuie scris atât de mult cod. Datorită faptului că este utilizat de atât de mulți programatori, multe lucruri au fost deja făcute de alții

Fundamentele programării

Embed Size (px)

DESCRIPTION

programare

Citation preview

Page 1: Fundamentele programării

Fundamentele programării (I) - JavaDE MIHAI SCORȚARU · 10 MAI 2015

Începem acum cu adevărat seria de articole dedicate prezentării fundamentelor programării. Acesta este primul articol din versiunea Java a seriei. Dacă vă uitați la articolele corespunzătoare din versiunile dedicate celorlalte limbaje, veți observa că sunt foarte asemănătoare. Vă rugăm să nu ne acuzați de copy & paste… Există un motiv întemeiat! Vrem să fie asemănătoare. Vrem să arătăm elementele comune ale limbajelor. Nu are rost să reformulăm doar de dragul de a prezenta lucrurile puțin diferit.De ce Java?Motivul principal pentru care Java este unul dintre limbajele alese este acela că limbajul este, în momentul scrierii articolului, cel mai folosit în industria software. Nu este un prim loc detașat și probabil nu va rămâne în frunte pentru totdeauna. Totuși, credem că va avea o viață destul de lungă și cunoașterea sa este utilă.

După un start care va părea mai dificil comparativ cu alte limbaje, veți vedea că lucrurile devin din ce în ce mai simple. Se spune că în Java lucrurile funcționează de la sine, totul este intuitiv și șansele de a greși sunt mai mici. Va trebui să aveți puțină răbdare. Elementele de bază prezentate în cadrul acestui prim articol vor părea exagerat de complicate. Din fericire, trebuie să știți doar că se poate face, că așa se face și nu de ce trebuie scris atât de mult cod.

Datorită faptului că este utilizat de atât de mulți programatori, multe lucruri au fost deja făcute de alții și limbajul de permite foarte ușor să folosim codul scris de alții.

Există o mulțime de tehnologii care utilizează limbajul Java. Folosind acest limbaj vom putea dezvolta aplicații software dintre cele mai diverse. Vom scrie programe care vor rula pe servere, pe calculatoarele obișnuite, pe tablete, pe telefoane sau pe diversele dispozitive portabile care sunt lansate acum pe piață. Deși este posibilă utilizarea altor limbaje, cam tot ce are legătură cu sistemul de operare Android de laGoogle va fi scris, în principiu, în Java.Mediul de programare

Page 2: Fundamentele programării

Există două medii de programare preferate în comunitatea Java: Eclipse și IntelliJ IDEA. Fiecare are avantajele sale, pe măsură ce apar versiuni noi fiecare încearcă să adauge facilități noi, dar și facilitățile deja oferite de celălalt. Chiar și în redacția Gazetei de Informatică părerile sunt împărțite. La un moment dat va trebui să alegeți unul dintre ele (sau altul dacă vă place mai mult, dar șansele sunt relativ mici). Ambele sunt disponibile pentru diverse sisteme de operare și sunt relativ ușor de instalat. Dar, instalarea acestor medii de programare depășește scopul acestui articol. Dacă știți folosi un mediu de programare (sau vă ajută cineva), o puteți face. Pentru a ne păstra neutralitatea, vom oferi o soluție alternativă care nu necesită instalare.Pe parcursul acestei serii de articole, exemplele vor fi create și rulate folosit un mediu de programare disponibil online. Sunt mai multe disponibile, așa că vom alege la întâmplare. Nu avem criterii clare după care să alegem așa că Google a ales în locul nostru. O căutare după java environment online ne-a dus lahttp://ideone.com/. E suficient de bun deocamdată. Dacă aveți motive să credeți că ar fi trebuit să alegem altceva, vă rugăm să ne atenționați…Să începem…

Page 3: Fundamentele programării

Dacă accesați site-ul veți ajunge la o pagină care arată cam așa (am eliminat elementele neesențiale):

Observați că avem deja un program scris. Acesta este un fel de program minimal în Java. Nu face nimic. Nu trebuie să înțelegeți acum ce rol au toate acele texte…Puteți apăsa butonul Run din dreapta jos și se va executa. Veți ajunge în situația din imaginea de mai jos.

Page 4: Fundamentele programării

Observăm că execuția s-a încheiat cu succes, dar în rest nu s-a întâmplat mare lucru. Totuși, vedem că adresa paginii afișate s-a modificat (în cazul nostru este http://ideone.com/gF0qHX, dar programul fiecăruia va fi disponibil la o altă adresă). Vom putea întotdeauna accesa programele scrise folosind aceste adrese.Dacă dorim să facem ceva, ar trebui totuși să modificăm acest program care nu face nimic. Pentru aceasta putem apăsa butonul edit din stânga-sus. Adresa nu se mai modifică, dar acum putem efectua modificări în program.Să înlocuim // your code goes here cu // aici trebuie scris codul. Din motive cunoscute doar de creatorii site-ului, în locul butonului Run avem un buton numit Ideone it! Apăsându-l vom rula noul program care, poate v-ați așteptat, nu va face nici el nimic. Pentru a ne păstra modificările va trebui să apăsăm butonul Save.Primul program adevărat

Page 5: Fundamentele programării

Tradiția spune că primul program scris într-un limbaj de programare nou este cel care tipărește mesajulHello World! Noi vom fi mai originali și vom tipări Gazeta de Informatică.Așa cum probabil vă imaginați, codul va fi scris în zona în care ne-am “jucat”. Vom înlocui textul // aici trebuie scris codul cu o comandă Java propriu zisă, vom salva și vom rula programul. Comanda respectivă este cea din articolul introductiv:

1 System.out.println("Gazeta de Informatică");După rulare, veți observa că în zona din partea inferioară a ecranului a apărut textul dorit.

Page 6: Fundamentele programării

 

Tocmai am realizat una dintre operațiile fundamentale efectuate de programele de calculator. Am oferit o informație în exterior. De data aceasta am scris ceva pe ecran. Programele comunică rezultatele executării lor furnizând așa numitele date de ieșire. Acestea pot lua diverse forme. Cea mai simplă este tipărirea unui simplu text, dar sunt multe altele cum ar fi tipărirea la o imprimantă, desene sau filme pe ecran, sunete în boxe etc., dar și informații codificate care nu pot fi înțelese decât de alte programe.

Date de intrare

Page 7: Fundamentele programării

Programele ne furnizează date de ieșire. De cele mai multe ori ele au nevoie de informații din exterior. Acestea le sunt comunicate prin intermediul așa numitelor date de intrare. Dacă prin intermediul datele de ieșire programele ne furnizează informații, prin intermediul datelor de intrare noi suntem cei care oferim informații. Și datele de intrare pot lua diverse forme: informații introduse de la tastatură, mișcarea mouse-ului, apăsarea butoanelor mouse-ului, apăsarea unui touchscreen, rostirea în microfon, etc. Poate vă imaginați că acele informații codificate pe care le menționam la sfârșitul secțiunii anterioare, cele care nu pot fi înțelese decât de alte programe, reprezintă date de intrare pentru aceste alte programe.

Dar, să ne concentrăm asupra unui exemplu simplu. Vom cere numele utilizatorului și îl vom saluta. Utilizatorul își va introduce numele și după aceea va apărea mesajul Salut, urmat de nume și de un semn de exclamare. Ca să arate totul bine, vom adăuga și un spațiu înaintea numelui. De exemplu, dacă utilizatorul ar introduce numele GInfo, mesajul ar fi Salut GInfo!.Vi se părea complicată comanda prin care era afișat un text. Să vedeți acum…

1 String nume = new Scanner(System.in).nextLine();Site-ul ne permite să specificăm date de intrare sub forma unor text înainte de a rula programul. Acestea trebuie introduse în caseta din partea inferioară:

Page 8: Fundamentele programării

Dacă rulăm programul, observăm că este afișat mesajul ales.

Page 9: Fundamentele programării

În episoadele următoare veți înțelege ce este acel String, ce este acel nume și, mult mai încolo, ce este un Scanner…Deocamdată, singura observație demnă a fi luată în considerare este aceea că, în Java, fiecare instrucțiune se încheie cu semnul punct și virgulă.

Va urmaFundamentele programării (II) - JavaDE MIHAI SCORȚARU · 11 MAI 2015

În cadrul acestui episod vom introduce noțiunile de variabilă și tip de date și vom lucra cu numere și texte. Vom presupune că deja știți să

Page 10: Fundamentele programării

utilizați un mediu de programare (fie el și online); dacă nu, vă recomandăm să citiți din nou episodul anterior.VariabileChiar și pentru cele mai simple programe, la un moment dat avem nevoie să păstrăm anumite informații. Nu am avut nevoie de acest lucru atunci când doar am afișat un mesaj, dar atunci când am avut nevoie de numele utilizatorului a trebuit să păstrăm informația respectivă. Să ne amintim ultimul program de data trecută:

123456789101112131415

/* package whatever; // don't place package name! */ import java.util.*;import java.lang.*;import java.io.*; /* Name of the class has to be "Main" only if the class is public. */class Ideone{  public static void main (String[] args) throws java.lang.Exception  {    String nume = new Scanner(System.in).nextLine();    System.out.println("Salut " + nume + "!");  }}

În linia 12, avem o instrucțiune prin care preluăm informația introdusă de utilizator și o păstrăm în ceva de numit nume. Aceasta este o așa numită variabilă.Variabilele pot fi văzute ca fiind niște recipiente care păstrează informații. Practic, cu ajutorul lor ajungem undeva în memoria calculatorului, luăm o mică parte din ea și îi dăm o denumire pentru a o putea folosi ulterior.

Avem nevoie de variabile pentru cele mai diverse scopuri. Dacă scriem un program care controlează un roboțel, vom avea nevoie de variabile care să conțină poziția acestuia, orientarea sa etc. În schimb, dacă programul nostru simulează un joc de fotbal, am avea nevoie de variabile pentru a păstra scorul.

Page 11: Fundamentele programării

În principiu, dacă trebuie să ținem minte ceva, cel mai simplu este să punem acel ceva într-o variabilă.

Majoritatea limbajelor moderne necesită declararea unei variabile înainte ca aceasta să poată fi utilizată.Java este un astfel de limbaj. Mai mult, limbajul Java ne obligă să specificăm și ce tip de variabilă dorim.Dacă revenim la linia 12 a programului nostru, observăm că înaintea denumirii nume, apare cuvântulString. Acesta este tipul variabilei nume. Vom vedea exact ce înseamnă puțin mai încolo.În Java, pentru a declara o variabilă, trebuie să precizăm tipul acesteia, urmat de denumirea sa. Pentru un meci de fotbal, am putea avea o variabilă declarată astfel:

1 int goluriGazde;Tipul este int (vom vedea ce înseamnă), iar denumirea este goluriGazde (vom vedea și de ce denumirea arată oarecum ciudat). Urmează semnul ;, cel care separă instrucțiunile în Java. Deci, declararea unei variabile este o instrucțiune.Termenul variabilă implică faptul că ea se poate modifica. Prin diverse mecanisme, informația conținută de o variabilă se poate schimba în timpul execuției programului. De exemplu, într-un joc de fotbal, la începutul unui meci variabila care ar păstra numărul golurilor marcate de echipa gazdă ar conține informația 0. Dar, dacă echipa marchează un gol, informația respectivă trebuie să devină 1. Dacă se mai marchează unul, variabila va conține informația 2 și așa mai departe. Dar, dacă începe un joc nou, informația redevine 0. Această informație păstrată de către variabilă poartă denumirea de valoare a variabilei.În Java, este posibil ca în momentul declarării unei variabile să precizăm și ce valoare dorim să aibă la început. Pentru aceasta, după denumirea ei (înainte de ;) adăugăm semnul =, urmat de valoarea dorită. O astfel de declarație ar putea fi:

1 int goluriGazde = 0;

Page 12: Fundamentele programării

Spunem că o astfel de variabilă este inițializată.TipuriAm spus că în Java variabilele au tipuri. Tipul unei variabile indică ce fel de informație poate conține variabila respectivă. În exemplul nostru tipul este int; el arată că variabila noastră este un număr întreg. Dacă o variabilă are un anumit tip, atunci informația conținută trebuie să fie compatibilă cu acel tip. Putem scrie:

1 int goluriGazde = 2457;Chiar dacă este puțin probabil să găsim vreun sport în care o echipă să marcheze 2457 de goluri, instrucțiunea este corectă fiindcă, din punctul de vedere al calculatorului, goluriGazde este un număr întreg și valoarea sa poate fi orice număr întreg acceptabil (vom vedea mai încolo că există anumite restricții).Totuși, nu putem scrie:

1 int goluriGazde = "GInfo";GInfo este în acest caz un text (vom vedea puțin mai târziu rolul ghilimelelor) și variabila goluriGazdenu poate conține decât numere întregi.Variabilele pot avea diverse tipuri: ele pot fi numere întregi, numere cu zecimale (acestea sunt denumite uneori numere reale, dar nu e chiar corect), texte etc. Dar putem avea și tipuri mult mai complexe; putem avea variabile care reprezintă clădiri, animale, galaxii, atomi și așa mai departe.

Unele tipuri sunt disponibile direct, altele trebuie inventate. Cele disponibile pot fi utilizate imediat; cele create deja de alții pot fi și ele utilizate. Dar, tipurile noi trebuie întâi definite.

În Java, tipurile disponibile imediat poartă denumirea de primitive. Acestea sunt byte, short, int, long,float, double, char și boolean. Primele patru pot conține numere întregi (vom vedea de ce sunt mai multe),

Page 13: Fundamentele programării

următoarele două pot conține numere cu zecimale, următorul un așa numit caracter, iar ultimul doar o valoare de adevăr (adevărat sau fals).Iată câteva exemple de declarații (împreună cu inițializările):

1234

int a = 5;double b = 5.1;char c = '+';boolean d = true;Avem așadar un număr întreg a care are deocamdată valoarea 5, un număr cu zecimale b care are valoarea 5.1, un caracter c care are valoarea + și un așa numit boolean d cu valoarea true (adevărat), valorile booleene trebuie scrise în engleză și pot fi true sau false.Mai avem un tip special, aproape primitiv din anumite puncte de vedere, numit String. VariabileleString conțin șiruri de caractere (mai multe caractere într-o anumită ordine).De obicei, string-urile conțin texte, iar caracterele sunt litere, cifre, semne de punctuație etc. Vom vedea în viitor că aceste caractere pot reprezenta și alte lucruri, dar deocamdată să considerăm string-urile ca fiind texte.

Un exemplu pentru declararea și inițializarea unei variabile de tip String ar fi:

1 String s = "GInfo";Despre tipurile mai complicate vom discuta cu altă ocazie.

NumereAm spus că în Java există mai multe feluri de numere și chiar mai multe feluri de numere întregi. Știm că avem o infinitate de numere întregi. Pentru numere foarte mari, noi am nevoie să scriem multe cifre; la fel, calculatoarele ar avea nevoie să folosească tot mai multă memorie pe măsură ce numerele sunt mai mari. Dar, memoria calculatoarelor este finită. Diferitele variante de numere întregi ne spun cam câtă memorie dorim să utilizăm. Din acest motiv, pentru fiecare tip vom putea avea valori care nu depășesc o valoare maximă, specifică tipului. Semnul unui număr întreg

Page 14: Fundamentele programării

e și el în memorie, deci putem avea și numere negative. Dar, datorită memoriei limitate, numerele trebuie să fie mai mari decât o valoare minimă specifică tipului.Pare complicat și ciudat, dar nu e chiar așa. În practică nu utilizăm numere foarte mari. În cele mai multe situații este suficient tipul int (valoarea maximă este 231 - 1, adică două miliarde și ceva). Uneori nu este suficient și avem nevoie de long. Valoarea maximă este 263 - 1, adică aproape zece miliarde de miliarde. Dacă avem nevoie de valori și mai mari e mai complicat, dar sunt soluții.Am văzut cum declarăm o variabilă și cum o inițializăm. Dar, am spus că valorile variabilelor se pot modifica. Pentru aceasta avem nevoie de o instrucțiune. O astfel de instrucțiune arată așa:

1 a = 2457;Valoarea variabilei a va fi acum 2457 indiferent care a fost înainte. Informația înlocuită se pierde. Nu vom ști cât a fost acea valoare înainte, deci dacă avem nevoie de ea, ar fi fost bine să o punem altundeva (într-o altă variabilă de exemplu).Instrucțiunea anterioară este validă numai dacă a este într-adevăr o variabilă de tip numeric. Ea trebuie să fi fost declarată anterior (nu neapărat și inițializată).

Să nu credeți că a = 2457; este o ecuație sau ceva asemănător; este o comandă. Calculatorului i se spune ca în zona de memorie corespunzătoare variabilei a să fie pusă valoarea 2457. O astfel de comandă se numește atribuire.Printr-o instrucțiune de atribuire, unei variabile i se dă o valoare. Tipul acestei valori trebuie să fie compatibil cu cel al variabilei (vom vedea ulterior de ce, în unele cazuri, e posibil ca tipurile să nu fie chiar identice).

Așadar, o instrucțiune de atribuire conține denumirea variabilei care va primi valoarea, urmată se semnul =și apoi de valoarea propriu zisă. În cazul nostru, valoarea a fost numărul 2457.Există mai multe modalități de a reprezenta numerele; 2457 este varianta care ni se pare nouă naturală; nu e nicio șmecherie, e chiar numărul care urmează după 2456 și e înainte de 2458. Fără să explicăm de ce și doar

Page 15: Fundamentele programării

pentru a arăta că se poate și altfel dacă chiar vrem, același număr poate fi reprezentat prin0x999. Instrucțiunea următoare are exact același efect:

1 a = 0x999;În Java, numerele sunt numere simple dacă nu apare nimic altceva lipit de ele. Alte simboluri sau caractere le modifică semnificația. Partea 999 din 0x999 nu reprezintă deloc numărul 999; ne-am aștepta ca 02457 și 2457 să reprezinte același lucru, dar nu e așa.Lucrurile pot deveni și mai ciudate: 2, '2' și "2" sunt complet diferite. Primul este numărul 2, al doilea este un caracter care reprezintă cifra 2 și al treilea este un string. Mai multe despre caractere și string-uri în secțiunea următoare.Numerele cu zecimale pot și ele fi reprezentate așa cum ni se pare nouă natural; 2.5 este o valoare corectă; dar, putem avea și ciudățenii ca 1e-4 sau 5D.Nu dorim să explicăm aceste lucruri care par bizare; dorim doar să atragem atenția că în multe cazuri lucrurile nu sunt ceea ce par.

Caractere și string-uriÎn Java un caracter reprezintă un simbol. Poate fi o literă, o cifră, un semn de punctuație, un operator matematic etc. În Java valoarea unui caracter este cuprinsă între apostroafe. În principiu, avem un apostrof, un semn și apoi un alt apostrof. De exemplu, caracterul + trebuie scris '+'.Dar, ce ne facem dacă vrem să avem chiar valoarea apostrof? Ați putea crede că ''' este soluția, dar nu e chiar așa. Al doilea apostrof este interpretat ca fiind sfârșitul elementelor care descriu caracterul și al treilea nu mai este înțeles. Ca urmare, instrucțiunea c = '''; nu este corectă.Ni se oferă o soluție… Putem marca al doilea apostrof cu un simbol special care să indice faptul că acesta nu trebuie interpretat ca sfârșit al descrierii caracterului, ci ca semn propriu-zis. Elementul special este \(backslash). Varianta corectă a instrucțiunii este:

Page 16: Fundamentele programării

1 c = '\'';Ar părea că ni s-au rezolvat toate problemele, dar… dacă avem nevoie fix de backslash? c = '\'; nu e corect fiindcă backslash-ul indică faptul că următorul element trebuie interpretat ca fiind semnul apostrof. Soluți este să marcăm semnul backslash cu un alt backslash. Deci, pentru a atribui unei variabile valoarea \, va trebui să scriem:

1 c = '\\';String-urile sunt cuprinse între ghilimele. Ați ghicit probabil, dacă unul dintre caracterele string-ului este chiar ", avem o problemă. Probabil intuiți soluția, vom marca astfel de caractere cu backslash. Dispare problema cu apostroful (nu mai trebuie marcat) și este în continuare prezentă cea cu backslash-ul (trebuie și aici dublat).Dar… avem probleme suplimentare. Spuneam că string-urile sunt folosite în special pentru a păstra valori care reprezintă texte. Și textele pot avea mai multe linii. Cum facem?

Dacă scriem:

123

s = "GazetadeInformatică";vom vedea că nu e corect.

Avem conceptul de caracter special de sfârșit de linie. Dacă dorim să avem textul Gazeta de Informatică scris pe trei rânduri (câte un cuvânt pe o linie), vom scrie:

1 s = "Gazeta\nde\nInformatică";

Page 17: Fundamentele programării

Fundamentele programării (III) - JavaDE MIHAI SCORȚARU · 18 MAI 2015

Cel de-al treilea episod al serialului dedicat fundamentelor programării va prezenta detalii legate de modul în care sunt executate diverse operații. De asemenea, vom vedea cum putrem adăuga informații suplimentare care nu afectează deloc modul în care sunt executate programele, dar ajută la înțelegerea acestora.

Altfel de atribuiriÎn cadrul episodului anterior am văzut cum putem modifica valoarea unei variabile cu ajutorul instrucțiunii de atribuire. Dar, toate atribuirile pe care le-am prezentat nu făceau decât să dea unei variabile o simplă valoare.

Limbajele ne permit mult mai mult. De exemplu, am putea să atribuim unei variabile valoarea altei variabile. Să considerăm următoarea secvență:

1234

int a;int b;a = 3;b = a;

În urma executării acestor instrucțiuni, atât variabila a, cât și variabila b, vor avea valoarea 3. Instrucțiunea din linia 4 indică faptul că variabilei b trebuie să i se atribuie valoarea variabilei a. Cele două variabile sunt în continuare independente. Dacă am continua programul cu a = 5; doar valoarea variabilei a se va modifica; valoarea variabilei b va rămâne 3.Să facem acum un mic exercițiu. Să presupunem că avem două variabile a și b care conțin două valori diferite (pentru exemplul nostru vom considera că acestea sunt 2 și 4). Dorim să scriem un program care schimbă între ele cele două valori. Cele două variabile vor fi declarate și inițializate astfel:

Page 18: Fundamentele programării

12

int a = 2;int b = 4;Evident, pentru a rezolva problema, am putea scrie:

12

a = 4;b = 2;Dar, să ne închipuim că dorim ca programul să funcționeze corect indiferent care sunt valorile inițiale (de exemplu, am putea presupune că ele sunt introduse de utilizator și în momentul scrierii programului nu știm care vor fi.

Având în vedere că tocmai am prezentat cum unei variabile i se poate stribui valoarea altei variabile, ne-am putea gândi la o soluție de genul:

12

a = b;b = a;Dar, să vedem ceva ce se întâmplă; inițial a are valoare 2 și b are valoarea 4. Prin instrucțiunea a = b;variabilei a i se stribuie valoarea curentă a variabilei b, adică 4. Așa cum am spus în cadrul episodului anterior, valoarea 2 se pierde. Cea de-a doua instrucțiune face ca variabilei b să i se atribuie valoarea variabilei a; dar această valoare este acum 4, deci în urma executării instrucțiunii, valoarea variabilei b va fi tot 4. Astfel, ajungem să avem aceeași valoare pentru ambele variabile și nu am schimbat valorile între ele.Am spus că variabilele pot fi privite ca fiind niște recipiente. Să ne imaginem că cele două variabile ar fi două pahare pline cu lichide diferite și dorim să schimbăm lichidele între ele. Pentru a putea muta lichidul dintr-un pahar în altul, va trebui să vărsăm lichidul dintr-un pahar pentru a face loc. În principiu, lichidul se pierde în acest mod. Dar, l-am putea vărsa într-un al treilea pahar, nu?

Page 19: Fundamentele programării

Atunci, pentru a schimba lichidele între ele, vom lua un al treilea pahar, vom turna în el lichidul din primul pahar, apoi vom turna în primul pahar lichidul din al doilea și, la final, vom turna în al doilea pahar lichidul din cel de-al treilea. Astfel, în primul pahar vom avea lichidul care a fost inițial în al doilea, iar în al doilea pahar vom avea lichidul care a fost inițial în primul.

Ne dăm seama destul de ușor că pentru a schimba valorile a două variabile, avem nevoie de o a treia variabilă (ajutătoare). Secvența care schimbă valorile ar putea fi:

123

int c = a;a = b;b = c;Am declarat variabila c și am și inițializat-o. După cum se vede și la inițializare e la fel ca la atribuire, Putem inițializa o variabilă cu valoarea altei variabile.

Prima operațieTotuși, până acum doar am declarat variabile, le-am dat valori și ne-am jucat puțin cu ele. Dar, lucrăm cu un calculator; la un moment dat ar trebui să facem și niște calcule, nu? Deși pare că e cam târziu fiindcă suntem deja la al treilea episod, vom realiza acum prima adunare. Presupunem că două variabile au anumite valori pe care dorim să le adunăm și să păstrăm rezultatul într-o a treia variabilă. Nu e nicio mare filosofie, codul arată cam cum v-ați aștepta;

123456

int a;int b;int c;a = 2;b = 4;c = a + b;

Nu e nicio surpriză, valoarea variabilei c va fi 6. Dar, vedem că am atribuit variabilei c altceva, nu o simplă valoare și nici valoarea unei alte variabile. Am cerut efectuarea unui calcul, a unei operații; descrierea acestei operații

Page 20: Fundamentele programării

poartă denumirea de expresie. De fapt, și anterior am folosit tot expresii, dar foarte simple. Valoarea simplă este și ea o expresie, la fel și valoarea unei variabile.Așa cum putem atribui unei variabile o expresie, la fel putem și inițializa o variabilă cu o expresie. Codul de mai jos are același efect ca cel anterior:

123

int a = 2;int b = 4;int c = a + b;

ExpresiiExpresille pot fi foarte complexe. Ele pot conține valori simple, valori ale unor variabile, operatori și multe altele. De exemplu, putem aduna trei numere, dintre care doar două sunt păstrate în variabile, iar al treilea este o valoare simplă:

123

int a = 2;int b = 4;int c = a + b + 1;

Așa cum vă așteptați, putem realiza și alte operații matematice. Pentru scăderi și înmulțiri nu avem nicio surpriza. La împărțire lucrurile sunt mai complicate și vom reveni.

Pentru înmulțire, operatorul folosit este *; putem efectua o înmulțire astfel:

123

int a = 2;int b = 4;int c = a * b;

Putem combina operațiile și regulile matematice se aplică:

Page 21: Fundamentele programării

123

int a = 2; int b = 4; int c = 3 + a * b;

Valoarea variabilei c va fi 11. Dacă dorim să modificăm ordinea firească a operațiilor, putem folosi paranteze:

123

int a = 2; int b = 4; int c = (3 + a) * b;

În acest caz valoarea variabilei c va fi 20. Putem avea și paranteze în paranteze, dar nu chiar ca la matematică. Nu folosim paranteze drepte sau acolade. Toate parantezele sunt rotunde:

123

int a = 2; int b = 4; int c = (3 + a * (a - 2)) * b;

De data aceasta c va avea valoarea 12. Prima dată se calculează valoarea a - 2; rezultatul este 0. Urmează înmulțirea valorii variabilei a cu acest rezultat fiindcă înmulțirile se efectuează înaintea adunărilor dacă nu sunt paranteze; noul rezultat este tot 0. Urmează adunarea între 3 și acest rezultat (obținem 3), iar apoi înmulțirea cu b care duce la rezultatul final: 12.ÎmpărțireaDacă împărțim numărul 3 la 2 spunem fie că rezultatul este 1.5, fie că obținem câtul 1 și restul 1. În Java, dacă împărțim două numere întregi, rezultatul operației este câtul, iar operatorul folosit este /. Dacă unul dintre numere este cu zecimale, atunci rezultatul este și el cu zecimale, nu doar câtul. Să vedem un exemplu:

123

int a = 3; int b = 2; int c = a / b;

Valoarea variabilei c va fi 1. Dar, dacă avem:

Page 22: Fundamentele programării

123

double a = 3; double b = 2; double c = a / b;

valoarea variabilei c va fi 1.5. Rezultatul va fi cu zecimale, dacă cel puțin unul dintre cele două numere este cu zecimale. De exemplu, și în următorul caz rezultatul este tot 1.5:

123

double a = 3; int b = 2; double c = a / b;

La fel stau lucrurile în situația următoare:

123

int a = 3; double b = 2; double c = a / b;

Însă, dacă cele două numere împărțite sunt întregi, rezultatul este 1, chiar dacă variabila căreia i-l atribuim reprezintă un număr cu zecimale:

123

int a = 3; int b = 2; double c = a / b;

Putem face experimente mai interesante. Nu trebuie să folosim neapărat variabile; valorile simple sunt suficiente. Încercați să vă dați seama ce valori vor avea variabilele declarate astfel:

1234

double a = 3 / 2;double b = 3 / 2.0;double c = 3.0 / 2;double d = 3.0 / 2.0;

Page 23: Fundamentele programării

În Java, dacă scriem 2, numărul este întreg, dar dacă scriem 2.0 el este considerat cu zecimale (partea fracționară fiind 0). Pe baza acestei informații ne dăm seama destul de ușor că valoarea variabilei a va fi 1, iar celelalte trei vor avea valoarea 1.5.Spuneam că dacă împărțim două numere întregi, rezultatul va fi câtul operației matematice. Ni se oferă și posibilitatea de a afla restul. Pentru aceasta vom folosi un alt operator, anume %.  În situația:

123

int a = 5; int b = 3; int c = a % b;

valoarea variabilei c va fi 2.Deși e oarecum bizar, operatorul % poate fi folosit și pentru numere cu zecimale. Rezultatul este tot un fel de rest; se calculează partea întreagă a împărțirii și rezultatul este dat de "ce rămâne". Să vedem un exemplu:

123

double a = 8; double b = 2.5; double c = a % b;

Valoarea variabilei c va fi 0.5. Partea întreagă a împărțirii este 3; pentru acest rezultat se "consumă" 7.5din 8 și "rămâne" 0.5.Am văzut că putem transforma un număr întreg în unul cu zecimale adăugând .0. Avem și alternative: putem adăuga f, F, d sau D. Spuneam că numerele sunt numere simple dacă nu apare nimic legat de ele. Dacă adăugăm una dintre aceste litere schimbăm semnificația. Practic, transformăm un număr întreg într-unul cu zecimale. În Java avem două tipuri pentru astfel de numere: float și double. Dacă adăugăm fsau F, numărul este considerat a fi de tip float; dacă adăugăm d sau D, el este considerat a fi de tipdouble. Deocamdată nu are relevanță dacă avem float sau double...Operații logicePutem efectua operații și cu variabilele booleene. Chiar dacă au doar două valori posibile, există operații care pot fi efectuate. În primul rând avem negația; este o

Page 24: Fundamentele programării

operație prin care adevărul devine fals și falsul devine adevăr. Operatorul este !; să îl folosim în cele două posibile situații:

1234

boolean a = true; boolean b = false; boolean c = !a;boolean d = !b;

Valoarea variabilei c va fi false, iar cea a variabilei d va fi true.Dar, avem și operații puțin mai complicate.

De exemplu, putem efectua o operație care să ne spună dacă două valori booleene sunt ambele adevărate. Operația se numește ȘI; mai riguros, ea este numită conjuncție. Să vedem un exemplu:

12345

boolean a = true; boolean b = true;boolean c = false; boolean d = a & b;boolean e = a & c;

Probabil v-ați dat seama, operatorul este &. Valoarea variabilei d va fi true, iar cea a variabilei e va fifalse.O altă operație pe care o avem la dispoziție ne spune dacă cel puțin una dintre două valori booleene este adevărată. Operația se numește SAU; mai riguros, ea este numită disjuncție. De data aceasta operatorul este |.  Să vedem acum câteva variante:

1234567

boolean a = true; boolean b = true;boolean c = false;boolean d = false; boolean e = a | b;boolean f = a | c;boolean g = c | d;

Doar g va avea valoarea false, fiindcă atât c, cât și d, au valoarea false. e și f vor avea valoarea truefiindcă cel puțin una

Page 25: Fundamentele programării

dintre cele două variabile asupra căreia este efectuată operația are valoarea true(ambele pentru e, doar prima pentru f).Acest SAU logic nu prea seamănă cu cel pe care îl folosim natural. De exemplu, dacă spunem că vrem o rochie roșie sau albastră, vrem să spunem că rochia poate fi fie roșie, fie albastră. Nu vrem să spunem că rochia poate fi și roșie și albastră; nu vrem nici să spunem că dorim două rochii, una roșie și una albastră (deși poate nu ar deranja pe nimeni). Un alt exemplu ar fi când spunem că dorim banane sau portocale; vrem una dintre cele două variante, nu amândouă.Există o operație logică al cărei rezultat ne spune dacă exact una dintre cele două valori booleene este adevărată. Rezultatul este false dacă ambele valori sunt true sau dacă ambele valori sunt false. Acest sau natural este numit SAU EXCLUSIV sau disjuncție exclusivă. Operatorul este ^; să vedem exemplul:

1234567

boolean a = true; boolean b = true;boolean c = false;boolean d = false; boolean e = a ^ b;boolean f = a ^ c;boolean g = c ^ d;

Doar f va avea valoarea true, fiindcă a are valoarea true și c are valoarea false. e și g vor avea valoarea false fiindcă ambele variabile asupra căreia este efectuată operația au aceeași valoare (truepentru e, false pentru g).Operații cu string-uriOperatorul + poate fi utilizat și pentru string-uri. Aplicat asupra a două varioabile de tip String, operatorul duce la unirea acestora. De exemplu, rezultatul operației "alpha" + "beta" este"alphabeta". Operația poartă denumirea de concatenare. Ne putem reaminti de o instrucțiune din programul din primul episod:

1 System.out.println("Salut " + nume + "!");

Page 26: Fundamentele programării

Aici avem o concatenare de trei string-uri.Rezultatul concatenării unor string-uri are tipul String. Dar, putem aplica operatorul + și în cazul în care doar una dintre cele două valori are tipul String, iar rezultatul este cel pe care îl așteptăm. Iată câteva exemple:

1234567

String a = "ceva"; int b = 2;double c = 3;boolean d = false;String e = a + b;String f = c + a;String g = a + d;

Valoarea variabilei e va fi ceva2, cea a variabilei f va fi 3.0ceva, iar cea a variabilei g va fi cevafalse.3.0ceva pare cam ciudat; nu e 3ceva fiindcă numerele cu zecimale apar cu zecimale chiar dacă partea fracționară lipsește.Atribuiri mai interesanteCe-ați zice dacă o variabilă ar apărea de ambele părți ale semnului = ale unei instrucțiuni de atribuire. Următoarea secvență este validă, dar nu prea interesantă fiindcă nu se întâmplă nimic special:

12

int a = 1;a = a;Totuși, am putea avea o expresie în dreapta. De exemplu:

12

int a = 1;a = a + 1;Dacă a = a + 1 ar fi fost o ecuație, așa ceva nu ar avea sens. Dar, instrucțiunea de mai sus se traduce astfel: preia valoarea variabilei a, adună 1 și pune rezultatul în variabila a. Inițial a are valoarea 1, adunăm1 și obținem 2 și a primește valoarea 2. Faptul că acest lucru este posibil este foarte util. Vă mai amintiți exemplul cu

Page 27: Fundamentele programării

variabila goluriGazde care conține numărul golurilor înscrise de echipa gazdă într-un meci de fotbal. În momentul în care echipa gazdă marchează un gol, valoarea acestei variabile trebuie să devină mai mare cu 1. Am putea scrie:

1 goluriGazde = goluriGazde + 1;De fapt, astfel de instrucțiuni sunt atât de des folosite, încât ni se oferă posibilitatea să o scriem și prescurtat. Următoarea instrucțiune este echivalentă:

1 goluriGazde += 1;Mai mult, atât de des este nevoie ca valoarea unei variabile să fie mărită cu exact 1, încât avem la dispoziție o prescurtare suplimentară:

1 goluriGazde++;Există și varianta ++goluriGazde, care are același efect. Pentru a explica diferența sunt necesare cunoștințe mai avansate; deocamdată vom considera că cele două variante sunt echivalente. Operația prin care valoarea unei variabile crește cu 1 este numită incrementare.Pentru majoritatea operatorilor avem variante prescurtate: există -=, *=, /=, %=, &=, |= și multe altele.Avem o prescurtare suplimentară și pentru decrementare (valoarea unei variabile scade cu 1). Operatorul corespunzător este --; el poate apărea înainte sau după variabilă.Despre spațiiÎn cadrul diverselor secvențe de cod prezentate până acum ați văzut că, în cadrul instrucțiunilor, diverse elemente sunt separate prin spații. Aceste spații pot lipsi de cele mai multe ori și, în marea majoritate a cazurilor, putem pune oricâte spații.

Page 28: Fundamentele programării

Spațiul este obligatoriul doar dacă absența sa ar crea confuzii. De exemplu, există o mare diferență întreint a = 2  și inta = 2 . Prima variantă declară o variabilă a și o inițializează cu valoarea 2. Cea de-a doua atribuie variabilei inta valoarea 2. Dacă o astfel de variabilă nu a fost declarată anterior, atunci instrucțiunea nu este validă. Dar, de exemplu, putem elimina spațiile din jurul operatorului =; varianta inta=2  reprezintă o declarație cu inițializare validă. Putem pune și mai multe spații dacă dorim:

1 int   a            =2;Nu arată foarte bine, dar este corect. De fapt, de cele mai multe ori modul în care utilizăm spațiile are rol estetic; ne ajută să vedem mai ușor codul.

Pentru a separa elementele limbajului, putem folosi și taburi sau putem trece pe o linie nouă. Nu prea putem ilustra aici taburile (ar arăta tot ca niște spații), dar putem ilustra folosirea mai multor linii:

12345

int        a              =2 ;

Din nou, parcă nu am vrea să arate așa codul nostru, dar este permis. După cum vedeți, am folosit și multe linii și multe spații.

Simbolurile care nu se văd și sunt folosite pentru a separa diverse elemente poartă denumirea decaractere albe. Deocamdată am văzut că astfel de caractere sunt spațiile, taburile și marcajele de sfârșit de linie.Trebuie precizat faptul că în interiorul string-urilor caracterele albe își păstrează semnificația. De exemplu, string-urile "a   b" și "a b" sunt diferite.ComentariiUneori scriem cod pe care dorim să nu îl mai folosim deocamdată, dar poate vom avea nevoie în viitor. Putem marca acest cod astfel

Page 29: Fundamentele programării

încât el să nu se execute. Porțiunile marcate astfel poartă denumirea decomentarii.În Java avem două tipuri de comentarii. Pe o linie, putem pune secvența // și tot ce urmează după ea este comentariu.Putem folosi și comentarii pe mai multe linii. Vom marca începutul comentariului prin /* și sfârșitul său prin */.Dacă // sau /* apar în interiorul unui string, atunci își pierd semnificația. De exemplu String s = "a//a"; este o instrucțiune care inițializează string-ul s cu valoarea a//a. La fel, nu avem un comentariu în instrucțiunea String s = "a/*a";.Dar, putem folosi comentariile nu numai pentru a elimina temporar cod, ci și pentru a-l explica. Când altcineva citește codul nostru, îi va fi mult mai ușor să înțeleagă dacă acesta conține explicații. Acel "altcineva" poate fi chiar persoana care a scris codul, o lună mai târziu. În multe cazuri ne va fi foarte greu să ne dăm seama ce și cum am vrut să facem.

Trebuie să fim puțin atenți în câteva situații. Să presupunem că avem următorul cod:

123456

int a = 1;int b = 2;int c = 3;int d = 4;int e = 5;int f = 6;

Să presupunem că nu mai avem nevoie de variabilele c și d. Am putea comenta liniile corespunzătoare:

123456

int a = 1;int b = 2;/*int c = 3;int d = 4;*/int e = 5;int f = 6;

Dacă dorim să arate mai frumos, am putea și așa:

Page 30: Fundamentele programării

12345678

int a = 1;int b = 2;/*int c = 3;int d = 4;*/int e = 5;int f = 6;

Acum să presupunem că am dori să scăpăm și de variabilele b și e. Soluția care pare la îndemână ar fi:

12345678910

int a = 1;/*int b = 2;/*int c = 3;int d = 4;*/int e = 5;*/int f = 6;

Dar... nu am luat în considerare faptul că ce apare în interiorul comentariului este ignorat până în momentul în care este întâlnită secvența care marchează sfârșitul comentariului. Comentariul nostru începe pe linia 2 și secvența de sfârșit este întâlnită pe linia 7. Secvența de pe linia 9 este acum invalidă.

Un alt exemplu interesant ar putea fi următorul:

123

/*Operatorii admiși sunt +-*/%*/Am putea crede că avem un simplu comentariu care ne spune care sunt operatorii permiși într-o anumită situație. Dar, înșirurirea operatorilor conține secvența */ care indică sfârșitul comentariului. Ce rămâne nu mai este corect.

Page 31: Fundamentele programării

Va urmaFundamentele programării (IV) - JavaDE MIHAI SCORȚARU · 25 MAI 2015

În cadrul acestui episod vom vedea cum putem face în așa fel încât programele să ia anumite decizii în funcție de circumstanțe.

Până acum am scris doar programe sau scurte secvențe de cod în care instrucțiunile se executau în ordine, începând cu prima și terminând cu ultima. Nimic nu putea afecta acest proces. Dar, programele trebuie să poată face mai mult decât atât...

Să ne imaginăm că ajungem la o răscruce de drumuri; cel din dreapta duce spre Împărăția Roșie, iar celălalt spre Împărăția Verde. În funcție de unde vrem să ajungem, vom alege drumul din dreapta sau cel din stânga.

Pentru a o lua la dreapta, trebuie ca o anumită condiție să fie îndeplinită; trebuie să vrem să mergem în Împărăția Roșie. Pentru a o lua la stânga, trebuie ca acea condiția să nu fie îndeplinită; trebuie să nu vrem să mergem în Împărăția Roșie, ceea ce înseamnă că vrem să mergem în Împărăția Verde.

Condiția poate lua diverse forme. În exemplul anterior condiția a fost voința noastră; dar, ar putea să fie ceva mai interesant; de exemplu, am putea spune că dacă în caleașca pe care o însoțim se află o prințesă, atunci vom merge în Împărăția Roșie.

Instrucțiunea ifPentru a explica ce vrem să facem, am folosit cuvântul dacă; am spus că dacă o anumită condiție este îndeplinită vom efectua o anumită acțiune. Și în Java vom folosi ceva similar; va fi în engleză, deci cuvântul va fi if. El va fi urmat de condiția care trebuie verificată, cuprinsă între paranteze rotunde și apoi de instrucțiunea care trebuie executată în cazul în care condiția este îndeplinită. Condiția este o expresie booleană; poate fi o simplă variabilă sau o expresie mai complexă. O astfel de instrucțiune este numită condițională.

Să presupunem că avem o variabilă existaPrintesa care are o anumită valoare; nu știm exact cum a fost atribuită acea valoare și nici care este valoarea sa curentă. Dar, dacă în acest moment această variabilă are valoarea true, dorim să scriem mesajul "Împărăția Roșie". Secvența de cod ar arăta astfel:

1if (existaPrintesa) System.out.println("Împărăția Roșie");Secvența este corectă, dar nu arată prea bine. De obicei instrucțiunea care ar trebui executată atunci când este îndeplinită condiția este scrisă pe o linie nouă.

if (existaPrintesa) System.out.println("Împărăția Roșie");Blocuri de instrucțiuniDeocamdată, dacă este îndeplinită condiția executăm o singură instrucțiune. Dar, s-ar putea să vrem să executăm mai multe. De exemplu, am putea să vrem să ducem prințesa în Împărăția

Page 32: Fundamentele programării

Roșie și să o lăsăm acolo; când ajunge acasă, prințesa va coborî din caleașcă, deci în caleașcă nu se va mai afla nicio prințesă. Așadar, variabila existaPrintesa ar trebui să primească valoarea false. Am putea verifica din nou dacă este îndeplinită condiția; codul ar putea fi următorul:

if (existaPrintesa) System.out.println("Împărăția Roșie");if (existaPrintesa) existaPrintesa = false;Nu arată deloc bine... Ce am vrea este să scriem condiția o singură dată și să executăm mai multe instrucțiuni. Pentru aceasta va trebui să creăm un așa numit bloc de instrucțiuni. Un astfel de bloc este format dintr-o succesiune de instrucțiuni, cuprinse între acolade. Putem rescrie secvența astfel:

if (existaPrintesa) { System.out.println("Împărăția Roșie"); existaPrintesa = false;}O practică des întâlnită este să se creeze blocuri de instrucțiuni formate dintr-o singură instrucțiune; codul este mai clar și sunt evitate anumite greșeli puțin mai greu de detectat.

Să presupunem că avem prima variantă: cea în care doar scriem string-ul "Împărăția Roșie". Dorim acum ca, pe lângă acest mesaj, pe o altă linie să scriem și string-ul "Prințesa a ajuns acasă". Dacă ne grăbim, codul nostru ar putea arăta așa:

if (existaPrintesa) System.out.println("Împărăția Roșie"); System.out.println("Prințesa a ajuns acasă");Deși am aliniat instrucțiunea cu cea anterioară, spațiile se ignoră, deci nu are nicio importanță. Avem o instrucțiunei if care spună că, în cazul în care condiția este îndeplinită, se execută instrucțiunea care urmează. Cealaltă instrucțiune se execută oricum; condiția nu mai este verificată. Deci, mesajul "Prințesa a ajuns acasă" ar fi afișat chiar dacă nu am fi avut nicio prințesă în caleașcă.

Dar, dacă am fi folosit acolade chiar și în prima variantă:

if (existaPrintesa) { System.out.println("Împărăția Roșie");}atunci, după adăugarea celei de-a doua instrucțiui, codul ar deveni:

if (existaPrintesa) { System.out.println("Împărăția Roșie"); System.out.println("Prințesa a ajuns acasă");}și ar fi funcționat așa cum ne-am dori.

Page 33: Fundamentele programării

Altfel de condițiiSpuneam că acea condiție este o expresie booleană. Până acum am folosit o simplă variabilă booleană; este ușor să ne gândim că putem folosi operatorii booleeni pe care i-am prezentat în episodul trecut. Poate dacă în caleașcă se află și un prinț, dorim de fapt să mergem la nunta din Împărăția Verde. Codul ar putea arăta așa:

123if (existaPrintesa & existaPrint) { System.out.println("Împărăția Verde");}Dar, de obicei condițiile pe care dorim să le verificăm sunt cu totul altele. Dacă lucrăm cu numere, am putea dori să verificăm dacă un număr are o anumită valoare, să vedem dacă un număr este mai mare decât altul etc.

Să considerăm un prim exemplu: avem o variabilă nr care conține un număr întreg; în cazul în care valoarea acelei variabile este 2457, dorim să scriem mesajul "Număr magic". Codul este:

123if (nr == 2457) { System.out.println("Număr magic");}Observăm că nu am scris un singur simbol =, ci două; == este operatorul de egalitate. Folosim un singur = pentru atribuire. Secvența următoare nu este validă:

if (nr = 2457) { System.out.println("Număr magic");}Operatorul de egalitate este aplicat asupra a doi operatori cu tipuri compatibile; pentru tipurile primitive nu avem nicio surpriză; rezultatul este o valoare booleană care arată dacă cele două valori sunt egale.

Avem și un operator de inegalitate; rezultatul arată dacă cele două valori nu sunt egale.

if (nr != 2457) { System.out.println("Numărul nu este magic!");}După cum vedeți, operatorul este !=. Intuitiv, am putea spune că am negat egalitatea; am folosit semnul exclamării (cel care indică negația) urmat de semnul egal.

Dar, numerele pot fi și comparate; nu ar trebui să ne surprindă deloc existența unor operatori ca < sau >. Să verificăm dacă un număr este strict pozitiv:

Page 34: Fundamentele programării

if (nr > 0) { System.out.println("Număr strict pozitiv!");}La fel de simplu este să verificăm dacă numărul este strict negativ:

3if (nr < 0) { System.out.println("Număr strict negativ!");}Când comparăm numerele folosim câteodată și conceptul de mai mare sau egal. Avem și un operator pentru așa ceva; nu este chiar ≥ cum poate ne-ar plăcea, ci >=. Să vedem cum verificăm dacă un număr este pozitiv (nu strict pozitiv):

if (nr >= 0) { System.out.println("Număr pozitiv!");}Similar, avem operatorul <= pentru mai mic sau egal.

Condiții compuseRezultatul utilizării oricărui astfel de operator este o valoare booleană; este natural să ne așteptăm să putem folosi operatorii booleeni asupra rezultatelor.

Am putea dori să verificăm dacă un anumit număr întreg este format dintr-o singură cifră. Am avea o condiția dublă: numărul trebuie să fie mai mare sau egal cu zero și mai mic decât zece. Am putea scrie următorul cod:

if (nr >= 0 & nr < 10) { System.out.println("O cifră");}Mai avem și alte variante; una ar putea fi:

if (nr > -1 & nr <= 9) { System.out.println("O cifră");}Codul funcționează corect fiindcă operațiile de comparare sunt executate înaintea conjucției logice; există o ordine specifică limbajului și de data aceasta ordinea de convine; dar, ar fi cam mult să ținem minte ordinea luată în considerare de limbaj; de obicei vrem să ne asigurăm că operațiile sunt efectuate în ordinea pe care o dorim; pentru aceasta folosim paranteze, chiar dacă nu sunt neapărat necesare; codul poate fi înțeles mult mai ușor. Așadar, varianta recomandată ar fi:

if ((nr >= 0) & (nr < 10)) { System.out.println("O cifră");}

Page 35: Fundamentele programării

Avem paranteze în paranteze, dar totul este în regulă; totuși, să nu vă gândiți că am putea folosi paranteze drepte sau acolade; am întâlnit deja acolade și am văzut că au cu totul alt rol (delimitează grupuri de instrucțiuni); vom întâlni și paranteze drepte, care au și ele un rol diferit.

Deși nu prea are sens să scriem un astfel de cod, pentru a ilustra că nu tot timpul ordinea este cea pe care am dori-o să verificăm dacă un număr este diferit del 2457 verificând egalitatea și negând rezultatul. Codul ar arăta așa:

123if (! nr == 2457) { System.out.println("Numărul nu este magic!");}Vom observa că este generată o eroare care ne spune că operatorul logic de negație nu poate fi aplicat asupra unui număr întreg. Totul se rezolvă dacă scriem:

123if (!(nr == 2457)) { System.out.println("Numărul nu este magic!");}În Java mai avem la dispoziție doi operatori pentru condițiile compuse care ar putea fi utili. Este vorba de && și ||. Ei seamănă cu & și |, dar există o șmecherie. Dacă avem && și prima dintre cele două condiții este falsă, atunci a doua nu mai este verificată fiindcă rezultatul ar fi false oricum. Similar, dacă avem || și prima dintre cele două condiții este adevărată, atunci a doua nu mai este verificată fiindcă rezultatul ar fi true oricum. Deocamdată nu pare foarte important; dar, dacă ne gândim că aceste condiții pot deveni din ce în ce mai complicate, ne putem imagina că am putea ajunge să economisim timp dacă nu facem verificări inutile. Să revenim la codul care verifică dacă un număr are o singură cifră, dar să dublăm ampersandul:

if ((nr >= 0) && (nr < 10)) { System.out.println("O cifră");}Dacă numărul ar fi negativ, prima condiție este falsă și nu mai are rost să verificăm dacă el este mai mic decât zece. Chiar dacă ar fi (și în cazul nostru știm că va fi fiindcă este negativ), nu are nicio relevanță; condiția compusă va fi falsă.

AlternativaSă revenim la exemplul inițial; spuneam că dacă avem o prințesă în caleașcă vrem să mergem în Împărăția Roșie. Probabil că dacă nu însoțim nicio prințesă am vrea totuși să mergem în Împărăția Verde (poate găsim o prințesă acolo?). Pentru a verifica dacă trebuie să mergem în Împărăția Verde, am putea nega condiția; codul ar arăta astfel:

if (existaPrintesa) { System.out.println("Împărăția Roșie");

Page 36: Fundamentele programării

}if (!existaPrintesa) { System.out.println("Împărăția Verde");}Deocamdată nu avem nicio problemă, dar pare complicat și ne putem imagina că în situații complexe ar deveni din ce în ce mai ciudat. Codul pe care l-am scris ar putea fi descris astfel: dacă în caleașcă este o prințesă mergem în Împărăția Roșie; dacă în caleașcă nu este o prințesă mergem în Împărăția Verde. Pare puțin ciudat și cam lung; ne-am aștepta ca raționamentul să fie ceva de genul: dacă în caleașcă este o prințesă mergem în Împărăția Roșie; altfel mergem în Împărăția Verde. Din fericire, Java și majoritatea limbajelor de programare ne permit să "spunem" altfel. Cuvântul va fi în engleză: else.

În Java vom avea cuvântul if, urmat de condiția care trebuie verificată, cuprinsă între paranteze rotunde, de instrucțiunea care trebuie executată în cazul în care condiția este îndeplinită, apoi de cuvântul else și de instrucțiunea care trebuie executată în cazul în care condiția este îndeplinită.

Codul nostru devine:

if (existaPrintesa) { System.out.println("Împărăția Roșie");} else { System.out.println("Împărăția Verde");}If în ifAm spus că în cazul în care este îndeplinită o condiție se execută o instrucțiune. Am mai arătat că dacă nu este îndeplinită condiția, putem specifica o altă instrucțiune care să fie executată. Nu am pus nicio restricție legată de tipul instrucțiunilor respective. De fapt, nu există nicio restricție. Am văzut că putem pune o instrucțiune simplă sau un bloc de instrucțiuni. Dar, putem pune chiar și o altă instrucțiune condițională. De fapt, și printre instrucțiunile care formează un bloc, oricare poate fi un if.

Așadar, putem verifica o condiție și apoi, printre operațiile pe care le efectuăm, putem verifica o altă condiție și efectua alte operații în funcție de ea.

Să extindem puțin exemplul inițial; la răscrucea de drumuri putem alege trei variante: spre Împărăția Roșie, spre Împărăția Verde sau spre Împărăția Albastră. În caleașcă putem avea sau nu o prințesă și putem sau nu avea un prinț. Dacă prințesa nu este în caleașcă, atunci mergem în Împărăția Albastră să aducem prințesa; dacă e în caleașcă și nu e însoțită, mergem în Împărăția Verde să luăm prințul; dacă e însoțită de prinț, mergem la nuntă în Împărăția Roșie.

Așadar, vom avea o condiția care verifică dacă prințesa există. Dacă da, atunci trebuie să verificăm dacă există și prințul. Dacă prințul există, scriem mesajul "Împărăția Roșie". Dacă prințul nu există, scriem mesajul "Împărăția Verde". Dacă prințesa nu există, scriem mesajul "Împărăția Albastră" indiferent dacă prințul există sau nu.

Codul ar putea arăta așa:

if (existaPrintesa) { if (existaPrint) { System.out.println("Împărăția Roșie");

Page 37: Fundamentele programării

} else { System.out.println("Împărăția Verde"); } } else { System.out.println("Împărăția Albastră"); }De data aceasta putem și fără acolade, deși nu este recomandat:

if (existaPrintesa) if (existaPrint) System.out.println("Împărăția Roșie"); else System.out.println("Împărăția Verde");else System.out.println("Împărăția Albastră");Nu trebuie neapărat să ne oprim la un singur if în if. Cel din interior poate conține la rândul său o instrucțiune condițională; la fel acest al treilea if și așa mai departe.

Când avem două sau mai multe astfel de instrucțiuni if, spunem că ele sunt imbricate.

Să vedem de ce este periculos să nu folosim acolade. Poate nu vrem să facem absolut nimic în cazul în care avem prințesă dar nu avem prinț. Am putea crede că este suficient să eliminăm liniile 4 și 5. Codul ar deveni:

if (existaPrintesa) if (existaPrint) System.out.println("Împărăția Roșie");else System.out.println("Împărăția Albastră");Vă mai aduceți aminte cum calculatoarele fac ceea ce le spunem să facă, nu ceea ce vrem noi să facă? Degeaba avem acel else la începutul liniei 4; calculatorul nu are cum să știe că noi vrem ca acesta să fie alternativa pentru primul if; caracterele albe sunt ignorate; e ca și cum am scrie:

12345if (existaPrintesa) if (existaPrint) System.out.println("Împărăția Roșie"); else System.out.println("Împărăția Albastră");Cum alege calculatorul? De data aceasta nu cum vrem noi! Un else reprezintă alternativa pentru cel mai apropiat if.

Dacă am fi transformat codul care avea acolade, noua versiune ar fi fost:

Page 38: Fundamentele programării

if (existaPrintesa) { if (existaPrint) { System.out.println("Împărăția Roșie"); } } else { System.out.println("Împărăția Albastră"); }De data aceasta obținem ce ne-am dorit; datorită faptului că al doilea if face parte dintr-un bloc și acel bloc s-a încheiat, alternativa nu se poate aplica decât primului if.

Va urmaFundamentele programării (V) - JavaDE MIHAI SCORȚARU · 1 IUNIE 2015

Am văzut în cadrul episodului anterior cum pot lua programele decizii în funcție de circumstanțe, cum se execută o instrucțiune sau alta în funcție de anumite condiții. În cadrul acestui episod vom continua prezentarea modului în care sunt luate decizii.

Mai multe variantePână acum doream să se execute anumite instrucțiuni dacă o anumită condiție era adevărată și altele dacă era falsă. Dar, ce am face dacă nu avem doar două variante, ci mai multe.

Să ne imaginăm o situție în care dorim să scriem cifrele folosind litere. Avem o variabilă c care ar trebui să conțină o cifră. Dacă valoarea este 1, ar trebui să scriem string-ul "unu"; dacă valoarea este 2, ar trebui să scriem "doi" și așa mai departe. Variabila conține numere, deci probabil nu va avea neapărat valori cuprinse între zero și nouă; în cazul în care valoarea nu este o cifră, am vrea să scriem textul "nu este o cifră".

Cea mai simplă variantă este să comparăm, pe rând, valoarea variabilei c cu fiecare cifră și să scriem mesajul corespunzător în cazul în care identificăm cifra; începem comparând cu zero; dacă am găsit valoarea scriem textul "zero"; dacă nu am găsit-o încercăm să comparăm cu unu și așa mai departe; dacă am ajuns la nouă și tot nu am găsit cifra, putem concluziona că nu avem o cifră. Codul ar arăta astfel:

if (c == 0) { System.out.println("zero");} else { if (c == 1) { System.out.println("unu"); } else { if (c == 2) { System.out.println("doi"); } else { if (c == 3) { System.out.println("trei"); } else { if (c == 4) { System.out.println("patru"); } else { if (c == 5) {

Page 39: Fundamentele programării

System.out.println("cinci"); } else { if (c == 6) { System.out.println("șase"); } else { if (c == 7) { System.out.println("șapte"); } else { if (c == 8) { System.out.println("opt"); } else { if (c == 9) { System.out.println("nouă"); } else { System.out.println("nu este o cifră"); } } } } } } } } }}Am respectat recomandarea de a folosi blocuri de instrucțiuni chiar dacă avem o singură instrucțiune și nu arată prea bine...

Trebuie să ne obișnuim ca, în funcție de situație, să avem recomandări, excepții de la recomandări, excepții de la excepții etc. De data aceasta recomandarea nu a dus la ceva bun, deci vom introduce o excepție (tot sub formă de recomandare). Avem aici o succesiune if, else, if, else, if, else, etc. În situația în care pe ramura else avem doar un if, noua recomandare este să nu folosim un bloc de instrucțiuni, ci o instrucțiune condițională simplă. Se poate vedea că arată mult mai bine:

if (c == 0) { System.out.println("zero");} else if (c == 1) { System.out.println("unu");} else if (c == 2) { System.out.println("doi");} else if (c == 3) { System.out.println("trei");} else if (c == 4) { System.out.println("patru");} else if (c == 5) { System.out.println("cinci");} else if (c == 6) { System.out.println("șase");} else if (c == 7) {

Page 40: Fundamentele programării

System.out.println("șapte");} else if (c == 8) { System.out.println("opt");} else if (c == 9) { System.out.println("nouă");} else { System.out.println("nu este o cifră");}SwitchChiar și așa, pare totuși cam complicat; ar trebui să putem mai simplu. Ni se pune la dispoziție instrucțiunea switch; aceasta seamănă cu instrucțiunea if, dar are mai multe "ramuri"; în locul condiției avem o expresie al cărei rezultat trebuie să fie un număr întreg sau un string. Putem apoi specifica instrucțiunile care trebuie executate pentru fiecare valoare în parte; de asemenea, putem specifica instrucțiuni care să se execute în cazul în care nu se potrivește nicio valoare.

Fiecare alternativă este specificată folosind cuvântul case, urmat de o valoare, apoi de semnul : și, în sfârșit, instrucțiunile care trebuie executate. Pot fi mai multe instrucțiuni; acestea nu trebuie grupate într-un bloc.

Putem specifica și o ultimă alternativă (nicio valoare nu se potrivește) folosind cuvântul default, urmat de semnul : și de instrucțiunile care trebuie executate în acest caz.

Alternativele sunt cuprinse între acolade.

Limbajul Java (la fel ca multe altele) are o abordare puțin ciudată. Dacă expresia se potrivește cu una din valorile specificate, atunci se execută toate instrucțiunile care urmează, inclusiv de la alternativele prezentate ulterior.

Să vedem exact ce înseamnă acest lucru... Pe baza celor prezentate, ne-am aștepta ca problema noastră inițială să poată fi rezolvată folosind următorul cod:

switch (c) {case 0: System.out.println("zero");case 1: System.out.println("unu");case 2: System.out.println("doi");case 3: System.out.println("trei");case 4: System.out.println("patru");case 5: System.out.println("cinci");case 6: System.out.println("șase");case 7: System.out.println("șapte");case 8: System.out.println("opt");case 9:

Page 41: Fundamentele programării

System.out.println("nouă");default: System.out.println("nu este o cifră");}Dacă am avea valoarea 4, ne-am aștepta să fie afișat textul "patru". Dar, în realitate, afișăm mult mai mult:

patrucincișaseșapteoptnouănu este o cifrăNu este ceea ce ne dorim, dar așa funcționează în Java. Totuși, avem o soluție: Java ne pune la dispoziție instrucțiunea break care duce la întreruperea executării instrucțiunilor. O putem folosi pentru a spune că nu dorim să se execute ceea ce urmează. Obținem ceea ce ne-am dori dacă rescriem codul astfel:

switch (c) {case 0: System.out.println("zero"); break;case 1: System.out.println("unu"); break;case 2: System.out.println("doi"); break;case 3: System.out.println("trei"); break;case 4: System.out.println("patru"); break;case 5: System.out.println("cinci"); break;case 6: System.out.println("șase"); break;case 7: System.out.println("șapte"); break;case 8: System.out.println("opt"); break;case 9: System.out.println("nouă");

Page 42: Fundamentele programării

break;default: System.out.println("nu este o cifră");}Nu are sens să punem break și pentru alternativa default fiindcă e ultima. Această variantă face ceea ce ne dorim.

Operatorul condiționalDe multe ori dorim să verificăm o anumită condiție booleană și, în funcție de rezultatul verificării să atribuim unei variabilă o valoare sau alta. De exemplu, am putea avea o variabilă nr care conține numere întregi și am dori să atribuim unei variabile s care conține string-uri valoarea "negativ" dacă numărul respectiv este mai mic decât zero și valoarea "nenegativ" în caz contrar (numărul este mai mare sau egal cu zero).

Putem face asta simplu:

12345if (nr < 0) { s = "negativ";} else { s = "nenegativ";}Totuși, situația este atât de frecventă încât limbajele oferă o prescurtare și anume operatorul condițional. Acesta este interesant: are trei operanzi; nu am mai văzut așa ceva până acuma. Primul este o condiție booleană, iar ceilalți doi sunt expresii. Rezultatul aplicării operatorului este detrminat astfel: în cazul în care econdiția este îndeplinită, rezultatul este obținut prin evaluarea primeia dintre cele două expresii; altfel, rezultatul este obținut prin evaluarea celeilalte expresii; tipurile rezultatelor celor două expresii trebuie să fie compatibile.

Următoarea instrucțiune este echivalentă cu secvența anterioară:

1s = nr < 0 ? "negativ" : "nenegativ";Așadar, avem condiția, urmată de semnul ?, de prima expresie, semnul : și apoi de a doua expresie.

Cum acest operator are ca rezultat o valoare, putem folosi astfel de expresii și pentru inițializări de variabile. Următoarea inițializare este validă:

1String s = nr < 0 ? "negativ" : "nenegativ";Va urmaÎn următorul episod vom introduce conceptul de funcție. Vom vedeaFundamentele programării (VI) - Java

Page 43: Fundamentele programării

DE MIHAI SCORȚARU · 8 IUNIE 2015

Pe măsură ce scriem din ce în ce mai mult cod, acesta devine mai greu de urmărit. Vă amintiți de lunga secvență if, else, if din episodul anterior? Atunci am avut o soluție cu switch, dar în alte situații instrucțiunile nu au astfel de caracteristici comune. Totuși, am putea dori să le grupăm cumva. Am văzut că avem grupuri de instrucțiuni, dar nici acestea nu sunt utile decât în anumite situații.

Ar fi frumos dacă am putea împărți codul în bucățele mici, ușor de înțeles, pe care să le folosim cum vrem. Să ne imaginăm că vrem să tipărim versurile din Gaudeamus. Deocamdată, programul nostru ar arăta cam așa:

/* package whatever; // don't place package name! */ import java.util.*;import java.lang.*;import java.io.*; /* Name of the class has to be "Main" only if the class is public. */class Ideone{ public static void main (String[] args) throws java.lang.Exception { System.out.println("Gaudeamus igitur"); System.out.println("Iuvenes dum sumus."); System.out.println("Post iucundam iuventutem"); System.out.println("Post molestam senectutem"); System.out.println("Nos habebit humus."); System.out.println(""); System.out.println("Ubi sunt qui ante nos"); System.out.println("In mundo fuere?"); System.out.println("Vadite ad superos"); System.out.println("Transite in inferos"); System.out.println("Hos si vis videre."); System.out.println(""); System.out.println("Vita nostra brevis est"); System.out.println("Brevi finietur."); System.out.println("Venit mors velociter"); System.out.println("Rapit nos atrociter"); System.out.println("Nemini parcetur."); System.out.println(""); System.out.println("Vivat academia!"); System.out.println("Vivant professores!"); System.out.println("Vivat membrum quodlibet;"); System.out.println("Vivant membra quaelibet;"); System.out.println("Semper sint in flore."); System.out.println(""); System.out.println("Vivant omnes virgines"); System.out.println("Faciles, formosae."); System.out.println("Vivant et mulieres");

Page 44: Fundamentele programării

System.out.println("Tenerae, amabiles,"); System.out.println("Bonae, laboriosae."); System.out.println(""); System.out.println("Vivat et res publica"); System.out.println("et qui illam regit."); System.out.println("Vivat nostra civitas,"); System.out.println("Maecenatum caritas"); System.out.println("Quae nos hic protegit."); System.out.println(""); System.out.println("Pereat tristitia,"); System.out.println("Pereant osores."); System.out.println("Pereat diabolus,"); System.out.println("Quivis antiburschius"); System.out.println("Atque irrisores."); }}Cam lung și monoton, nu?

Împărțirea în funcțiiAm spus că am vrea să împărțim acest cod în bucățele mai mici. O putem face oricum, dar ar fi bine ca acele bucățele să aibă totuși un sens. De data aceasta este natural să alegem o împărțire pe strofe. Fiecare strofă va fi scrisă de o bucată de cod; o astfel de bucată de cod poartă denumirea de funcție. Prezentăm noua variantă a codului și apoi vom discuta mai pe larg despre funcții (ce sunt și cum sunt create).

/* package whatever; // don't place package name! */ import java.util.*;import java.lang.*;import java.io.*; /* Name of the class has to be "Main" only if the class is public. */class Ideone{ private static void strofa1() { System.out.println("Gaudeamus igitur"); System.out.println("Iuvenes dum sumus."); System.out.println("Post iucundam iuventutem"); System.out.println("Post molestam senectutem"); System.out.println("Nos habebit humus."); System.out.println(""); }

private static void strofa2() { System.out.println("Ubi sunt qui ante nos"); System.out.println("In mundo fuere?"); System.out.println("Vadite ad superos"); System.out.println("Transite in inferos"); System.out.println("Hos si vis videre."); System.out.println("");

Page 45: Fundamentele programării

}

private static void strofa3() { System.out.println("Vita nostra brevis est"); System.out.println("Brevi finietur."); System.out.println("Venit mors velociter"); System.out.println("Rapit nos atrociter"); System.out.println("Nemini parcetur."); System.out.println(""); }

private static void strofa4() { System.out.println("Vivat academia!"); System.out.println("Vivant professores!"); System.out.println("Vivat membrum quodlibet;"); System.out.println("Vivant membra quaelibet;"); System.out.println("Semper sint in flore."); System.out.println(""); }

private static void strofa5() { System.out.println("Vivant omnes virgines"); System.out.println("Faciles, formosae."); System.out.println("Vivant et mulieres"); System.out.println("Tenerae, amabiles,"); System.out.println("Bonae, laboriosae."); System.out.println(""); }

private static void strofa6() { System.out.println("Vivat et res publica"); System.out.println("et qui illam regit."); System.out.println("Vivat nostra civitas,"); System.out.println("Maecenatum caritas"); System.out.println("Quae nos hic protegit."); System.out.println(""); }

private static void strofa7() { System.out.println("Pereat tristitia,"); System.out.println("Pereant osores."); System.out.println("Pereat diabolus,"); System.out.println("Quivis antiburschius"); System.out.println("Atque irrisores."); }

public static void main (String[] args) throws java.lang.Exception { strofa1(); strofa2(); strofa3();

Page 46: Fundamentele programării

strofa4(); strofa5(); strofa6(); strofa7(); }}Vedem acum șapte noi porțiuni de cod, care încep cu ciudatul private static void. Să ignorăm deocamdată aceste cuvinte...

Urmează o denumire; acesta este numele funcției. Avem apoi o paranteză deschisă, urmată imediat de una închisă. Cam ciudat, dar să ignorăm și acest aspect deocamdată (vom vedea în episodul următor mai multe despre aceste paranteze). După aceea avem un simplu bloc de instrucțiuni; acesta este numit corpul funcției.

Până acum, în Java, codul pe care l-am scris a fost tot timpul între acoladele care urmau după linia care începea cu public static void main. De data aceasta vedem că funcțiile sunt undeva în afară. Dar, înauntru vedem șapte linii care conțin numele celor șapte funcții, urmate de câte o paranteză deschisă și câte una închisă. Acestea sunt instrucțiuni prin care spunem că dorim să se execute codul corespunzător unei funcții. Ele poartă denumirea de apeluri de funcții.

Instrucțiunile din interiorul unei funcții nu se execută decât dacă funcția este apelată. Dacă am șterge liniile 74 - 80 versurile nu ar mai fi afișate. De fapt, acum putem alege ce strofe dorim să afișăm. Prin eliminarea unei linii, decidem că o anumită strofă nu trebuie afișată. Vă mai amintiți de comentarii? Putem să nu ștergem linia, ci doar să o comentăm.

Funcții apelate din funcțiiCorpul funcției poate conține orice instrucțiuni, inclusiv un apel al unei alte funcții. Să presupunem că primele versuri din prima strofă sunt speciale; la fel și ultimul vers (vom vedea mai târziu de ce). Poate am dori să împărțim codul corespunzător funcției strofa1 în mai multe bucățele: primele două versuri, următoarele două și ultimul. Secțiunea corespunzătoare a codului ar putea arăta astfel:

private static void strofa1inceput() { System.out.println("Gaudeamus igitur"); System.out.println("Iuvenes dum sumus.");} private static void strofa1mijloc() { System.out.println("Post iucundam iuventutem"); System.out.println("Post molestam senectutem");} private static void strofa1sfarsit() { System.out.println("Nos habebit humus.");} private static void strofa1() { strofa1inceput(); strofa1mijloc(); strofa1sfarsit();

Page 47: Fundamentele programării

System.out.println("");}Avem acum o funcție care apelează alte trei funcții. Putem face același lucru și pentru funcțiile corespunzătoare celorlalte strofe.

Apeluri multipleAm spus că o funcție este executată doar dacă este apelată. Dar, ce ne împiedică să o apelăm de mai multe ori? Nimic! Lăsăm nemodificate funcțiile strofa1inceput, strofa1mijloc și strofa1sfarsit, dar modificăm funcția strofa1 astfel:

private static void strofa1() { strofa1inceput(); strofa1inceput(); strofa1mijloc(); strofa1sfarsit(); strofa1sfarsit(); System.out.println("");}Acum funcția strofa1inceput este apelată de două ori, deci va fi executată de două ori, deci primele două versuri vor fi afișate de două ori. Similar, funcția strofa1sfarsit este apelată de două ori, deci va fi și ea executată de două ori și ultimul vers va fi și el afișat de două ori.

De ce am face așa ceva? Când este cântat Gaudeamus, primele două versuri din fiecare strofă sunt repetate; la fel și ultimul vers. Deci, dacă am ales o împărțire potrivită a funcțiilor, am putut trece ușor de la poezie la cântec.

Ne putem gândi și la alte situații în care apelurile multiple ar putea fi utile. De exemplu, am putea avea un cântec cu refren. Funcția care afișează refrenul ar putea fi apelată de mai multe ori.

Va urma

Fundamentele programării (VII) - JavaDE MIHAI SCORȚARU · 22 IUNIE 2015

În cadrul episodului anterior am văzut cum putem crea și apela funcții. Dar acestea erau foarte simple; practic, erau o înșiruire de instrucțiuni care, eventual, ar putea fi apelate de mai multe ori. Vom vedea acum că putem face mai multe.

Să considerăm următoarea secvență:

123456

int nr = 2457;if (nr % 2 == 0) {  System.out.println("Număr par");} else {  System.out.println("Număr impar");}

Page 48: Fundamentele programării

Verificăm dacă un număr este par și afișăm un mesaj corespunzător, după caz. Verificarea se face simplu: numerele pare se împart exact la 2 (restul împărțirii la doi este zero), iar cele impare nu.În urma executării acestei secvențe, s-ar afișa mesajul Număr impar. Dacă am vrea să verificăm paritatea altui număr am mofica prima linie, inițializând variabila nr cu o altă valoare.Am putea pune acest cod într-o funcție. Am văzut că uneori e mai bine așa... Funcția noastră ar putea arăta astfel:

12345678

private static void verificareParitate() {  int nr = 2457;  if (nr % 2 == 0) {    System.out.println("Număr par");  } else {    System.out.println("Număr impar");  }}

Acum putem să o apelăm de mai multe ori; dar, nu facem decât să verificăm de câte ori vrem paritatea aceluiași număr ( 2457 dacă nu-l schimbăm). Nu pare foarte util...Dar, cum ar fi dacă am putea să verificăm paritatea oricărui număr am dori. Nu ar fi frumos ca atunci când apelăm funcția să putem preciza și care este numărul a cărui paritate vrem să o verificăm?

Din fericire este posibil. Vă amintiți de acele ciudate parenteze care trebuie adăugate și când definim și când apelăm funcția? Vom vedea acum la ce sunt bune... În momentul în care apelăm funcția, putem să precizăm anumite valori sau variabile, pe care le punem între acele paranteze; dacă sunt mai multe, le separăm prin virgule. Ele poartă denumirea de argumente ale apelului.În situația noastră, am vrea să verificăm paritatea anumitor numere: apelurile noastre ar putea arăta așa:

1234

verificareParitate(2457);verificareParitate(47);verificareParitate(0);verificareParitate(a);Avem patru apeluri. În urma executării primelor două s-ar afișa textul Număr impar, pentru al treilea s-ar afișa textul Număr par, iar textul afișat pentru ultimul depinde de valoarea curentă a variabilei a.

Page 49: Fundamentele programării

Dar, așa cum arată funcția noastră acum, ea nu ia în seamă nicio eventuală valoare care însoțește apelul. Dar, are și ea acele paranteze care par inutile. Probabil ați ghicit, putem pune aici ceva. Practic, putem face în așa fel încât valorile argumentelor apelului să fie disponibile. Pentru aceasta avem așa-numițiiparametri ai funcției. Ei seamănă cu niște variabile: au tip și denumire. Putem modifica foarte ușor funcția noastră astfel încât ea să aibă un parametru: 1234567

private static void verificareParitate(int nr) {  if (nr % 2 == 0) {    System.out.println("Număr par");  } else {    System.out.println("Număr impar");  }}

Dacă funcția are mai mulți parametri, sunt separați și ei prin virgule.

De multe ori denumirile de argument și parametru nu sunt folosite corect. Veți auzi sau vedea de multe ori spunându-se că apelul are parametri sau funcția are argumente. Noțiunile au ajuns să fie aproape interschimbabile. De fapt, nici nu ar prea au de ce să fie diferite. Dar, strict vorbind, funcțiile au parametri și apelurile au argumente.

În Java, tipurile și numărul argumentelor trebuie să se potrivească. Așadar, pentru noua versiune a funcției, următoarea apeluri nu sunt corecte:

123

verificareParitate(2, 3);verificareParitate("text");verificareParitate();Când apelăm funcția, putem avea orice argument care este compatibil cu tipul argumentului; am văzut că putem folosi valori sau variabile; dar, putem avea și expresii, atâta timp cât tipul rezultatului este compatibil. Următoarea secvență este corectă:

12345

verificareParitate(2 + 3);int nr = 2457;verificareParitate(nr + 47);bool exista = true;verificareParitate(exista ? nr : 13);Dacă privim cu atenție, ne dăm seama că foloseam apeluri cu argumente încă de la primul episod. Să revenim la primul program pe care l-am scris în Java:

Page 50: Fundamentele programării

1234567891011121314

/* package whatever; // don't place package name! */ import java.util.*;import java.lang.*;import java.io.*; /* Name of the class has to be "Main" only if the class is public. */class Ideone{  public static void main (String[] args) throws java.lang.Exception  {    System.out.println("Gazeta de Informatică");  }}

În linia 12 vedeți ceva ce seamănă foarte mult cu un apel de funcție; aceasta ar fi System.out.println, iar argumentul ar fi "Gazeta de Informatică". Este într-adevăr un apel de funcție; nu apelăm o funcție pe care am creat-o noi, ci una care există deja în Java. Această funcție afișează la ieșire un mesaj pe care îl primește ca parametru.Mai trebuie precizat faptul că denumirea funcției este doar println (nu pot fi folosite puncte în denumirile funcțiilor); System și out sunt altceva și nu vom intra în detalii acum fiindcă nu sunt relevante (cel puțin nu în acest moment).Va urmaFundamentele programării (VIII) - JavaDE MIHAI SCORȚARU · 29 IUNIE 2015

Am văzut în cadrul episodului anterior cum putem transmite anumite valori unei funcții și funcția poate opera cu ele. Dar, este posibil și o comunicare în sens invers; în urma executării unei funcții, apelantul poate primi o valoare. Se spune că funcția returnează acea valoare.În Java trebuie să precizăm care este tipul valorii returnate de o funcție. Am văzut în cadrul episodului anterior că funcțiile erau precedate de trei cuvinte ciudate: private static void. Este momentul să explicăm unul dintre ele: void. Acesta reprezintă tipul funcției (sau tipul valorii returnate). În acest caz,void indică faptul că funcția nu returnează nicio valoare. Putem spune că nu are tip sau că tipul său este vid.

Page 51: Fundamentele programării

Așa cum ne așteptăm, putem folosi orice alt tip. Să presupunem că vrem să determinăm ultima cifră a unui număr. Am putea scrie următoarea funcție:

123

private static int ultima(int nr) {    return nr % 10;}

Vedem cuvântul return. Acesta este folosit în cadrul unei instrucțiuni care precizează valoarea care trebuie returnată de funcție. În cazul nostru returnăm ultima cifră, adică restul împărțirii la 10 a parametrului. Nu va funcționa corect pentru numere negative, dar acest lucru nu este relevant acum.Putem face ce vrem cu valoarea returnată de o funcție. De exemplu, o putem atribui unei variabile. Funcția noastră ar putea fi apelată astfel:

1 int c = ultima(2457);Valoarea variabilei c va fi 7. Probabil v-ați dat seama deja, funcția poate fi utilizată în cadrul expresiilor. De exemplu, am putea avea:

1 int v = ultima(2457) + ultima(47);În această situație, valoarea variabilei v va fi 14.Mai trebuie să precizăm faptul că, în Java, după executarea instrucțiunii care returnează o valoare, nicio altă instrucțiune din cadrul funcției nu se mai execută. Evident, avem excepții, dar nu sunt importante acum.Putem avea mai multe instrucțiuni return  în cadrul unei funcții, dacă ambele au șanse să fie apelate. De exemplu, următoarea funcție este corectă:

1234

private static String paritate(int nr) {  if (nr % 2 == 0) {    return "Număr par";  } else {

Page 52: Fundamentele programării

567

    return "Număr impar";  }}

În funcție de valoarea variabilei nr, una dintre cele două instrucțiuni return se va executa.Dar, următoarea variantă nu mai este corectă (cea de-a treia instrucțiune return nu are șanse să se execute):

12345678

private static String paritate(int nr) {  if (nr % 2 == 0) {    return "Număr par";  } else {    return "Număr impar";  }  return "Altceva";}

Este obligatoriu ca o funcție să returneze o valoare. Așadar, oricâte ramificații am avea, este obligatoriu ca, la un moment dat, să fie întâlnită o instrucțiune care returnează o valoare (cu excepția cazului când tipul funcției este void). Varianta care urmează nu este corectă:

12345

private static String paritate(int nr) {  if (nr % 2 == 0) {    return "Număr par";  } }

Dacă parametrul nu este par, nu este întâlnită nicio instrucțiune de returnare. În schimb, am putea scrie următoarea funcție:

12345678

private static String paritate(int nr) {  if (nr % 2 == 0) {    return "Număr par";  } else {    nr++;  }  return "Altceva";}

Page 53: Fundamentele programării

Cam ciudat codul, dar este valid. Până la urmă este întâlnită o instrucțiune de returnare, indiferent dacă parametrul este par sau nu.

Să revenim puțin la funcțiile fără tip (sau cu tip void). Putem folosi instrucțiunea return și în cadrul lor; nu precizăm și o valoare returnată; efectul este întreruperea execuției funcției.Să presupunem că am dori să scriem o funcție care afișează un număr pe care îl primește ca parametru, dar numai dacă acesta este par. Una dintre variantele prin care aceasta ar putea fi implementată este:

123456

private static void paritate(int nr) {  if (nr % 2 != 0) {    return;  }  System.out.println(nr);}

Se poate evita întreruperea execuției (pentru acest exemplu adăugând un simplu else), dar de multe ori este mult mai simplu să întrerupem execuția în anumite cazuri, evitând scrierea de condiții din ce în ce mai complicate.

Fundamentele programării (IX) - JavaDE MIHAI SCORȚARU · 6 IULIE 2015

Am văzut până acum că trebuie să declarăm variabilele înainte să le folosim. Dar, oare le putem folosi oriunde? Nu chiar...

Să considerăm următorul program:

123456789101

public class Test {    public static void test () {        int n = 2457;        if (n % 2 == 0) {            System.out.println("Număr par");        } else {            System.out.println("Număr impar");        }    }     public static void main (String[] args) {        test();

Page 54: Fundamentele programării

112131415

        System.out.println(n);    }}

Poate ne-am aștepta ca totul să fie în regulă, dar nu e așa. Primim o eroare care ne spune că variabila n  din linia 13 nu este cunoscută. Ar părea că am declarat această variabilă în linia 3. Dar, această declarație a fost făcută în interiorul funcției test și e valabilă doar acolo.Spunem că o variabilă este vizibilă doar acolo unde este declarată. Evident,

ea poate fi folosită doar acolo unde este vizibilă. Spunem că locul în care poate fi văzută o variabilă este domeniul de vizibilitateal variabilei.Am văzut că o variabilă declarată într-o funcție nu poate fi utilizată în afara funcției respective. Dar, e mai complicat decât atât. De fapt, o variabilă este vizibilă doar în interiorul blocului de instrucțiuni în care a fost declarată.

Următorul program nu este nici el corect:

12345678910

public class Test {    public static void main (String[] args) {        int n = 2457;        if (n % 2 == 0) {            int k = 47;            System.out.println(k % 10);        }        System.out.println(k);    }}

De data aceasta eroarea apare în linia 8, deși variabila k a fost declarată în

linia 5.Dacă o variabilă nu este vizibilă într-un anumit bloc de instrucțiuni, o putem

declara. Ar putea părea că am declarat o variabilă de mai multe ori, dar trebuie să luăm în considerare faptul că domeniile de vizibilitate sunt diferite. Următorul program este corect:

Page 55: Fundamentele programării

123456789101112

public class Test {    public static void main (String[] args) {        int n = 2457;        if (n % 2 == 0) {            int k = 47;            System.out.println(k % 10);        } else {            int k = 13;            System.out.println(k % 2);        }    }}

Practic avem două variabile k; prima există în blocul de instrucțiuni dintre liniile 4 și 7, iar a doua în blocul dintre liniile 7 și 10.Trebuie să avem grijă ca domeniile de vizibilitate a două variabile cu același

nume să nu se suprapună. De cele mai multe ori nu este permis; uneori este posibil, dar trebuie să fim atenți.

Am putea încerca să înlocuim în linia 3 n  cu k. Nu mai este corect; vom avea erori pe liniile 5 și 8 care precizează că variabila k este deja definită.

Să vedem acum un exemplu mai interesant:

12345678910

public class Test {    public static void test(int n) {        int n = 47;        System.out.println(n);    }     public static void main (String[] args) {        test(2457);    }}

Nu este corect nici așa ceva; parametrul n este vizibil în cadrul funcției test, deci corpul acestei funcții nu poate conține o declarație a unei variabile cu același nume fiindcă domeniile de vizibilitate s-ar suprapune.

Page 56: Fundamentele programării

Am văzut că, dacă au domenii de vizibilitate diferite, două variabile sunt diferite chiar dacă au aceeași denumire. Să vedem mai exact ce înseamnă

acest lucru:

12345678910111213

public class Test {    public static void test() {        int n;        n = 47;        System.out.println(n);    }     public static void main (String[] args) {        int n = 2457;        test();        System.out.println(n);    }}

Avem o variabilă n a cărei valoare este 2457. Apelăm funcția test; în cadrul acesteia avem o altă variabilă n cu valoarea 47 și scriem valoarea acesteia. Execuția funcției se încheia și urmează scrierea variabilei n; se va scrie 2457, fiindcă variabila din interiorul funcției nu este vizibilă în afara funcției și atribuirea din linia 4 afectează doar variabila declarată în linia 3, nu și pe cea declarată în linia 9.Trebuie să reținem faptul că orice instrucțiune care folosește o variabilă o folosește pe cea vizibilă, chiar dacă în alte locuri există variabile cu același

nume. Să vedem un exemplu mai interesant:

12345678

public class Test {    public static void test(int n) {        n++;        System.out.println(n);    }     public static void main (String[] args) {        int n = 2457;

Page 57: Fundamentele programării

9101112

        test(n);        System.out.println(n);    }}

Vom vedea că în urma execuției instrucțiunii din linia 4, este scrisă valoarea 2458, dar în urma execuției instrucțiunii din linia 10, este scrisă valoarea 2457.Avem o variabilă n definită în linia 8 și inițializată cu valoarea 2457. Aceasta este transmisă ca argument al apelului funcției test. În linia 3 valoarea parametrului funcției test este incrementată. Dar, deja avem o altă variabilă

(parametrul); incrementarea se aplică doar asupra ei. Noua valoare este tipărită și execuția funcției test se încheie. Variabila definită în linia 8 nu a fost

afectată de incrementarea din linia 3; ca urmare, în momentul executării instrucțiunii din linia 10, valoarea sa este tot 2457.Există mecanisme prin care modificările aduse unui parametru al unei funcții să nu se piardă în momentul în care se încheie execuția funcției respective,

dar vom reveni asupra acestui aspect la momentul oportun.

Situația este aceeași dacă variabila transmisă ca argument ajunge să devină un parametru cu alt nume. Efectul execuției următorului program este același:

123456789101112

public class Test {    public static void test(int k) {        k++;        System.out.println(k);    }     public static void main (String[] args) {        int n = 2457;        test(n);        System.out.println(n);    }}

Va urma

Page 58: Fundamentele programării

Va urma

Fundamentele programării (X) - JavaDE MIHAI SCORȚARU · 20 IULIE 2015

Am văzut până acum că, dacă dorim să executăm aceleași instrucțiuni de mai multe ori, fie le scriem de mai multe ori, fie creăm o funcție și o apelăm de mai multe ori. În cazul funcțiilor, am văzut că putem avea parametri astfel încât am putea avea variații asupra modului în care se execută instrucțiunile din corpul funcției.

Dar, aceste soluții au un impediment. Trebuie să știm exact de câte ori vrem să executăm acele instrucțiuni și fie să le scriem de atâtea ori, fie să apelăm de atâtea ori o funcție care le conține. Ce facem dacă nu știm exact de câte ori vrem să fie executate?

De exemplu, am putea dori să scriem cifrele unui număr. Vom avea, probabil, o instrucțiune care va scrie o cifră și un mecanism prin care acesta va fi apelată. Dar, în funcție de cât de mare este acel număr, numărul execuțiilor va varia. Pentru numărul 2457 instrucțiunea se va executa de patru ori, dar pentru 47 doar de două ori.Am văzut în episodul VIII că pentru a determina ultima cifră a unui număr este suficient să calculăm restul împărțirii acelui număr la zece. Putem observa că, practic, printr-o împărțire întreagă (calcularea câtului împărțirii) la zece eliminăm acea cifră din număr. Restul împărțirii noului număr la zece ne va da penultima cifră a numărului inițial; o nouă împărțire întreagă la zece va elimina și această cifră. Continuăm până se termină cifrele, adică atâta timp cât rezultatul împărțirii la zece va fi mai mare decât zero.Vom avea cifrele în ordine inversă, dar ne vom mulțumi cu acest lucru deocamdată; de asemenea, nu va funcționa pentru numere negative și nici pentru numărul zero (vom crede că nu există nicio cifră).

Limbajul Java ne pune la dispoziție o construcție care permite executarea unei instrucțiuni atâta timp cât o anumită condiție este adevărată. Evident, instrucțiunea respectivă poate fi un bloc de instrucțiuni. La fel ca în cazul instrucțiunii if (a se vedea episodul IV) se păstrează recomandarea de

Page 59: Fundamentele programării

a avea un bloc format dintr-o singură instrucțiune în locul unei instrucțiuni simple.Instrucțiunea whileDar, care este noua instrucțiune? Pentru a explica ce vrem să facem, am folosit cuvintele atâta timp; am spus că atâta timp cât o anumită condiție este îndeplinită vom efectua o anumită acțiune. Și în Java vom folosi ceva similar; va fi în engleză, deci cuvântul va fi while. El va fi urmat de condiția care trebuie verificată, cuprinsă între paranteze rotunde și apoi de instrucțiunea care trebuie executată cât timp condiția este îndeplinită. Condiția este o expresie booleană; poate fi o simplă variabilă sau o expresie mai complexă. O astfel de instrucțiune este numită iterativă. Mai sunt folosite și denumirile deinstrucțiune repetitivă sau buclă. Instrucțiunile executate atâta timp cât este îndeplinită condiția sunt numite și corpul buclei.Putem scrie acum secvența care afișează cifrele unui număr (în ordine inversă)...

12345

int n = 2457;while (n > 0) {    System.out.println(n % 10);    n /= 10;}

Astfel de instrucțiuni pot apărea oriunde; de exemplu, ar putea fi parte a unui bloc de instrucțiuni (în interiorul unui alt while, al unui if, al unei funcții etc.). Să vedem cum facem o funcție care să afișeze cifrele unui număr: 123456

private static void cifre(int n) {    while (n > 0) {        System.out.println(n % 10);        n /= 10;    }}

Observăm că este posibil ca blocul de instrucțiuni care formează bucla să nu se execute niciodată în cazul în care condiția nu este îndeplinită la prima verificare. Acest lucru s-ar întâmpla dacă am apela funcția de mai sus transmițând ca argument un număr negativ sau zero.

De asemenea, trebuie să avem în vedere că în corpul buclei trebuie să existe la un moment dat ceva care afectează condiția care este evaluată. Altfel, aceasta va rămâne tot timpul adevărată (dacă a fost prima dată) și

Page 60: Fundamentele programării

corpul său se va executa la infinit dacă nu este înterupt prin alt mecanisme (de exemplu printr-unreturn).While în whileAm spus că instrucțiunea while poate apărea oriunde. De exemplu, ar putea fi parte a blocului de instrucțiuni al unei alte instrucțiuni while. Să încercăm să scriem un program care afișează tabla înmulțirii până la zece. Vom avea numerele de la unu la zece ca prim factor și, pentru fiecare dintre acestea, numerele de la unu la zece ca al doilea factor. Să vedem cum ar arăta o funcție care ar realiza acest lucru: 123456789101112

private static void tablaInmultirii() {    int factor1 = 1;    while (factor1 <= 10) {        int factor2 = 1;        while (factor2 <= 10) {            System.out.print("\t" + factor1 * factor2);            factor2++;        }        System.out.println();        factor1++;    }}

Am separat valorile prin taburi pentru a le alinia puțin mai frumos. Așa cum există caracterul special pentru sfârșit de linie, există și un caracter special pentru tab; acesta este \t. Dacă este apelată funcția de mai sus, la ieșire vom avea ceva de genul:

12345678910

1 2 3 4 5 6 7 8 9 102 4 6 8 10 12 14 16 18 203 6 9 12 15 18 21 24 27 304 8 12 16 20 24 28 32 36 405 10 15 20 25 30 35 40 45 506 12 18 24 30 36 42 48 54 607 14 21 28 35 42 49 56 63 708 16 24 32 40 48 56 64 72 809 18 27 36 45 54 63 72 81 9010 20 30 40 50 60 70 80 90 100

Mai trebuie să observăm că variabila factor2 este declarată și utilizată în interiorul primei bucle. Domeniul de vizibilitate al acestei variabile este doar în blocul de instrucțiuni care formează corpul buclei; pentru fiecare execuție a corpului primei bucle, va fi declarată și utilizată o nouă variabilă, care nu are nicio

Page 61: Fundamentele programării

legătură cu variabilele cu același nume declarate și utilizate în timpul execuțiilor anterioare sau ulterioare.Instrucțiunea do whilePână acum secvențele noastre erau de genul: cât timp o anumită condiție este îndeplinită execută instrucțiunile următoare. Avem la dispoziție o variație: execută instrucțiunile următoare cât timp o anumită condiție este îndeplinită.În noua variantă, executăm instrucțiunile și abia apoi verificăm dacă este îndeplinită condiția. Dacă este îndeplinită mai executăm odată instrucțiunile și tot așa cât timp este îndeplinită acea condiție. Observăm că în această situație vom executa corpul buclei cel puțin odată.

Noua instrucțiune începe cu do, urmat de instrucțiunea sau blocul de instrucțiuni care formează corpul buclei, de cuvântul while și de condiția care trebuie verificată la sfârșit, între paranteze. Să rescriem funcția care afișează cifrele unui număr: 123456

private static void cifre(int n) {     do {         System.out.println(n % 10);         n /= 10;     } while (n > 0); }

Observăm un efect interesant; datorită faptului că se va executa cel puțin odată corpul buclei, de data aceasta vom avea rezultatul corect și dacă apelăm funcția cu argumentul zero.

Fundamentele programării (XI) - JavaDE MIHAI SCORȚARU · 27 IULIE 2015

Am arătat în episodul anterior cum putem face în așa fel încât să executăm în mod repetat instrucțiuni atâta timp cât o condiție este îndeplinită. Să considerăm acum un exemplu simplu: dorim să scriem o funcție care să afișeze toate numerele naturale cuprinse între 1 și o valoare pe care o primește ca parametru. Destul de simplu, nu? Ar fi cam așa:

Page 62: Fundamentele programării

1234567

private static void numere(int n) {    int i = 1;    while (i <= n) {        System.out.println(i);        i++;    }}

Dacă privim cu atenție codul, identificăm patru componente: în linia 2 avem inițializarea unei variabile; în linia 3 avem condiția (influențată și de variabila menționată), în linia 4 avem instrucțiunea care realizează operație care dorim să fie repetată și în linia 5 avem o instrucțiune care modifică variabila pentru ca, la un moment dat, condiția să nu mai fie îndeplinită.

Acesta este un șablon atât de des întâlnit, încât limbajul Java oferă o prescurtare.Instrucțiunea forNoua instrucțiune permite specificarea inițializării, a condiției și a modificării într-un format mai compact. Practic, avem cuvântul for, urmat de inițializare, condiție și modificare, cuprinse între paranteze și separate prin semnul ; și apoi de instrucțiunea sau blocul de instrucțiuni care trebuie executate la fiecare iterație. Funcția noastră ar putea fi rescrisă astfel:

123456

private static void numere(int n) {    int i;    for (i = 1; i <= n; i++) {        System.out.println(i);    }}

Observăm variabila i declarată în linia 2. Nu are nicio utilitate în afara buclei; limbajul Java ne permite să punem declarația în zona de inițializare:

12345

private static void numere(int n) {    for (int i = 1; i <= n; i++) {        System.out.println(i);    }}

Page 63: Fundamentele programării

Există o diferență între cele două versiuni. Vă dați seama care este? Este vorba de domeniul de vizibilitate al variabilei i. În prima variantă ea este vizibilă în interiorul întregii funcții, în cea de-a doua este vizibilă doar în interiorul buclei. Dar, nu e cam și cum ar fi fost declarată în corpul buclei; atunci și-ar fi pierdut valoarea de la o iterație la alta; dacă e declarată în zona de inițializare a buclei, variabila există din momentul în care începe execuția buclei și până se termină (când condiția nu mai este adevărată). Trebuie să facem distincție între execuția întregii bucle și execuția unei iterații a buclei.Dacă alegem prima variantă, valoarea finală a variabilei va fi disponibilă după încheierea execuției buclei.

Operatorul virgulăÎn Java avem la dispoziție un operator interesant, reprezentat printr-o virgulă (semnul ,). Acesta este un operator binar; el evaluează valoarea primului operand, o ignoră și apoi evaluează valoarea celui de-al doilea. Pare inutil, dar nu este deloc așa.Practic, dacă avem expresii, le putem înlănțui cu virgule (nu spune nimeni că al doilea operand nu poate include, la rândul său, operatorul virgulă).

Un prim efect interesant este că dacă avem doar o serie de atribuiri sau apeluri de funcții, le putem separa prin , în loc de ;. Nu are nicio utilitate practică, dar se poate (atâta timp cât nu avem nevoie de un if, un while, un for, un switch etc.).Dar, unul dintre locurile în care acest operator este util, este zona de inițializare a instrucțiunii for. Putem inițializa mai multe variabile dacă dorim. De asemenea, putem folosi operatorul și în zona de incrementare / decrementare (aceasta este o denumire utilizată pentru a treia zonă, deoarece de obicei operațiile care apar acolo sunt incrementări sau decrementări, deși nu este obligatoriu). I se mai spune, simplu, zona de incrementare (mult mai des avem incrementări).Următoarea funcție utilizează aceasta facilitate. Încercați să vă dați seama ce se afișează!

Page 64: Fundamentele programării

12345

private static void perechi(int n) {     for (int i = 0, j = n; i <= j; i++, j--) {         System.out.println(i + " " + j);     } }

Trebuie avute în vedere câteva restricții: dacă folosim declarații în zona de inițializare, atunci toate variabilele care apar trebuie să fie noi și trebuie să aibă același tip. Niciuna dintre următoarele variante nu este permisă:

12345678910

for (int i = 0, double j = n; i <= j; i++, j--) {...} int i;for (i = 0, int j = n; i <= j; i++, j--) {...} int i;for (int i = 0, j = n; i <= j; i++, j--) {...} int j;for (int i = 0, j = n; i <= j; i++, j--) {...}

Oricare dintre cele trei zone poate lipsi. Dacă lipsește zona de inițializare, înseamnă că vom opera asupra altor variabile. Dacă lipsește condiția, înseamnă că ne bazăm pe alte mecanisme pentru a întrerupe execuția buclei (de exemplu un return; altele vor fi prezentate în episodul următor). Dacă lipsește zona de incrementare / decrementare, înseamnă că ne bazăm pe alte mecanisme pentru a afecta condiția (în principiu, modificări în corpul buclei).For în forCum era de așteptat, în cadrul corpului buclei pot apărea orice fel de instrucțiuni, inclusiv un alt for. Până acum am spus că este permis if în if (episodul IV) sau while în while (episodul X). Ne putem imagina că este permis și pentru alte instrucțiuni: am putea avea do în do, switch în switch și, acum,for în for. De fapt, știm că nu trebuie să ne limităm doar la un nivel de imbricare (vă mai amintiți termenul?). Și... instrucțiunile nu trebuie să fie de același fel: nimic nu ne oprește să avem if în while înfor în switch în for. Nu ar fi prea bine să ajungem să avem așa ceva fiindcă am înțelege cu greu ce se întâmplă exact în zona respectivă, dar este posibil.Să nu credem totuși că este permis orice! De exemplu, în Java nu putem avea o funcție în interiorul altei funcții. Dar, ca de obicei, există excepții...

Page 65: Fundamentele programării

Dar, să revenim la for în for; e destul de simplu. Să scriem o funcție care afișează numerele puțin altfel; fiecare va fi reprezentat de niște steluțe, numărul acestora indicând valoarea numărului.

12345678

private static void numere(int n) {    for (int i = 1; i <= n; i++) {     for (int j = 1; j <= i; j++) {         System.out.print('*');     }        System.out.println();    }}

Dacă am apela funcția cu argumentul 10, la ieșire s-ar scrie:

12345678910

*******************************************************

În situațiile simple în care avem o singură variabilă care apare în zonele de inițializare și incrementare și este implicată și în condiție, spunem că ea controlează bucla respectivă.

În principiu, buclele imbricate sunt controlate de variabile diferite, chiar dacă o variabilă dintr-o buclă exterioară poate fi folosită într-una interioară. În cazul nostru, variabila i care controlează prima buclă este utilizată în condiția celei de-a doua. Din nou, sunt excepții; putem (în teorie) să folosim aceeași variabilă pentru a controla o buclă interioară, atâta timp cât nu o redeclarăm; totuși, în marea majoritate a cazurilor așa ceva nu este de dorit.Din nou, este important domeniul de vizibilitate al variabilelor. O buclă interioară poate accesa sau modifica o variabilă declarată într-un exterioară, dar invers nu este posibil.

Page 66: Fundamentele programării

Fundamentele programării (XII) - JavaDE MIHAI SCORȚARU · 3 AUGUST 2015

În cadrul episodului VIII am văzut că putem întrerupe execuția unei funcții folosind instrucțiunea return. Uneori, s-ar putea să avem nevoie de întreruperea unei bucle. Dacă suntem în interiorul unei funcții și este OK să se înterupă execuția întregii funcții, putem folosi return. Dar, în multe situații vrem să continuăm cu intrucțiunile care urmează după buclă.Să vedem un exemplu: o modalitate simplă (dar ineficientă) de a verifica dacă un număr este prim este numărarea divizorilor săi. Dacă sunt exact doi, atunci numărul este prim. O funcție care afișează dacă un număr primit ca parametru este prim, ar putea arăta astfel:

123456789101112131415

private static void prim(int n) {int divizori = 0;int d = 1;while (d <= n) {

if (n % d == 0) {divizori++;

}d++;

}if (divizori == 2) {

System.out.println(n + " este prim!");} else {

System.out.println(n + " nu este prim!");}

}

Avem o variabilă divizori  pe care o folosim pentru a număra divizorii și o variabilă d care va conține potențialii divizori (toate numerele cuprinse între 1 și n). La fiecare pas verificăm dacă n se împarte exact la valoarea curentă a lui d. Dacă da, creștem numărul divizorilor. Indiferent dacă d a fost sau nu divizor a lui n, trecem la următorul potențial divizor incrementând valoarea d. Ne oprim doar atunci cândd devine mai mare decât n (cu alte cuvinte, continuăm cât timp d este mai mic sau egal

Page 67: Fundamentele programării

cu n). La sfârșit verificăm dacă numărul divizorilor este exact 2 și scriem un mesaj corespunzător ( n este sau nu prim).Funcționează pentru orice număr pozitiv; dar, putem observa destul de ușor că, dacă am ajuns să avem trei divizori, am vrea să ne oprim. Nu putem folosi instrucțiunea return fiindcă s-ar întrerupe execuția întregii funcții și nu am mai afișa mesajul de la final. Funcția ar putea arăta așa:

123456789101112131415161718

private static void prim(int n) {int divizori = 0;int d = 1;while (d <= n) {

if (n % d == 0) {divizori++;

}if (divizori == 3) {

return;}d++;

}if (divizori == 2) {

System.out.println(n + " este prim!");} else {

System.out.println(n + " nu este prim!");}

}

Mesajul nu va mai fi afișat decât pentru numerele prime (și pentru zero sau unu). Am putea să modificăm variabilele implicate în evaluarea condiției și să forțăm astfel întreruperea. De exemplu, am putea modifica linia 9 astfel încât d să devină mai mare decât n:

12345

private static void prim(int n) {int divizori = 0;int d = 1;while (d <= n) {

if (n % d == 0) {

Page 68: Fundamentele programării

6789101112131415161718

divizori++;}

                if (divizori == 3) {                        d = n + 1;                }

d++;}if (divizori == 2) {

System.out.println(n + " este prim!");} else {

System.out.println(n + " nu este prim!");}

}

Execuția buclei nu se oprește imediat; incrementarea din linia 11 se va execută. În cazul nostru această incrementare este inofensivă ( d va deveni n + 2 și condiția de continuare a buclei nu va mai fi îndeplinită). De fapt, puteam pune doar d = n; în linia 9 și incrementarea din linia 11 ar fi făcut în așa fel încât condiția să nu mai fie îndeplinită. Dar, nu este deloc bine să ne bazăm pe astfel de efecte colaterale.Dar, în unele situații instrucțiunile care urmează după momentul în care dorim întreruperea ar putea avea efecte nedorite. Poate vrem ca execuția buclei să se oprească de tot.

De obicei, întrerupem execuția în cazul îndeplinirii unei condiții, deci avem un if. Putem pune tot ce urmează în else și atunci totul va funcționa așa cum ne dorim.

1234567891011

private static void prim(int n) {int divizori = 0;int d = 1;while (d <= n) {

if (n % d == 0) {divizori++;

}                if (divizori == 3) {

d = n + 1;} else {

d++;}

}

Page 69: Fundamentele programării

1213141516171819

if (divizori == 2) {System.out.println(n + " este prim!");

} else {System.out.println(n + " nu este prim!");

}}

Soluția este acceptabilă în cazul în care corpul buclei nu are o structură foarte complicată. Dar, există și altfel de situații: poate condiția de înterupere este verificată în interiorul unui alt if și după acestif exterior există alte instrucțiuni. Soluția noastră cu else nu ar funcționa; am avea nevoie de alte "artificii" pentru a evita executarea acestor instrucțiuni.Din fericire, avem la dispoziție o instrucțiune care face exact ce vrem: break (Vă amintiți de ea de laswitch? - episodul V). După executarea ei, bucla în interiorul căreia a apărut instrucțiunea se întrerupe (nici iterația curentă nu continuă). Codul redevine simplu, fiind aproape identic cu cel de la încercarea cureturn, dar de data aceasta mesajul de final nu se mai pierde (singura modificare este în linia 9).

12345678910111213141

private static void prim(int n) {int divizori = 0;int d = 1;while (d <= n) {

if (n % d == 0) {divizori++;

}                if (divizori == 3) {                        break;                }

d++;}if (divizori == 2) {

System.out.println(n + " este prim!");} else {

System.out.println(n + " nu este prim!");}

}

Page 70: Fundamentele programării

5161718Atât pentru varianta aceasta cât și pentru unele dintre cele anterioare putem face niște modificări care să îmbunătățească puțin performanța. Nu are niciun rost să verificăm dacă am ajuns la trei divizori decât dacă tocmai am incrementat numărul acestora. Funcția rescrisă ar putea fi următoarea:

123456789101112131415161718

private static void prim(int n) {int divizori = 0;int d = 1;while (d <= n) {

if (n % d == 0) {divizori++;

                 if (divizori == 3) {                         break;                 }                }

d++;}if (divizori == 2) {

System.out.println(n + " este prim!");} else {

System.out.println(n + " nu este prim!");}

}

Există numeroase alte optimizări care pot fi făcute; așa cum am spus la început, această modalitate de verificare a primalității unui număr este ineficientă.

Ce se întâmplă dacă avem bucle imbricate? Instrucțiunea break are efect doar în interiorul buclei din care face parte; buclele "exterioare" nu sunt afectate. Dacă dorim să întrerupem toate buclele trebuie să căutăm alte soluții.

Page 71: Fundamentele programării

Uneori nu dorim să întrerupem execuția buclei, ci doar să oprim execuția iterației curente (să sărim direct la evaluarea condiției). Pentru aceasta avem la dispoziție instrucțiunea continue. Ea este utilă dacă la fiecare pas executăm anumite operațiuni, dar atunci când o anumită condiție este îndeplinită nu are rost să le continuăm.Având la dispoziție o funcție prim ușor modificată (returnează o valoarea booleană care ne spune dacă un număr este sau nu prim), am putea dori să afișăm suma și produsul numerelor prime cuprinse între1 și 20. Putem găsi multe soluții, printre care și una care folosește continue:

123456789101112131415161718192021222324

class NumerePrime{

private static boolean prim(int n) {int divizori = 0;int d = 1;while (d <= n) {

if (n % d == 0) {divizori++;if (divizori == 3) {

break;}

}d++;

}if (divizori == 2) {

return true;} else {

return false;}

}

public static void main (String[] args) throws java.lang.Exception{

int suma = 0;int produs = 1;for (int i = 1; i <= 20; i++) {

if (!prim(i)) {continue;

}suma += i;produs *= i;

}System.out.println("Suma: " + suma);System.out.println("Produsul: " + produs);

}}

Page 72: Fundamentele programării

252627282930313233343536Putem face câteva observații, care nu sunt neapărat legate de break sau continue:

Datorită faptului că prim returnează o valoare booleană și rezultatul evaluării unei condiții este o astfel de valoare, codul din liniile 15 - 19 poate fi înlocuit cu un simplu return divizori == 2;.

Noua funcție prim returnează doar valoarea booleană, fără a mai afișa nimic; din acest motiv ar fi fost corect ca în linia 10 să folosim direct return false; pentru a întrerupe execuția funcției, fără să ne mai intereseze bucla (evident, și execuția ei ar fi fost întreruptă); la sfârșit am fi putut presupune că numărul este prim dacă nu este zero sau unu și am fi putut avea în linia 15 returnn > 1;.

Am calculat o sumă și un produs de mai multe numere; calculul se efectuează pas cu pas, adăugând sau înmulțind de fiecare dată câte un număr. Valorile inițiale sunt date de elementele neutre ale operațiilor (zero pentru adunare și unu pentru înmulțire). Folosind acest model puteți încerca să scrieți secvențe de cod care efectuează diverse calcule: suma numerelor impare cuprinse între 1 și 100 suma pătratelor numerelor cuprinse între 1 și 1000 produsul numerelor pare cuprinse între 1 și 10 diferența dintre suma pătratelor numerelor pare cuprinse între 1

și 100 și suma pătratelor numerelor impare cuprinse între 1 și 100.

Page 73: Fundamentele programării

Fundamentele programării (XIII) - JavaDE MIHAI SCORȚARU · 17 AUGUST 2015

Am văzut până acum că avem șiruri de caractere (string-uri) și acestea sunt foarte utile pentru a reprezenta texte. Dar, poate avem nevoie și de alte tipuri de șiruri... De exemplu, am putea avea nevoie de șiruri de numere.

ȘiruriPutem spune că un șir este o colecție de valori, puse împreună, care au o denumire. Sunt întâlnite diverse denumiri pentru acest concept: șir, vector, listă sau englezescul array. În Java, termenul folosit este, de obicei, array.Pentru a lucra cu șiruri va trebui să le declarăm, să le dăm valori și să dăm valori și elementelor care fac parte din șir.

În Java, șirurile trebuie să conțină elemente de același tip. Pentru a declara un șir va trebui să specificăm tipul elementelor din șir, să precizăm că de fapt vrem să avem un șir, nu o simplă variabilă și să alegem o denumire. Pentru a preciza că dorim să lucrăm cu un șir, imediat după tip adăugăm o paranteză dreaptă deschisă și una închisă.De exemplu, pentru a declara un șir de numere întregi, declarația folosită ar putea fi:

1 int[] a;Trebuie acum să dăm o valoare variabilei a; varianta standard este puțin mai ciudată. Vom folosi cuvântulnew pentru a preciza că este vorba de un nou șir, urmat de tipul elementelor din șir și apoi de numărul elementelor cuprins între paranteze drepte. Pentru ca a să fie un șir format din 10 elemente, am putea scrie:

Page 74: Fundamentele programării

1 a = new int[10];La fel ca în cazul variabilelor simple, putem inițializa șirul în momentul declarării sale. Cele două linii de mai sus pot fi combinate în:

1 int[] a = new int[10];

Accesarea elementelorȘirurile sunt excelente pentru a lucra cu date care au sens să fie grupate. Putem evita să declarăm câte o variabilă pentru fiecare. Putem avea zeci, sute sau mii de valori care sunt păstrate împreună și avem o singură variabilă. Dar, cum lucrăm cu valorile individuale? Cum vedem care este primul element al șirului, care este al doilea și așa mai departe?

Într-un array, elementele sunt numerotate (începând cu 0). Numărul de ordine al unui element în șir poartă denumirea de indice. Pentru a accesa un anumit element, trebuie să folosim variabila care reprezintă șirul, urmată de indicele respectiv, cuprins între paranteze drepte.De exemplu, pentru a da o valoare celui de-a șaselea element al șirului nostru, am putea scrie:

1 a[5] = 47;Observați că am scris a[5], nu a[6], fiindcă numerotarea începe de la 0. În acest mod putem da valori tuturor elementelor șirului.Dar, dorim și să accesăm valorile acestor elemente. Acest lucru se realizează în același fel. Pentru a scrie valoarea celui de-a șaselea element al șirului, am putea folosi instrucțiunea:

1 System.out.println(a[5]);

Inițializare mai simplă

Page 75: Fundamentele programării

Am văzut că trebuie să inițializăm șirul și apoi să precizăm valorile tuturor elementelor. De exemplu, dacă am dori să avem un șir care să conțină numărul zilelor din lunile anului, am putea avea o secvență de genul:

12345678910111213

int[] zile = new int[12];zile[0] = 31;zile[1] = 28;zile[2] = 31;zile[3] = 30;zile[4] = 31;zile[5] = 30;zile[6] = 31;zile[7] = 31;zile[8] = 30;zile[9] = 31;zile[10] = 30;zile[11] = 31;

Am presupus că nu avem de-a face cu un an bisect...

Pare complicat și ne-ar plăcea să putem face mai simplu. Din fericire, ni se oferă o prescurtare:

1 int[] zile = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};Putem specifica șirul cuprins între acolade, elementele sale fiind separate prin virgule. Nu mai este necesar să precizăm câte elemente are șirul; numărul elementelor va fi egal cu numărul valorilor dintre acolade.

Șiruri ca parametriPutem folosi șiruri cam peste tot unde am folosit un tip simplu. De exemplu, putem crea funcții ale căror parametri să fie șiruri; am putea avea o funcție care are doi parametri; primul este numărul zilelor din lunile anului; al doilea este numărul de ordine al unei luni (numerotarea începe cu 0); funcția va afișa numărul zilelor din luna respectivă. Un program ar putea fi:

Page 76: Fundamentele programării

123456789101112131415

class Zile {

private static void zile(int[] an, int luna) {System.out.println(an[luna]);

}

public static void main (String[] args) {int[] anBisect = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};int[] anNebisect = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};zile(anBisect, 7);zile(anNebisect, 7);zile(anBisect, 1);zile(anNebisect, 1);

}}

Observăm câteva aspecte interesante:

indicele nu trebuie să fie un număr întreg precizat ca atare; putem folosi o variabilă (în acest caz un parametru al funcției) care are ca valoare un număr întreg;

pentru fiecare apel am ales șirul pe care să îl transmitem ca argument al funcției; două apeluri folosesc zilele din anii bisecți și două zilele din anii nebisecți.

Poate ne-am aștepta să putem scrie și ceva de genul:

1 zile({31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 1);Limbajul Java nu ne permite o construcție atât de simplă, dar putem folosi ceva apropiat:

1 zile(new int[] {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 1);

Page 77: Fundamentele programării

Fundamentele programării (XIV) - JavaDE MIHAI SCORȚARU · 24 AUGUST 2015

Până acum am creat șiruri și am accesat elemente individuale ale acestora. Dar, nu prea are rost să grupăm elemente împreună dacă nu le și folosim împreună. În cadrul acestui episod vom vedea cum putem folosi întregul șir.

În majoritatea operațiilor cu șiruri pe care le folosim trebuie să lucrăm cu fiecare element al șirului. Spunem că parcurgem, traversăm sau iterăm elementele șirului respectiv.Traversarea clasicăSă presupunem că avem un șir și dorim să calculăm suma elementelor sale. Vom crea o funcție care va primi ca parametru un șir și numărul elementelor acestuia și va returna suma acestor elemente.

Pentru a parcurge șirul vom folosi o variabilă care va avea valori cuprinse între 0 și n - 1, unde n este numărul elementelor șirului. Cu ajutorul acesteia vom putea accesa fiecare element al șirului și le putem aduna. Funcția noastră ar putea fi următoarea:

1234567

private static int suma(int[] sir, int n) {int suma = 0;for (int i = 0; i < n; i++) {

suma += sir[i];}return suma;

}Observăm că instrucțiunea din linia 3 face ca variabila i să aibă, pe rând, valorile cuprinse între 0 și n - 1; apoi, în linia 4, prin sir[i] accesăm cel de-al i-lea element al șirului și adunăm la sumă valoarea respectivă. Pentru a calcula suma am folosit metoda prezentată la sfârșitul episodului XII (inițializarea cu 0 și adunarea succesivă a valorilor).Acum, am putea efectua apeluri de genul:

Page 78: Fundamentele programării

12

System.out.println(suma(new int[] {1, 2, 3}, 3));int s = suma(new int[]{2457, 47}, 2);

Proprietatea lengthEste oarecum neplăcut că a trebuit să precizăm lungimea șirului. De fapt, e chiar riscant; putem greși destul de ușor. De exemplu, am putea folosi o valoare prea mică și atunci nu am mai aduna toate numerele sau am putea folosi o valoare prea mare și atunci am încerca să adunăm elemente care nu există. Puteți încerca să vedeți ce se întâmplă dacă efectuăm apelurile următoare:

12

System.out.println(suma(new int[] {1, 2, 3}, 2));System.out.println(suma(new int[] {1, 2, 3}, 4));Ne-am dori să putem calcula automat această valoare. Din fericire, array-urile au o proprietate care ne spune câte elemente conțin. Pentru a accesa o proprietate trebuie să precizăm variabila, urmată de un punct și de numele proprietății.Proprietatea care conține numărul elementelor unui array este length. Așadar, pentru a determina numărul elementelor șirului a, putem folosi a.length.Să încercăm acum să rescriem apelul:

12

int[] a = {1, 2, 3};System.out.println(suma(a, a.length));Apelând în acest mod, evităm să greșim dimensiunea șirului, dar parcă ar fi mai bine ca funcția să știe să își determine singură numărul elementelor. Nici nu e prea greu să o modificăm; nu vom mai avea n ca parametru; îl vom calcula. Noua funcție ar putea fi:

1234567

private static int suma(int[] sir) {int n = sir.length;int suma = 0;for (int i = 0; i < n; i++) {

suma += sir[i];}return suma;

Page 79: Fundamentele programării

8 }Apelurile modificate sunt:

12

System.out.println(suma(new int[] {1, 2, 3}));int s = suma(new int[]{2457, 47});Dimensiunea unui șir este un număr și poate folosită oriunde este folosit un număr; nu trebuie nepărat să stocăm valoarea într-o altă variabilă. Putem scăpa de n cu totul:

1234567

private static int suma(int[] sir) {int suma = 0;for (int i = 0; i < sir.length; i++) {

suma += sir[i];}return suma;

}

Instrucțiunea for eachÎn exemplele de până acum am avut nevoie de toate elementele dintr-un șir. Pentru aceasta am folosit o variabilă care lua pe rând valorile tuturor indicilor posibil și apoi accesam elementele respective. Scenariul este atât de frecvent încât limbajul Java ne oferă o "scurtătură", așa-numita instrucțiune for each (în traducere, pentru fiecare).Practic, vom preciza doar șirul cu care lucrăm și o variabilă care va conține, pe rând, valorile elementelor șirului respectiv. Numărul iterațiilor este dat de numărul elementelor șirului (dacă nu este întâlnită vreo instrucțiune care să întrerupă prematur execuția buclei: break, return sau altele pe care nu le-am prezentat încă).Pentru a folosi noua instrucțiune vom scrie cuvântul for, urmat de o paranteză deschisă, declarația variabilei care va conține valorile, semnul :, un șir, o paranteză închisă și apoi instrucțiunea sau blocul de instrucțiuni care formează corpul buclei.Putem rescria funcția noastră astfel:

Page 80: Fundamentele programării

1234567

private static int suma(int[] sir) {int suma = 0;for (int valoare : sir) {

suma += valoare;}return suma;

}Evident, tipul variabilei care va conține elementele șirului trebuie să fie același cu tipul acestor elemente.