Sunteți pe pagina 1din 384

Ministerul Educaţiei, Cercetării şi Tineretului

Vlad Tudor Huţanu


Carmen Popescu

Manual de

PENTRU CLASA A XII-A

filiera teoretică, profil real, specializarea: matematică-informatică,


intensiv informatică

Aprobat prin ordinul MEdCT nr. 1561/83 din 23.07.2007

L&S Info-mat
Copyright 2007-2016  L&S INFO-MAT

Toate drepturile asupra acestei lucrǎri aparţin editurii L&S INFO-MAT.


Reproducerea integralǎ sau parţialǎ a textului din aceastǎ carte este posibilǎ
doar cu acordul în scris al editurii L&S INFO-MAT.

Manualul a fost aprobat prin Ordinul Ministrului Educaţiei, Cercetǎrii şi Tineretului


nr. 1561 / 83 din 23.07.2007 în urma evaluǎrii calitative şi este realizat în
conformitate cu programa analiticǎ aprobatǎ prin Ordin al ministrului Educaţiei şi
Cercetǎrii nr. 5959 din 22.12.2006.

Refenţi ştiinţifici:
Prof. Gradul I Carmen Mincǎ, Colegiul Naţional “Sf. Sava", Bucureşti
Prof .Gradul I, Enciu Magdalena, Colegiul Naţional “Octav Onicescu”, Bucureşti

Tiparul executat la S.C. LuminaTipo S.R.L.


Str. Luigi Galvani nr. 20 bis, Sector 2, Bucureşti,
office@luminatipo.com

Editura L&S INFO-MAT:


Adresa: Str. Stânjeneilor nr. 6, bl. 30, sc. A, et. 1, apt. 11, sector 4, Bucureşti;
Mobil: 0722-573701; 027.731.947;
E-mail: office@ls-infomat.ro;
Web Site: www.ls-infomat.ro.
CUPRINS

Partea I. Baze de date 7


Capitolul 1. Proiectarea bazelor de date 7
1.1. Noţiuni introductive 8
1.2. Normalizarea datelor 22
1.3. Implementarea modelului conceptual 29
1.4. Managementul de proiect 41
Teme de proiect 45

Partea a II-a. Programare WEB 47


Capitolul 2. Limbajul MySQL 47
2.1. Ce este şi de ce învăţăm MySQL ? 48
2.2. Cum rulăm MySQL pe propriul calculator ? 49
2.3. Crearea unei baze de date 50
2.4. Tabele. Noţiuni elementare 51
2.5. Tipuri de date în MySQL 53
2.6. Operatori utilizaţi în MySQL 57
2.7. Funcţii MySQL 62
2.8. Afişarea coloanelor care rezultă în urma unui calcul 65
2.9. Valoarea NULL 66
2.10. Valori implicite 68
2.11. Cheie primară şi cheie unică 69
2.12. Autoincrementare 71
2.13. Sortarea datelor 72
2.14. Filtrarea datelor 73
2.15. Actualizări într-un tabel 74
2.16. Funcţii agregate 77
2.17. Utilizarea subinterogărilor 78
2.18. Gruparea datelor 80
2.19. Uniuni de tabele 82
2.20. Elemente care privesc securitatea bazelor de date 85
Probleme Propuse 86
4 Manual de Informatică pentru clasa a XII-a

Capitolul 3. Primii paşi către construcţia unui site 90


3.1. Ce este Internetul ? 91
3.2. Protocolul TCP/IP 92
3.3. Despre site-uri 94
3.4.Un program care rulează sub FTP 97
3.5. Cum scriem un fişier HTML ? 99
Teste recapitulative 103

Capitolul 4. HTML, CSS – primele noţiuni 104


4.1. Structura de bază a unei pagini HTML+CSS 105
4.2. Elemente HTML pentru afişarea textelor 109
4.3. Atribute CSS pentru font-uri 114
4.4. Atribute CSS pentru texte 115
4.5. Liste 117
4.6. Structura unui element HTML 120
4.7. Atribute de culoare şi fond 122
4.8. Atribute pentru margini 125
4.9. Atribute pentru padding 125
4.10. Atribute pentru bordură 125
4.11. Elementul IMG 126
4.12. Tabele 128
4.13. Hiperlegături (link-uri) 133
4.14. Hărţi imagine 140
4.15. Elementele BASE, META şi SCRIPT 145
4.16. Cadre (FRAMESET, FRAME şi IFRAME) 147
4.17. Elementul MARQUEE 152
4.18. Aşezarea implicită în pagină a diverselor elemente 153
4.19. Alte modalităţi de aşezare în pagină a elementelor 155
4.20. Atributul z-index 157
4.21. Atributul display 159
4.22. Caractere HTML 160
4.23. Aspecte generale ale proiectării interfeţelor web 161
Probleme propuse 165

Capitolul 5. Limbajul PHP 169


5.1. Introducere 170
5.2. Formulare 172
5.3. Elementul TEXTAREA 176
5.4. Elementul SELECT 176
5.5. Constante. Variabile. Operatori 177
5.6. Instrucţiunile limbajului PHP 181
Cuprins 5

5.7. Funcţii în PHP 184


5.8. Funcţii “matematice” 187
5.9. Afişarea datelor - echo şi print 188
5.10. Funcţii pentru prelucrarea şirurilor de caractere 189
5.11. Masive în PHP 192
5.12. Variabile cookie 195
5.13. Utilizarea în comun a limbajelor PHP şi MySQL 197
5.14. Aplicaţii 203
5.15. Proiectarea paginilor web 212
Probleme propuse 213
Teme de proiect 215

Partea a III-a. Programare orientată pe obiecte şi


programare vizuală 216

Capitolul 6. Iniţiere în utilizarea limbajului Java 216


6.1. Cum instalăm Java ? 217
6.2. Primul program 219
6.3. Conceptul de Maşină Virtuală Java (JVM) 220
6.4. Tipuri de aplicaţii Java 221
6.5. Comentarii 222
6.6. Afişarea şirurilor de caractere 222
6.7. Tipuri de date 222
6.8. Operatori 225
6.9. Instrucţiuni 234
6.10. Masive 240
6.11. Citirea datelor de la tastatură 244
Probleme rezolvate 246
6.12. Date membru 248
6.13. Metode 248
6.14. Exemple de utilizare a metodelor 251
6.15. Supraîncărcarea metodelor 252
Capitolul 7. Programare orientată pe obiecte 253
7.1. Principiile programării orientate pe obiecte 254
7.2. Constructori 256
7.3. Date membru statice şi metode statice 258
7.4. Cuvântul cheie “this” 259
7.5. Referinţe către obiecte 259
7.6. Masive de obiecte 261
7.7. Aplicaţii ale noţiunilor prezentate. Lucrul cu numere raţionale 263
7.8. Studiul unor clase din limbajul Java 267
7.9. Extinderea claselor (moştenirea) 276
7.10. Polimorfism 282
6 Manual de Informatică pentru clasa a XII-a

7.11. Clase abstracte 287


7.12. Interfeţe 290
7.13. Specificatori de acces (modificatori de acces) 293
7.14. Excepţii (tratarea erorilor) 296
Probleme propuse 305

Capitolul 8. Programare vizuală 311


8.1. Conceptele de bază ale programării vizuale în Java 312
8.2. Studiul principalelor componente 326
8.3. Obiecte grafice. Clasa Graphics 351
8.4. Accesarea şi prelucrarea datelor 356
Probleme propuse 363
Teme de proiect 366

Anexa 1. Instalarea programelor Apache, PHP şi MySQL 367

Anexa 2. Dezvoltarea profesională în domeniul IT 369

Anexa 3. Caractere HTML 377

Indicaţii / Răspunsuri 380


PARTEA I CAPITOLUL
Proiectarea bazelor de date

În acest prim capitol veţi studia principiile generale ale proiectării


bazelor de date, vă veţi familiariza cu diversele anomalii care pot invalida
bazele de date, precum şi cu modalităţile de evitare ale acestora.
De asemenea, se va defini modelul conceptual al unei baze de date.
În ultima parte a capitolului, vor fi prezentate etapele realizării
unui proiect, avantajele lucrului în echipă şi veţi învăţa cum
să pregătiţi şi să susţineţi o prezentare în faţa publicului.

 Ce este modelul conceptual şi care este rolul său ?


 Ce este un ERD ?
 Ce este o entitate şi cum se reprezintă ea într-un ERD ?
 Ce este o instanţă ?
 Ce sunt şi cum se stabilesc atributele unei entităţi ?
 Cum se stabilesc relaţii între entităţi ?
 Ce tipuri de relaţii pot exista între entităţi ?
 Cum se reprezintă relaţiile în ERD ?
 Normalizarea datelor
 Cum se implementează modelul conceptual ?
 Managementul de proiect

Cuvinte cheie: dată, informaţie, cunoştinţă, analiză, model


conceptual, entitate, instanţă, atribut, identificator unic, relaţie,
normalizare, mapare, integritate, proiect, echipă, prezentare
8 Manual de Informatică pentru clasa a XII-a

1.1. Noţiuni introductive

1.1.1. Date. Informaţii. Cunoştinţe

Auzim adesea vorbindu-se despre “era informaţiilor” sau “societatea


informaţională” sau “tehnologia informaţiei”, însă de multe ori cuvântul "informaţie"
este folosit fără a-i înţelege clar sensul, diferenţa dintre date, informaţii sau
cunoştinţe.
În general, conţinutul gândirii umane operează cu următoarele concepte:
• Date – constau în material brut, fapte, simboluri, numere, cuvinte, poze
fără un înţeles de sine stătător, neintegrate într-un context, fără relaţii cu
alte date sau obiecte. Ele se pot obţine în urma unor experimente,
sondaje, etc.
• Informaţii – prin prelucrarea datelor şi găsirea relaţiilor dintre acestea
se obţin informaţii care au un înţeles şi sunt integrate într-un context.
Datele, organizate şi prezentate într-un mod sistematic pentru a
sublinia sensul acestora, devin informaţii. Pe scurt, informaţiile sunt
date prelucrate. Informaţiile se prezintă sub formă de rapoarte,
statistici, diagrame, etc.
• Cunoştinţe – colecţii de date, informaţii, adevăruri şi principii învăţate,
acumulate de-a lungul timpului. Informaţiile despre un subiect, reţinute
şi înţelese, ce pot fi folosite în luarea de decizii, care pot forma judecăţi
şi opinii, devin cunoştinţe. Cu alte cuvinte, cunoştinţele apar în
momentul utilizării informaţiei.

1.1.2. Colectarea şi analizarea datelor. Modelul conceptual

Primul pas în realizarea unei aplicaţii de baze de date este analiza datelor şi
realizarea unei scheme conceptuale (model conceptual) ale acestora.
În această etapă sunt analizate natura şi modul de utilizare a datelor. Sunt
identificate datele care vor trebui memorate şi procesate, se împart în grupuri
logice şi se identifică relaţiile care există între aceste grupuri.
Analiza datelor este un proces uneori dificil, care necesită mult timp, însă
este o etapă obligatorie. Fără o analiză atentă a datelor şi a modului de utilizare a
acestora, vom realiza o bază de date care, putem constata în final, că nu
întruneşte cerinţele beneficiarului. Ideea de bază a analizei datelor şi a construirii
modelului conceptual este "să măsori de două ori şi să tai o singură dată".
Informaţiile necesare realizării modelului conceptual se obţin folosind
metode convenţionale precum intervievarea oamenilor din cadrul organizaţiei şi
studierea documentelor folosite.
Capitolul 1. Proiectarea bazelor de date 9

Odată obţinute aceste informaţii, ele trebuie reprezentate într-o formă


convenţională care să poată fi uşor înţeleasă de toată lumea. O astfel de
reprezentare este diagrama entităţi-relaţii, numită şi harta relaţiilor sau ERD-ul
(Entity Relationship Diagram). Aceste scheme sunt un instrument util care uşurează
comunicarea între specialiştii care proiectează bazele de date şi programatori, pe de
o parte şi beneficiari, pe de altă parte. Aceştia din urmă pot înţelege cu uşurinţă o
astfel de schemă, chiar dacă nu sunt cunoscători în domeniul IT.
În cele ce urmează, vom prezenta principalele elemente care intră în
componenţa unui ERD precum şi convenţiile de reprezentare a acestora.

1.1.3. Entităţi. Instanţe. Atribute. Identificator unic

O entitate este un lucru, obiect, persoană sau eveniment care are


semnificaţie pentru afacerea modelată, despre care trebuie să colectăm şi să
memorăm date. O entitate poate fi un lucru real, tangibil precum o clădire, o
persoană, poate fi o activitate precum o programare sau o operaţie sau poate fi o
noţiune abstractă.
O entitate este reprezentată în ERD printr-un dreptunghi cu colţurile
rotunjite. Numele entităţii este întotdeauna un substantiv la singular şi se scrie în
partea de sus a dreptunghiului cu majuscule, ca în Fig. 1.1:

PROFESOR PACIENT ELEV

Figura 1.1. Exemple de entităţi şi modul de reprezentare

O entitate este de fapt o clasă de obiecte şi pentru orice entitate există mai
multe instanţe ale sale. O instanţă a unei entităţi este un obiect, o persoană, un
eveniment particular din clasa de obiecte care formează entitatea. De exemplu,
elevul X din clasa a IX-a A de la Liceul de Informatică din localitatea Y este o
instanţă a entităţii ELEV.

După cum se vede, pentru a preciza o instanţă a unei entităţi, trebuie să


specificăm unele caracteristici ale acestui obiect, să-l descriem (să precizăm de
exemplu numele, clasa, şcoala, etc.). Aşadar, după ce am identificat entităţile
trebuie să descriem aceste entităţi în termeni reali, adică să le stabilim atributele.
Un atribut este orice detaliu care serveşte la identificarea, clasificarea,
cuantificarea, sau exprimarea stării unei instanţe a unei entităţi. Atributele sunt
informaţii specifice ce trebuie cunoscute şi memorate.
De exemplu, atributele entităţii ELEV sunt numele, prenumele, adresa,
numărul de telefon, adresa de e-mail, data naşterii, etc.
10 Manual de Informatică pentru clasa a XII-a

În cadrul unui ERD, atributele se vor scrie imediat


sub numele entităţii, cu litere mici. Un atribut este un ELEV
substantiv la singular (vezi Fig. 1.2). # cnp
* nume
* prenume
* data_nasterii
* adresa
○ telefon
Figura 1.2. Exemplu ○ e-mail
de entitate

Un atribut poate fi obligatoriu sau opţional. Dacă un atribut este


obligatoriu, pentru fiecare instanţă a entităţii respective trebuie să avem o valoare
pentru acel atribut: de exemplu, este obligatoriu să cunoaştem numele elevilor.
Pentru un atribut opţional putem avea instanţe pentru care nu cunoaştem valoarea
atributului respectiv. De exemplu, atributul ”e-mail” al entităţii ELEV este opţional,
un elev putând să nu aibă adresă de email. Un atribut obligatoriu este precedat în
ERD de un asterisc ”*”, iar un atribut opţional va fi precedat de un cerculeţ ”o”.

Atributele care definesc în mod unic instanţele unei entităţi se numesc


identificatori unici (UID). UID-ul unei entităţi poate fi compus dintr-un singur atribut,
precum codul numeric personal ce poate fi un identificator unic pentru entitatea ELEV.
În alte situaţii, identificatorul unic este compus dintr-o combinaţie de două sau mai
multe atribute. De exemplu, combinaţia dintre titlu, numele autorului şi data apariţiei
poate forma unicul identificator al entităţii CARTE. Oare combinaţia titlu şi nume autor
nu era suficientă? Răspunsul este NU, deoarece pot exista mai multe volume scrise de
Mihai Eminescu având toate titlul ”Poezii”, dar apărute la date diferite.
Atributele care fac parte din identificatorul unic al
unei entităţi vor fi precedate de semnul diez ”#” (vezi CARTE
Fig. 1.2 şi Fig. 1.3).
# titlu
# autor
# data_aparitiei
* format
* numar_pagini
Figura 1.3. Alt exemplu
de entitate

Observaţie ! Atributele din UID sunt întotdeauna obligatorii, însă semnul ”#” este
suficient, nu mai trebuie pus şi un semn asterisc în faţa acestor atribute.
Valorile unor atribute se pot modifica foarte des, ca de exemplu atributul
vârstă. Spunem, în acest caz, că avem de a face cu un atribut volatil. Dacă
valoarea unui atribut însă se modifică foarte rar sau deloc (de exemplu data
naşterii) acesta este un atribut non-volatil. Evident este de preferat să folosim
atribute non-volatile atunci când acest lucru este posibil.
Capitolul 1. Proiectarea bazelor de date 11

Identificaţi entităţile pentru următoarele scenarii. Identificaţi apoi pentru


fiecare entitate atributele sale, stabiliţi opţionalitatea acestora şi precizaţi unicul
identificator al fiecărei entităţi.
Indicaţie. Subliniaţi substantivele care au semnificaţie pentru afacerea descrisă.
Un substantiv va fi subliniat doar la prima sa apariţie. Dintre aceste substantive veţi
alege apoi entităţile.
1. Pentru a se abona la diverse reviste, persoanele doritoare trebuie să
furnizeze numele, adresa şi un număr de telefon. Fiecare revistă este identificată
prin titlu, numărul volumului şi data apariţiei. Abonaţii semnează pentru abonare un
contract pe o anumită perioadă de timp specificată prin data de început a
abonamentului şi data finală. Bineînţeles că o persoană se poate abona la mai
multe reviste în acelaşi timp.
2. Despre angajaţii unei firme se cunoaşte numele, titlul, numărul de telefon
de la birou. Angajaţii pot fi implicaţi într-o serie de proiecte ce se desfăşoară în
cadrul firmei. Despre fiecare proiect se cunoaşte numele, data la care a demarat
proiectul şi se poate cunoaşte o dată la care se va finaliza proiectul. La fiecare
proiect lucrează un singur angajat, însă un angajat poate fi implicat în mai multe
proiecte. Fiecare angajat are un manager, cu excepţia directorului. Managerii pot fi
şi ei implicaţi în proiecte.

1.1.4. Relaţii între entităţi

În lumea reală, obiectele nu există izolat. Percepem obiectele din lumea


reală doar în conexiune cu alte obiecte, de exemplu vom spune 'pământul se
învârte în jurul soarelui', 'el este medic', etc.
Aşadar, după ce aţi identificat care sunt entităţile şi atributele acestor entităţi,
este timpul să punem în evidenţă relaţiile care există între aceste entităţi, modul în
care acestea comunică între ele. O relaţie este o asociere, legătură sau conexiune
existentă între entităţi şi care are o semnificaţie pentru afacerea modelată.
Orice relaţie este bidirecţională, legând două entităţi sau o entitate cu ea însăşi.
De exemplu, elevii studiază mai multe materii, o materie e studiată de către elevi.
Orice relaţie este caracterizată de următoarele elemente:
- numele relaţiei;
- opţionalitatea relaţiei;
- gradul (cardinalitatea) relaţiei.
12 Manual de Informatică pentru clasa a XII-a

Să luăm ca exemplu relaţia existentă între entităţile JUCĂTOR şi ECHIPĂ.


Vom spune:
Un JUCĂTOR joacă într-o ECHIPĂ.
Numele relaţiei este: joacă.
Pentru a stabili opţionalitatea relaţiei trebuie să răspundem la următoarele
întrebări: un jucător trebuie să joace într-o echipă? Se poate ca un jucător să nu
joace în nicio echipă?
Dacă acceptăm faptul că toţi jucătorii trebuie să joace într-o echipă, relaţia
este obligatorie sau mandatorie şi vom spune că:
Un JUCĂTOR trebuie să joace într-o ECHIPĂ.

Dacă însă acceptăm că există jucători care nu joacă în nicio echipă (de
exemplu, li s-a terminat contractul şi în momentul de faţă nu mai joacă la nicio
echipă), atunci relaţia este opţională. În acest caz, vom spune că:
Un JUCĂTOR poate juca la o ECHIPĂ.

Cardinalitatea relaţiei este dată de numărul de instanţe ale entităţii din


partea dreaptă a relaţiei care pot intra în relaţie cu o instanţă a entităţii din partea
stângă a relaţiei. Adică va trebui să răspundem la întrebări de genul: la câte echipe
poate juca un jucător? Răspunsurile posibile sunt unul şi numai unul sau unul
sau mai mulţi. Vom spune:
Un JUCĂTOR trebuie/poate să joace la o ECHIPĂ şi numai una.
sau
Un JUCĂTOR trebuie/poate să joace la una sau mai multe ECHIPE.

Cea mai realistă variantă a relaţiei dintre JUCĂTOR şi ECHIPĂ este aşadar:

Un JUCĂTOR poate să joace la o ECHIPĂ şi numai una.

Am precizat însă mai înainte că orice relaţie este bidirecţională. Relaţia


dintre ECHIPĂ şi JUCĂTOR o putem enunţa astfel:

La o ECHIPĂ trebuie să joace unul sau mai mulţi JUCĂTORI.

1.1.4.1. Convenţii de reprezentare a relaţiilor

În cadrul diagramei entităţi-relaţii, o relaţie va fi reprezentată printr-o linie ce


uneşte cele două entităţi. Deoarece o relaţie este bidirecţională, linia ce uneşte cele
două entităţi este compusă din două segmente distincte, câte unul pentru fiecare
entitate. Tipul segmentului ce pleacă de la o entitate ne va indica opţionalitatea
relaţiei dintre această entitate şi entitatea aflată în cealaltă parte a relaţiei. Dacă
acest segment este continuu este vorba de o relaţie obligatorie, o linie întreruptă
indică o relaţie opţională.
Capitolul 1. Proiectarea bazelor de date 13

De exemplu, în Fig. 1.4 segmentul ce pleacă de la entitatea JUCĂTOR, fiind


întrerupt, înseamnă că un jucător poate juca la o echipă, adică relaţia este
opţională. Segmentul ce pleacă dinspre entitatea ECHIPĂ este continuu, deci la o
echipă trebuie să joace jucători.

Figura 1.4. Reprezentarea relaţiilor

Modul în care o linie se termină spre o entitate este important. Dacă se


termină printr-o linie simplă, înseamnă că o instanţă şi numai una a acestei entităţi
este în relaţie cu o instanţă a celeilalte entităţi. În exemplul anterior, linia de la
JUCATOR la ECHIPA se termină în partea dinspre ECHIPA cu o linie simplă, deci
un jucător joacă la o echipă şi numai una.
Dacă linia se termină cu trei linii (picior de cioară), înseamnă că mai multe
instanţe ale entităţii pot corespunde unei instanţe a celeilalte entităţi. În exemplul
anterior, linia de la ECHIPĂ la JUCĂTOR se termină cu piciorul de cioară,
înseamnă că unei instanţe a entităţii ECHIPĂ îi corespund mai multe instanţe ale
entităţii JUCĂTOR, adică o echipă are unul sau mai mulţi jucători.

Caracteristica relaţiei Valoare Mod de reprezentare


Numele relaţiei un verb se scrie deasupra relaţiei
relaţie obligatorie linie continuă
(TREBUIE)
Opţionalitatea
relaţie opţională linie întreruptă
(POATE)
linie simplă
una şi numai una
Cardinalitatea picior de cioară
una sau mai multe

Tabelul 1.1. Moduri de reprezentare a unei relaţii

1.1.4.2. Tipuri de relaţii

Variantele de relaţii ce pot exista între două entităţi sunt prezentate mai jos:
- relaţii one-to-one – acest tip de relaţie este destul de rar întâlnit –
uneori, astfel de relaţii pot fi modelate transformând una dintre entităţi
în atribut al celeilalte entităţi.
- relaţii one-to-many – sunt cele mai întâlnite tipuri de relaţii, însă şi aici,
cazurile c) şi d) prezentate în Fig. 1.6, sunt mai puţin uzuale;
14 Manual de Informatică pentru clasa a XII-a

Figura 1.5. Exemple de relaţii one-to-one

Figura 1.6. Exemple de relaţii one-to-many

- relaţii many-to-many – aceste tipuri de relaţii apar în prima fază a


proiectării bazei de date, însă ele trebuie să fie ulterior eliminate. Fig. 1.7
prezintă câteva exemple de astfel de relaţii.

Figura 1.7. Exemple de relaţii many-to-many


Capitolul 1. Proiectarea bazelor de date 15

1.1.5. Rezolvarea relaţiilor many-to-many

După cum am precizat anterior, relaţiile many-to-many pot apărea într-o


primă fază a proiectării bazei de date, însă ele nu au voie să apară în schema finală.
Să considerăm relaţia dintre entităţile STUDENT şi CURS (vezi Fig. 1.8). Se
ştie că orice curs se termină în general cu un examen. Unde vom memora nota
studentului la fiecare examen?

Figura 1.8. Exemplu de relaţie many-to-many

Dacă încercăm să introducem atributul nota la entitatea STUDENT, nu vom


şti cărei materii îi corespunde acea notă, întrucât unei instanţe a entităţii STUDENT
îi corespund mai multe instanţe ale entităţii CURS. Invers, dacă încercăm să
memorăm nota în cadrul entităţii CURS, nu vom şti cărui student îi aparţine acea
notă.
Rezolvarea unei relaţii many-to-many constă introducerea unei noi entităţi
numită entitate de intersecţie, pe care o legăm de entităţile originale prin câte o
relaţie one-to-many.
Paşii în rezolvarea unei relaţii many-to-many sunt următorii:
 se găseşte entitatea de intersecţie - pentru exemplul nostru, vom introduce
entitatea INSCRIERE:

Figura 1.9. Rezolvarea relaţiilor many-to-many, pasul 1


16 Manual de Informatică pentru clasa a XII-a

 crearea noilor relaţii:


o opţionalitatea: relaţiile care pleacă din entitatea de intersecţie sunt
întotdeauna obligatorii în această parte. În partea dinspre entităţile
originale, relaţiile vor păstra opţionalitatea relaţiilor iniţiale.
o cardinalitatea: ambele relaţii sunt de tip one-to-many, iar partea cu
many va fi întotdeauna înspre entitatea de intersecţie.
o numele noilor relaţii:

Figura 1.10. Rezolvarea relaţiilor many-to-many, pasul 2

 adăugarea de atribute în cadrul entităţii de intersecţie, dacă acestea există.


În exemplul nostru ne poate interesa, să spunem, data la care s-a înscris un
student la un curs, data la care a finalizat cursul, precum şi nota obţinută la
sfârşitul cursului.

Figura 1.11. Rezolvarea relaţiilor many-to-many, pasul 3


Capitolul 1. Proiectarea bazelor de date 17

 stabilirea identificatorului unic pentru entitatea de intersecţie: dacă entitatea


de intersecţie nu are un identificator unic propriu, atunci acesta se poate
forma din identificatorii unici ai entităţilor iniţiale, la care putem adăuga
atribute ale entităţii de intersecţie.
În exemplul nostru, identificatorul unic al entităţii de intersecţie este format
din id-ul studentului, id-ul cursului şi data înscrierii la curs.
Faptul că identificatorul unic al unei entităţi preia identificatorul unic din altă
entitate cu care este legată este reprezentat grafic prin bararea relaţiei
respective, înspre entitatea care preia UID-ul celeilalte entităţi:

Figura 1.12. Rezolvarea relaţiilor many-to-many, pasul 4

1. O bază de date va memora orarul unei universităţi. Fiecare curs este parte a
unui modul, iar fiecărui curs îi este asociat exact un profesor. La fiecare curs
participă mai mulţi studenţi.
Fiecare poziţie din orar corespunde unei zile a săptămânii şi unei anumite
ore. Fiecare poziţie din orar durează exact o oră, dar uneori un curs poate dura mai
multe ore consecutive, însă nici un curs nu poate apărea în zile diferite sau la ore
diferite neconsecutive ale aceleiaşi zile.
Fiecare profesor şi fiecare student pot avea mai multe ore de curs la care
participă în decursul unei săptămâni.
18 Manual de Informatică pentru clasa a XII-a

Care dintre următoarele variante NU este o soluţie posibilă a acestei probleme ?


a) Se stabileşte o relaţie one-to-many între CURS şi POZITIE_ORAR;
b) Se stabileşte o relaţie many-to-many între CURS şi POZITIE_ORAR;
c) Pentru fiecare curs vom avea un atribut start care reţine ora de începere
a cursului şi un atribut durată care memorează numărul de poziţii
consecutive din orar "ocupate" de acel curs;
d) Pentru fiecare curs vom avea două atribute primul şi ultimul care
memorează prima şi respectiv ultima poziţie din orar ocupată de acel
curs.

2. Fie următoarea hartă a relaţiilor:

Figura 1.13. Relaţia propusă pentru problema 2

Cum se citeşte corect relaţia dintre CLIENT şi MAŞINA?


a) Fiecare CLIENT poate să închirieze o MAŞINĂ şi numai una.
b) Fiecare CLIENT trebuie să închirieze o MAŞINĂ şi numai una.
c) Fiecare CLIENT poate să închirieze una sau mai multe MAŞINI.
d) Fiecare CLIENT trebuie să închirieze una sau mai multe MAŞINI.

3. Numele unei entitǎţi este de obicei:


a) un verb; b) un substantiv ; c) un adverb; d) orice cuvânt.

4. Care dintre următoarele variante NU poate reprezenta un atribut al entităţii


PANTOF?
a) culoare; b) mărime; c) model; d) clasa.

5. Care dintre următoarele fraze pot fi citite din schema de mai jos?

Figura 1.14. Relaţia propusă pentru problema 5


Capitolul 1. Proiectarea bazelor de date 19

a) Un student poate să urmeze mai multe cursuri.


b) Un curs poate fi urmat de mai mulţi studenţi.
c) Un student trebuie să urmeze un singur curs.
d) Un curs trebuie să fie urmat de un student.

6. Ce semnificaţie are piciorul de cioară ( ) în cadrul unui ERD?


a) relaţia este obligatorie;
b) relaţia este opţională;
c) pot exista una sau mai multe instanţe ale entităţii lângă care apare
semnul în relaţie cu o instanţă a celeilalte entităţi;
d) niciuna din variantele anterioare.

1. Completaţi în tabelul următor, în prima coloană, câte un exemplu de entitate a


cărui atribut este specificat în coloana a doua:

Entitate Atribut
culoare
nr_calorii
volum

Tabelul 1.2.

2. Citiţi, în ambele sensuri, următoarele relaţii. Din ce atribute este compus UID-ul
fiecărei entităţi?

Figura 1.15. Relaţiile propuse pentru problema 2


20 Manual de Informatică pentru clasa a XII-a

3. Rezolvaţi următoarele relaţii many-to-many:

Figura 1.16. Relaţiile propuse pentru problema 3

4. Daţi două exemple de relaţii one-to-many.

(vezi baremele de notare şi de corectare de la pag. 380)

1. Reluaţi aplicaţiile de la pagina 11 şi stabiliţi relaţiile dintre entităţile de la fiecare


exerciţiu. Rezolvaţi apoi eventualele relaţii many-to-many. Verificaţi să nu existe
relaţii redundante în schemele obţinute.

Pentru scenariile de la punctele 2-5, determinaţi entităţile, atributele acestora şi


relaţiile dintre entităţi. Desenaţi harta relaţiilor pentru fiecare exerciţiu în parte.

2. O firmă produce mai multe tipuri de maşini, un model fiind caracterizat printr-un
nume, mărimea motorului şi un sufix care indică gradul de lux al acesteia (de
exemplu XL, GL). Fiecare model este construit din mai multe părţi, fiecare parte
putând fi folosită pentru construirea mai multor modele de maşini. Fiecare parte are
o descriere şi un cod. Fiecare model de maşină este produs de exact o fabrică a
firmei, fabrică ce se poate găsi în una din ţările UE.

O fabrică poate produce mai multe modele de maşini şi mai multe tipuri de părţi
componente. De asemenea, fiecare tip de parte componentă poate fi produsă de o
singură fabrică a firmei.
Capitolul 1. Proiectarea bazelor de date 21

3. O universitate are în componenţa sa mai multe facultăţi, fiecare facultate având


mai multe departamente. Fiecare departament oferă studenţilor mai multe cursuri.
Un profesor poate lucra la un singur departament al unei singure facultăţi. Fiecare
curs are mai multe secţiuni, iar o secţiune poate să facă parte din mai multe
cursuri. Un profesor poate preda mai multe secţiuni, din acelaşi curs sau din
cursuri diferite, dar o secţiune poate fi predată de mai mulţi profesori.

4. La o facultate este nevoie să se memoreze date despre studenţi, cursuri şi


secţiunile fiecărui curs. Fiecare student are un nume, un număr de identificare,
adresa de acasă, adresa temporară, pentru cei care nu fac facultatea în localitatea
lor. Un student poate opta să urmeze un curs întreg sau doar anumite secţiuni ale
unui curs. De asemenea, el poate urma mai multe cursuri şi/sau secţiuni de curs
simultan. Un curs poate avea mai multe secţiuni, dar o secţiune poate fi parte a
mai multor cursuri.

5. Angajaţii unei firme sunt redistribuiţi la diferitele departamente din cadrul firmei.
Dorim ca în baza de date să memorăm, pentru fiecare angajat, departamentul la
care lucrează acum, dar şi departamentul la care a lucrat prima dată, la angajarea
în firmă.
22 Manual de Informatică pentru clasa a XII-a

1.2. Normalizarea datelor

1.2.1. Ce este normalizarea?

Normalizarea este o tehnică de proiectare a bazelor de date prin care se


elimină (sau se evită) anumite anomalii şi inconsistenţe ale datelor. O bază de date
bine proiectată nu permite ca datele să fie redundante, adică aceeaşi informaţie să
se găsească în locuri diferite sau să se memoreze în baza de date informaţii
care se pot deduce pe baza altor informaţii memorate în baza de date. Anomaliile
care pot să apară la o bază de date nenormalizată sunt următoarele:
- anomalii la actualizarea datelor – închipuiţi-vă că la secretariatul şcolii
voastre sunt memorate într-o tabelă informaţiile despre toţi elevii şcolii:
nume, adresă, telefon, etc. De asemenea, la biblioteca şcolii există fişele
voastre tot într-o tabelă. Aceste fişe conţin numele, prenumele, adresa,
telefonul, data înscrierii la bibliotecă, etc. Acum câteva zile v-aţi schimbat
domiciliul. Noua adresă trebuie modificată atât la secretariat cât şi în fişa
de la bibliotecă şi în toate locurile în care această informaţie apare. Dacă
modificarea nu se produce în unul dintre aceste locuri (fie că aţi uitat să
anunţaţi, fie din alte motive), datele devin inconsistente.
Alt scenariu: la o bibliotecă se înregistrează într-o tabelă următoarele
date despre cărţi: ISBN, titlu, autor, preţ, subiect, editură şi adresa
editurii. La un moment dat, o editură îşi schimbă adresa. Bibliotecara va
trebui să modifice adresa editurii respective în înregistrările corespun-
zătoare tuturor cărţilor din bibliotecă apărute la respectiva editură. Dacă
această modificare nu se face cu succes, unele dintre înregistrări
rămânând cu vechea adresă, apare din nou o inconsistenţă a datelor.
- anomalii de inserare – în exemplul anterior, nu vom putea memora
adresa unei edituri, lucru inacceptabil dacă dorim să avem informaţii şi
despre edituri a căror cărţi nu le avem în bibliotecă, eventual de la care
dorim să facem comenzi.
- anomalii de ştergere – să presupunem că într-o tabelă memorăm
următoarele informaţii: codul studentului, codul cursului şi codul
profesorului. La un moment dat, niciun student nu mai doreşte să
participe la un anume curs. Ştergând toate înregistrările corespunzătoare
cursului, nu vom mai putea şti niciodată cine preda acel curs.
Conceptul de normalizare a bazelor de date a fost pentru prima dată introdus de
către Edgar Frank Codd . Formele normale oferă indicaţii pe baza cărora puteţi decide
1

dacă un anumit ERD este bine proiectat, neexpus anomaliilor şi inconsistenţelor. În


principiu, normalizarea implică descompunerea unei entităţi în două sau mai multe
entităţi, prin compunerea cărora se pot obţine exact aceleaşi informaţii.

1
http://www.acm.org/classics/nov95/toc.html
Capitolul 1. Proiectarea bazelor de date 23

Formele normale se aplică fiecărei entităţi în parte. O bază de date (sau un


ERD) se găseşte într-o anumită formă normală doar dacă toate entităţile se găsesc
în acea formă normală.
Edgar Codd a definit primele trei forme normale 1NF, 2NF şi 3NF. Ulterior,
s-au mai definit formele normale 4NF, 5NF şi 6NF care însă sunt rar folosite în
proiectarea bazelor de date.

1.2.2. Prima formă normală (1NF)

O entitate se găseşte în prima formă normală dacă şi numai dacă:


- nu există atribute cu valori multiple;
- nu există atribute sau grupuri de atribute care se repetă.

Cu alte cuvinte, toate atributele trebuie să fie atomice, adică să conţină o


singură informaţie.
Dacă un atribut are valori multiple, sau un grup de atribute se repetă, atunci
trebuie să creaţi o entitate suplimentară pe care să o legaţi de entitatea originală
printr-o relaţie de 1:m. În noua entitate vor fi introduse atributele sau grupurile de
atribute care se repetă.
Să considerăm entitatea din Fig. 1.17, referitoare la notele elevilor unei
clase. Câteva observaţii referitoare la această entitate: câte discipline studiazǎ un
elev? Câte perechi (disciplina, nota) va trebui să aibă entitatea ELEV? Să spunem
că ştim exact numărul maxim de discipline pe care le poate studia un elev. Ce se
întâmplă dacă în anul şcolar viitor acest număr de discipline va fi mai mare? În
plus, la o materie un elev poate avea mai multe note. Câte note? Cum memorăm
aceste note? Le punem în câmpul corespunzător disciplinei cu virgulă între ele?
Cum rezolvăm această problemă? Vom crea o nouă entitate în care vom
introduce disciplina şi nota la disciplina respectivă (vezi Fig. 1.18).
În acest fel, fiecărui elev îi pot corespunde oricâte note, iar la o disciplină
poate avea oricâte note, singura restricţie conform acestui model fiind că un elev
nu va putea primi în aceeaşi zi, la aceeaşi materie, mai multe note.
Să considerăm un alt exemplu. Pentru managementul unui proiect este
important să ştim pentru fiecare membru al echipei care sunt abilităţile de care dispune,
pentru a cunoaşte modul în care să atribuim sarcinile în cadrul grupului. Într-o primă
etapă, am proiectat o entitate ANGAJAT, care are un atribut abilităţi, ca în Fig. 1.19.

Însă se ştie că fiecare angajat are mai multe abilităţi pe care dorim să le
memorăm. Aşadar, atributul abilităţi nu respectă prima formă normală. În
consecinţă, vom crea o nouă entitate ABILITATE în care vom memora toate
abilităţile fiecărui angajat (vezi Fig. 1.20).
24 Manual de Informatică pentru clasa a XII-a

Figura 1.17 Figura 1.18

Figura 1.19 Figura 1.20

1.2.3. A doua formă normală (2NF)

O entitate se găseşte în a doua formă normală dacă şi numai dacă se


găseşte în prima formă normală şi în plus, orice atribut care nu face parte din UID
(Unique IDentifier) va depinde de întregul UID, nu doar de o parte a acestuia.
De exemplu, dacă memorăm angajaţii unui departament într-o entitate ca mai jos:

Figura 1.21. Exemplu de entitate

Se observă că data_nasterii şi adresa sunt două atribute care depind


doar de id-ul angajatului, nu de întregul UID care este combinaţia dintre atributele
id_dep şi id_angajat. Această situaţie se rezolvă prin crearea unei noi entităţi
ANGAJAT, pe care o legăm de entitatea DEPARTAMENT printr-o relaţie 1:m.
Capitolul 1. Proiectarea bazelor de date 25

Figura 1.22. Relaţia între cele două entităţi

O situaţie mai specială este în cazul relaţiilor barate, când trebuie ţinut
seama că UID-ul unei entităţi este compus din atribute din entitatea respectivă,
plus un atribut sau mai multe provenite din relaţia barată. Să considerăm următorul
exemplu:

Figura 1.23. Exemplu de relaţie barată

Se observă că UID-ul entităţii APARTAMENT este compus din combinaţia a


trei atribute: numărul apartamentului, numărul blocului şi strada. Deci, toate
atributele din entitatea APARTAMENT care nu fac parte din UID, trebuie să depindă
de întregul UID. Dar se ştie că atributul cod_postal depinde doar de strada şi de
numărul blocului, nu şi de numărul apartamentului. Acest lucru ne spune că
atributul nu este memorat la locul potrivit. Deoarece depinde doar de combinaţia
(strada, nr_bloc), înseamnă că de fapt depinde de UID-ul entităţii bloc.
Aşadar, vom muta atributul cod_postal în entitatea BLOC.

Figura 1.24. Rezultatul modificării efectuate

Observaţie ! Dacă o entitate se găseşte în prima formă normală şi UID-ul său


este format dintr-un singur atribut, atunci ea se găseşte automat în a doua
formă normală.
26 Manual de Informatică pentru clasa a XII-a

1.2.4. A treia formă normală (3NF)

O entitate se găseşte în a treia formă normală dacă şi numai dacă se


găseşte în a doua formă normală şi în plus niciun atribut care nu este parte a
UID-ului nu depinde de un alt atribut non-UID. Cu alte cuvinte, nu se acceptă
dependenţe tranzitive, adică un atribut să depindă de UID în mod indirect.
Luăm ca exemplu entitatea CARTE din Fig. 1.25. Atributul biografie_autor nu
depinde de ISBN ci de atributul autor. Nerezolvarea acestei situaţii duce la
memorarea de date redundante, deoarece biografia unui autor va fi memorată
pentru fiecare carte scrisă de autorul respectiv.
Rezolvarea acestei situaţii constǎ în crearea unei noi entităţi, să-i zicem
AUTOR, pe care o legăm de entitatea CARTE printr-o relaţie 1:m (vezi Fig. 1.26).

Figura 1.26. Introducerea unei noi entităţi


Figura 1.25. Entitate
Iniţială

Atenţie! Acest model este corect doar dacă se acceptă că o carte are un singur autor.
Lăsăm ca temă rezolvarea situaţiei în care o carte poate avea mai mulţi autori. În
această situaţie, apare o relaţie many-to-many pe care trebuie să o rezolvaţi.

1. Care dintre următoarele enunţuri NU este un exemplu de redundanţă?


a) O relaţie între două entităţi care poate fi dedusă din altă relaţie.
b) O valoare dintr-o bază de date care poate fi obţinută direct pe baza altei valori.
c) Două atribute din baza de date care au aceeaşi valoare.
d) O valoare din baza de date care poate fi obţinută efectuând diferite
calcule asupra altor valori.
e) Niciuna dintre variantele anterioare.
Capitolul 1. Proiectarea bazelor de date 27

2. Care dintre următoarele cerinţe NU sunt necesare pentru ca o entitate să se


găsească în a treia formă normală?
a) Trebuie să se găsească în a doua formă normală.
b) Fiecare atribut care nu face parte din UID trebuie să depindă de întregul UID.
c) Nu trebuie să existe dependenţe tranzitive.
d) Niciuna dintre variantele anterioare.
3. Care este cea mai avansată formă normală în care
se găseşte entitatea alăturată?
a) 1NF; b) 2NF;
c) 3NF; d) ERD-ul nu este normalizat.

Figura 1.27.
Entitatea propusă

4. În ce formă normală se găseşte fiecare dintre următoarele entităţi?


a) b) c)

5. Un magazin vinde o gamă variată de pantofi de diferite mărimi şi modele. Un


model este identificat printr-un cod. Fiecare model are o descriere şi aceeaşi
descriere se poate aplica mai multor modele. Atributul vanzare_saptamanala
va memora numărul de pantofi de un anumit model şi o anumită mărime vânduţi
săptămâna anterioară (de exemplu, 25 de perechi, model 17, mărimea 39). Atributul
valoare_lunara_model reprezintă valoarea totală a pantofilor vânduţi pentru
fiecare model în parte, indiferent de model. Desenaţi un ERD în forma normală
3NF, conţinând toate aceste informaţii.
6. Se dă următoarea schemă a unei baze de date existente într-o videotecă.
Presupunând că videoteca dispune de un singur exemplar din fiecare film video,
stabiliţi în ce formă normală se găseşte acest ERD. Dacă el nu se găseşte în forma
normală 3NF, faceţi modificările necesare pentru aducerea sa la forma normală 3NF.

Figura 1.28.
Schema propusă
28 Manual de Informatică pentru clasa a XII-a

7. Plecând de la următoarea entitate, desenaţi un ERD în forma normală 3NF:

Figura 1.29. Entitatea propusă pentru problema 7

8. Desenaţi ERD-ul pentru următorul scenariu şi aduceţi-l în forma normală 3NF:


într-o clădire se găsesc mai multe birouri. Fiecare birou este identificat unic
printr-un număr. În fiecare birou se găseşte un singur telefon. Un telefon poate fi de
două tipuri: telefon interior (cu care nu se pot face apeluri în afara clădirii) şi telefon
exterior, cu care se pot face apeluri atât în interiorul clădirii cât şi cu exteriorul.
Fiecare telefon are un număr unic. Într-un birou pot lucra mai mulţi angajaţi, pentru
fiecare cunoscându-se numele, prenumele, adresa, e-mail-ul, data naşterii şi data
angajării. Se ştie că un angajat poate lucra într-un singur birou.
9. Modificaţi ERD-ul de la problema anterioară în ipoteza că într-un birou pot exista
mai multe telefoane, folosite în comun de către toţi angajaţii care lucrează în acel
birou.
10. Aduceţi modificările necesare entităţii alăturate astfel încât să obţineţi un ERD
în forma normală 3NF. Entitatea reţine informaţii despre angajaţii unei agenţii de
plasare a forţei de muncă, care oferă personal cu normă întreagă sau cu program
redus, pentru diferite hoteluri din întreaga ţară. Se
memorează numărul de ore lucrate de fiecare angajat
în diferite hoteluri. Se ştie că numărul de contract este
întotdeauna dependent de codul hotelului dar nu şi
invers.

Figura 1.30. Entitatea propusă


pentru problema 10
Capitolul 1. Proiectarea bazelor de date 29

1.3. Implementarea modelului conceptual

1.3.1. Modele de baze de date

Bazele de date au fost concepute pentru stocarea volumelor mari de informaţii


relativ omogene între care se pot stabili anumite relaţii. O bază de date este deci o
colecţie structurată de date aflate în interdependenţă, date care pot fi consultate
pentru a răspunde diferitelor interogări. Înregistrările returnate ca răspuns la o
interogare devin informaţii care pot fi utilizate în luarea unor decizii ulterioare.
Sistemul complex de programe care permite descrierea, organizarea,
memorarea, regăsirea, administrarea şi securizarea informaţiilor dintr-o bază de
date se numeşte sistemul de gestiune a bazelor de date (SGBD). Memorarea
datelor conţinute de bazele de date se face pe suporturile de memorie internă sau
externă folosite de calculatoare. SGBD este un software special asociat bazelor de
date care asigură interfaţa între o bază de date şi utilizatorii ei, rezolvând toate
cererile de acces la datele memorate.
Pentru orice bază de date poate fi compusă o descriere a datelor şi
obiectelor memorate, precum şi relaţiile existente între aceste obiecte. O astfel de
descriere se numeşte schema bazei de date.

Există mai multe modele de baze de date, acestea diferenţiindu-se în funcţie


de modul de organizare a schemei bazei de date.
Un model de bază de date nu este doar un mod de structurare a datelor, el
defineşte de asemenea un set de operaţii care pot fi realizate cu datele respective.
Cele mai cunoscute modele de baze de date sunt următoarele:

• Modelul tabelar – toate datele sunt memorate sub forma unui singur
tabel, un tablou bidimensional de date.

• Modelul ierarhic – datele sunt organizate sub forma unor structuri


arborescente, există deci o rădăcină cu mai mulţi dependenţi, care la rândul
lor pot avea alţi dependenţi. IMS (Information Management System) produs
de IBM este un exemplu de SGBD bazat pe acest tip de model.

• Modelul reţea este un model performant, dar complicat. O bază de date


de tip reţea reprezintă o colecţie de noduri şi legături, fiecare nod putând
fi legat de oricare altul. Legăturile trebuie stabilite având tot timpul în
minte interogările posibile şi acţiunile viitoare probabile.

• Modelul relaţional reprezintă cel mai utilizat model de stocare a datelor,


în care datele sunt organizate sub formă de tabele între care există
diverse legături.
30 Manual de Informatică pentru clasa a XII-a

• Modelul obiectual, destinat să suporte modele de obiecte complexe


(organizare de tip heap cu referinţe între componente) este oarecum
asemănător reţelei, iar prin faptul că pentru accesare directă, stochează
o hartă a ierarhiilor şi relaţiilor claselor de obiecte, are ascendent şi în
modelul ierarhic. Modelul obiectual se pretează pentru înmagazinarea
informaţiilor complexe: atribute descriptive asociate datelor multimedia,
documentelor, desenelor, arhivelor, etc.
• Modelele hibride sunt mixturi ale modelelor prezentate anterior, din care
cel mai semnificativ este modelul relaţional-obiectual, obţinut prin
extensii ale modelului de organizare tabelar şi izvorât din tendinţa spre
universalitate a bazei de date (entităţi complexe şi de naturi diferite,
evoluând în condiţii eterogene).

1.3.2. Baze de date relaţionale


Bazele de date relaţionale au fost dezvoltate având în vedere în primul rând
utilizatorii finali. Acest model are la bază teoria matematică a relaţiilor, ceea ce a
făcut posibilă tratarea algoritmică a proiectării bazelor de date şi problema
normalizării datelor.
Modelul relaţional este un model simplu, bazat pe algebra relaţională, care a
făcut posibilă dezvoltarea limbajelor relaţionale sub forma unui software specializat
ce asistă procesul de implementare a bazelor de date. Astfel de limbaje sunt
SQL-ul (Structured Query Language) şi QBE (Query By Example).
În momentul de faţă, există multe sisteme performante de gestiune a bazelor
de date relaţionale precum Oracle, DB2, MySQL, Informix, etc.
În cazul bazelor de date relaţionale mari şi foarte mari, s-au impus SGBD-uri
precum Oracle, DB2 şi Informix. Acestea au la bază tehnologia client-server.
Transformarea modelului conceptual, a ERD-ului, în modelul fizic, adică în
baza de date propriu-zisă, se numeşte mapare. Acest proces implică transformarea
fiecărui element al ERD-ului.
Prima etapă a acestui proces constă în crearea tabelelor bazei de date. Astfel:
 fiecărei entităţi îi va corespunde câte un tabel. Spre deosebire de
entitate, un tabel va avea numele un substantiv la plural. De exemplu,
entitatea ANGAJAT se va transforma în tabela ANGAJAŢI, entitatea
ELEV, în tabela ELEVI, etc.
 Fiecare atribut al unei entităţi va deveni o coloană a tabelei. Fiecare
coloană va memora date de acelaşi tip.
 Fiecare instanţă a unei entităţi se va transforma într-un rând (sau
înregistrare) al tabelului corespunzător.
 Unicul identificator al entităţii devine cheia primară a tabelei. Coloana
sau combinaţia de coloane care identifică în mod unic toate liniile unui
tabel se numeşte cheie primară.
Capitolul 1. Proiectarea bazelor de date 31

Deci, orice tabelă are linii şi coloane şi conţine datele organizate conform
anumitor structuri. În limbajul bazelor de date, coloanele se numesc câmpuri.
Fiecare coloană reprezintă un câmp cu o denumire unică, de un anumit tip (şir de
caractere, numeric, dată calendaristică, etc.), având o dimensiune prestabilită.
Rândurile tabelei se numesc înregistrări.
Vom vedea pe parcursul următorului paragraf cum mapăm relaţiile dintre
entităţi.

numele entităţii la plural  numele tabelei

atributul  coloana

instanţa  linia
Figura 1.31. Maparea entităţilor

Informaţiile despre o tabelă a bazei de date vor fi prezentate folosind


diagramele de tabelă care sunt nişte tabele de forma celui din Tabelul 1.3, în care
vom nota numele coloanelor pe care le va avea tabela bazei de date, notăm dacă
o coloană face parte din cheia primară, caz în care vom scrie un pk (primary key)
în coloana a treia, sau dacă face parte din cheia străină, caz în care vom scrie în
coloana a doua un fk (foreign key), iar în ultima coloană vom nota dacă atributul
este opţional sau obligatoriu. Pentru aceasta vom folosi aceleaşi simboluri ca şi în
cazul ERD-ului. Asupra cheilor străine vom reveni în paragraful următor.
În tabelul 1.3 vedeţi diagrama tabelei CĂRŢI corespunzǎtoare entitǎţii CARTE:

Numele coloanei Tip cheie Opţionalitatea

titlu Pk *

autor Pk *

data_apariţiei *

format *

nr_pagini *

Tabelul 1.3. Exemplu de diagramă de tabel

Se observă că deocamdată nu avem nicio cheie străină, deoarece cheia străină


provine din relaţiile în care entitatea este implicată. Cum deocamdată această
entitate nu are nici o relaţie cu nicio altă entitate, nu vom avea nicio cheie străină.
32 Manual de Informatică pentru clasa a XII-a

Completaţi diagramele de tabelă pentru entităţile de mai jos:

Figura 1.32. Entităţi propuse ca exerciţiu

1.3.3. Maparea relaţiilor

1.3.3.1. Maparea relaţiilor one-to-many

Să începem cu un exemplu. Vom considera ERD-ul din Fig. 1.33:

Figura 1.33. Exemplu de ERD

Să ne reamintim cum se citeşte relaţia dintre cele două entităţi:


Fiecare JUCĂTOR poate juca într-o ECHIPĂ şi numai una.

La fiecare ECHIPĂ trebuie sǎ joace unul sau mai mulţi JUCĂTORI.

Observăm că nu putem memora toţi jucătorii care joacă la o echipă în cadrul


tabelei ECHIPA, deoarece ar trebui să introducem o coloană cu valori multiple.
Invers însă, putem cu uşurinţă să memorăm, pentru fiecare jucător, echipa la care
joacă, deoarece acesta nu poate juca decât la o singură echipă.
Capitolul 1. Proiectarea bazelor de date 33

Oare cum putem memora echipa la care joacă un jucător? Răspunsul este
destul de simplu. Vom memora pentru fiecare jucător codul echipei la care joacă.
Adică diagrama de tabel corespunzătoare entităţii JUCĂTOR va fi următoarea:

Numele coloanei Tip cheie Opţionalitatea


Nr_legitimatie Pk *
Nume *
Prenume *
Data_nasterii *
Adresa *
Telefon o
Email o
cod_echipa Fk o

Tabelul 1.4. Diagrama de tabel corespunzătoare entităţii JUCĂTOR

De pe tabela anterioară puteţi deduce încă un element important al mapării


relaţiilor: dacă relaţia pe partea many este opţională atunci şi coloanele cheii străine
vor fi opţionale. Ce înseamnă acest lucru? Cum un jucător poate la un moment dat
să nu joace la nici o echipă, câmpul cod_echipă va rămâne necompletat în dreptul
lui (va avea valoarea NULL). Dacă însă relaţia este obligatorie pe partea many,
atunci coloanele ce fac parte din cheia străină vor fi obligatorii.
În general, la maparea unei relaţii de tip one-to-many vom introduce, în
tabela corespunzătoare entităţii de pe partea many a relaţiei, cheia primară a
entităţii de pe partea one a relaţiei. Câmpurile astfel introduse se vor numi chei
străine (în engleză, foreign key).
Aşadar:
- cheia străină a unei tabele este cheia primară din tabela referinţă;
- cheia străină este întotdeauna introdusă în tabela corespunzătoare
entităţii din partea many a relaţiei.

1.3.3.2. Maparea relaţiilor one-to-one

Dându-se două entităţi A şi B legate între ele printr-o relaţie one-to-one, este
evident că putem include cheia primară a lui A în cadrul tabelei B, dar putem
proceda la fel de bine şi invers, incluzând cheia primară a tabelei B în cadrul
tabelei A, deoarece fiecărei instanţe a entităţii A îi corespunde cel mult o instanţă a
entităţii B, dar şi invers, oricărei instanţe a entităţii B îi corespunde cel mult o
instanţă a entităţii A.

Pentru relaţia din Fig. 1.34, de exemplu, putem memora - pentru fiecare
persoană, seria de paşaport, dar şi invers - pentru fiecare paşaport, putem memora
cnp-ul deţinătorului.
34 Manual de Informatică pentru clasa a XII-a

Decizia depinde de specificul afacerii modelate. Dacă, de exemplu, ne


interesează în primul rând persoanele şi abia apoi datele de pe paşapoarte, atunci
vom adopta probabil prima variantă, a memorării seriei de paşaport în cadrul
tabelei PERSOANE, iar dacă însă baza de date este destinată evidenţei
paşapoartelor, atunci probabil vom adopta varianta a doua.

Figura 1.34. Exemplu de ERD

Uneori este convenabil să memorăm cheia străină în ambele părţi ale


relaţiei, în exemplul nostru, pentru fiecare paşaport să memorăm cnp-ul persoanei
care îl deţine, dar şi pentru fiecare persoană să memorăm seria de paşaport.

1.3.4. Maparea relaţiilor barate

Relaţiile barate se transformǎ în urma mapǎrii în cheie străină în tabela


aflată în partea many a relaţiei, la fel ca la maparea oricărei relaţii one-to-many.
Bara de pe relaţie exprimă faptul că acele coloane ce fac parte din cheia străină
vor deveni parte a cheii primare a tabelei din partea many a relaţiei barate.
Pentru exemplul din Fig. 1.35, cheia primară a tabelei ATRIBUTE va fi
formată din coloanele denumire_atribut şi denumire_entitate, aceasta din
urmă fiind de fapt cheie străină în tabela ATRIBUTE:

Figura 1.35. Maparea relaţiilor barate

Vom avea diagramele de tabel:

Numele coloanei Tip cheie Opţionalitatea


denumire Pk *
Tabelul 1.5. Diagrama de tabel ENTITĂŢI
Capitolul 1. Proiectarea bazelor de date 35

Numele coloanei Tip cheie Opţionalitatea


denumire_atribut Pk *
denumire_entitate Pk, Fk *
opţionalitate *
Tabelul 1.6. Diagrama de tabel ATRIBUTE

Să considerăm acum un exemplu în care există mai multe relaţii barate,


în cascadă:

Figura 1.36. Relaţii barate în cascadă

Vom avea tabelele de mai jos:

Numele coloanei Tip cheie Opţionalitatea


idA Pk *
C1 *
Tabelul 1.7. Diagrama de tabel pentru entitatea A

Numele coloanei Tip cheie Opţionalitatea


idB Pk *
C2 *
idA Pk, Fk *
Tabelul 1.8. Diagrama de tabel pentru entitatea B

Numele coloanei Tip cheie Opţionalitatea


idC Pk *
C3 *
idA Pk, Fk *
idB Pk, Fk *
Tabelul 1.9. Diagrama de tabel pentru entitatea C

Numele coloanei Tip cheie Opţionalitatea


idD Pk *
C4 *
idA Fk *
Tabelul 1.10. Diagrama de tabel pentru entitatea D
36 Manual de Informatică pentru clasa a XII-a

1. Reluaţi exerciţiile propuse pe parcursul paragrafelor anterioare şi realizaţi


maparea ERD-urilor obţinute.

2. Realizaţi maparea următoarei hărţi a relaţiilor.

Figura 1.37. Harta relaţiilor propusă ca aplicaţie

1.3.5. Operaţii specifice prelucrării bazelor de date

Orice sistem de gestiune a bazelor de date (SGBD) trebuie să asigure


următoarele funcţii:

• definirea structurii bazei de date;

• încărcarea datelor în baza de date (adăugarea de noi înregistrări la


baza de date);

• accesul la date pentru:


o interogare (afişarea datelor, sortarea lor, calcule statistice, etc.);
o ştergere;
o modificare;
Capitolul 1. Proiectarea bazelor de date 37

• întreţinerea bazei de date:


o refacerea bazei de date prin existenţa unor copii de siguranţă;
o repararea în caz de incident;
o colectarea şi refolosirea spaţiilor goale;

• posibilitatea de reorganizare a bazei de date prin:


o restructurarea datelor;
o modificarea accesului la date;
• securitatea datelor.

O parte din aceste operaţii pot fi realizate cu ajutorul limbajului SQL, altele
cu ajutorul unor programe specializate, care sunt puse la dispoziţia administra-
torului bazei de date de către sistemul de gestiune al bazelor de date.

1.3.6. Reguli de integritate

Detalierea caracteristicilor pe care trebuie să le prezinte un SGBD pentru a fi


considerat relaţional a fost realizată de către E. F. Codd în 1985 sub forma a 13
reguli. Una dintre aceste reguli precizează că restricţiile de integritate trebuie să
poată fi definite în limbajul utilizat de SGBD pentru definirea datelor.
Regulile de integritate garantează că datele introduse în baza de date sunt
corecte şi valide. Aceasta înseamnă că dacă există orice regulă sau restricţie
asupra unei entităţi, atunci datele introduse în baza de date respectă aceste
restricţii.
Tipurile de reguli de integritate sunt următoarele:
 Integritatea entităţilor – indică faptul că nici o coloană ce face parte
din cheia primară nu poate avea valoarea NULL. În plus, pentru fiecare
înregistrare, cheia primară trebuie să fie unică.
 Integritatea de domeniu – acest tip de reguli permite ca într-o
anumită coloană să se introducă doar valori dintr-un anumit domeniu.
De exemplu, putem impune ca salariul unui angajat să fie cuprins între
4500 şi 5000 RON.
 Integritatea referenţială – este o protecţie care asigură ca fiecare
valoare a cheii străine să corespundă unei valori a cheii primare din
tabela referită. De exemplu, referindu-ne la tabelele JUCĂTORI şi
ECHIPE, corespunzătoare ERD-ului din Fig. 1.33, cod este cheie
primară în tabela ECHIPE, iar în tabela JUCĂTORI, cod devine cheie
străină. Astfel, valoarea câmpului cod din cadrul tabelei JUCĂTORI
corespunzătoare unui anumit jucător trebuie să se regăsească printre
valorile câmpului cod din tabela ECHIPE, altfel ar însemna că jucătorul
respectiv joacă la o echipă inexistentă (vezi Fig. 1.38).
38 Manual de Informatică pentru clasa a XII-a

Figura 1.38. Exemplu de încălcare a integrităţii referenţiale

Situaţii de încălcare a integrităţii referenţiale pot apărea:


 la adăugarea unei noi înregistrări în baza de date, se poate încerca
introducerea unor valori invalide pentru câmpurile cheii străine;
 la actualizarea bazei de date;
 la ştergerea unei înregistrări. De exemplu, se şterge înregistrarea
corespunzătoare unei anumite echipe (echipa se desfiinţează).
Înregistrările jucătorilor care au jucat la acea echipă vor încălca
integritatea referenţială, deoarece se vor referi la o echipă care nu mai
există. Soluţiile posibile sunt ca la ştergerea unei echipe, toţi jucătorii
care au activat la acea echipă să fie şi ei şterşi din baza de date
(ştergere în cascadă), sau valoarea câmpului cod_echipă pentru
acei jucători să fie setată la NULL, ceea ce înseamnă că acei jucători
nu activează la nicio echipă.

1.3.7. Programe de validare şi de acţiune

În realizarea modelului conceptual al unei baze de date se ţine cont de


modul în care funcţionează afacerea modelată, datele care trebuie să fie memorate,
relaţiile dintre acestea, etc. Modul de utilizare a diferitelor date, modul în care
acestea sunt relaţionate pot diferi de la o afacere la alta.
Regulile afacerii unei organizaţii se referă în esenţă la procesele şi fluxurile
tuturor datelor şi activităţilor zilnice din cadrul organizaţiei.
Cum funcţionează organizaţia?
Care sunt activităţile sale?
Capitolul 1. Proiectarea bazelor de date 39

Regulile afacerii acoperă următoarele aspecte ale unei organizaţii:


 Orice tip de politici organizaţionale de orice tip şi de la orice nivel al
organizaţiei.
 Orice tip de formule de calcul (ca, de exemplu, modul de calcul al
ratelor pentru diverse împrumuturi, modul de calcul al salariilor, etc.).
 Orice tip de reguli impuse de lege sau reguli interne ale organizaţiei.
Regulile simple ale afacerii pot fi implementate în modelul bazei de date prin
intermediul relaţiilor dintre entităţi. Acest tip de reguli se numesc reguli structurale.
Alte reguli ale afacerii pot fi implementate folosind regulile de integritate despre
care am discutat în paragraful anterior. Există totuşi reguli pentru implementarea
cărora va trebui să scriem programe speciale folosind limbaje specializate specifice
SGBD-ului utilizat. Acest tip de reguli se numesc reguli procedurale.

1. Când mapaţi un ERD, care dintre următoarele afirmaţii NU este adevărată?


a) Fiecare entitate este mapată într-o tabelă.
b) Fiecare atribut este mapat într-o coloană a tabelei corespunzătoare.
c) Fiecare entitate în parte este mapată într-o linie din tabelul corespunzător.
d) Fiecare relaţie one-to-many se transformă într-o cheie străină.

2. Într-o tabelă, o instanţă a unei entităţi este mapată ca:


a) o relaţie many-to-many; b) o linie din tabel;
c) o coloană din tabel; d) un atribut; e) un index.

3. Două entităţi A şi B se găsesc într-o relaţie one-to-one care este opţională la


ambele capete. Care dintre următoarele variante este o soluţie corectă de mapare ?
a) Combinarea celor două entităţi A şi B într-o singură relaţie.
b) Crearea a două tabele separate şi includerea unei chei străine atât în
tabela A cât şi în tabela B.
c) Combinarea celor două entităţi A şi B într-o singură tabelă.
d) Utilizarea unei chei primare care să fie o combinaţie a cheilor primare din A şi B.

4. Referitor la ERD-ul din Fig. 1.39, care dintre afirmaţiile de mai jos corespund
unei variante corecte de mapare?
a) Se preia cheia primară din tabela PERSOANE şi se adaugă ca şi cheie
străină la tabela MASINI.
40 Manual de Informatică pentru clasa a XII-a

Figura 1.39. ERD propus pentru problema 4

b) Se preia cheia primară din tabela MASINI şi se adaugă ca şi cheie străină


la tabela PERSOANE.
c) Se creează o singură tabelă cu informaţiile din ambele entităţi.
d) Se preiau cheile primare din ambele tabele şi se introduc într-o nouă
tabelă numită PROPRIETARI.
e) Oricare dintre variantele de mai sus este corectă.

5. O bază de date conţine următoarele tabele:


Tabela DEPARTAMENTE Tabela ANGAJATI Tabela ANGAJARI
DepNo Departament IdAngajat NumeAngajat IdAngajat DepNo
1 IT 1 Ionescu 1 1
2 Electric 2 Georgescu 3 2
3 Geografie 3 Vasilescu 4 1
4 Istorie 4 Marinescu 3 3
5 Business 5 Andreescu 1 2
2 5
Desenaţi ERD-ul din care s-au obţinut prin mapare aceste tabele.

(vezi baremele de notare şi de corectare de la pag. 380)


Capitolul 1. Proiectarea bazelor de date 41

1.4. Managementul de proiect

1.4.1. Ce este un proiect ?

Un proiect este o secvenţă de acţiuni intercorelate, care se derulează într-o


perioadă de timp clar definită şi delimitată, orientate către îndeplinirea unor
obiective cu caracter unic şi precis.
Putem defini managementul de proiect ca fiind efortul planificării,
organizării şi mobilizării resurselor pentru un scop dat. Managementul de proiect
este de fapt un instrument, un set de metode şi tehnici care ne ajută să atingem cu
eficacitate scopurile şi obiectivele propuse.

1.4.2. Etape în realizarea unui proiect

Orice proiect trece printr-o serie întreagă de etape. Ceea ce este important
de reţinut este faptul că orice proiect este un proces iterativ, în sensul că orice
etapă poate fi repetată de mai multe ori, în funcţie de necesităţile de redefinire a
anumitor cerinţe.
Etapele principale pe care le parcurgem pentru realizarea unui proiect sunt
următoarele:
 Definirea proiectului
o Validarea proiectului – în această etapă vor fi analizate toate documentele
prezente în propunerea de proiect. Această analiză va duce fie la
confirmarea şi acceptarea proiectului, fie va duce la respingerea, sau
eventual regândirea acestuia, în cazul în care propunerea de proiect nu a
fost bine realizată, şi resursele au fost subestimate.
o Definirea proiectului – constă în enunţarea problemei, stabilirea scopului
proiectului, stabilirea unei liste a posibilelor soluţii etc. Orice proiect propus
poate avea elemente pe care cel care l-a propus nu a considerat necesar
să le detalieze, însă echipa de proiect poate avea nevoie de informaţii
suplimentare pentru a înţelege corect enunţul proiectului.
 Organizarea proiectului
o Stabilirea obiectivelor
o Stabilirea grupului ţintă - când încercaţi să stabiliţi care este grupul ţintă
al unui proiect trebuie să răspundeţi la următoarele întrebări: Cine trebuie
să ştie despre proiect? Cine va folosi acest proiect? Asupra cui vor avea
impact rezultatele proiectului? Cine finanţează acest proiect? Cine aprobă
acest proiect? Cine livrează proiectul? Cine va trebui să fie instruit?
42 Manual de Informatică pentru clasa a XII-a

o Stabilirea cerinţelor proiectului – este un proces iterativ care poate


implica negocierea. Fiind conducătorul proiectului, ştiţi ce este posibil şi ce
nu în ceea ce priveşte scopul proiectului, timpul alocat, costurile, cerinţele
de calitate etc. Un proiect care nu îndeplineşte cerinţele utilizatorului este
din start un eşec.
o Stabilirea infrastructurii proiectului – infrastructura se referă la
elemente precum instrumente de comunicare în cadrul echipei (telefoane
mobile, PDA, laptop, etc.), spaţiu de lucru pentru membrii echipei (birou),
echipamente de birou, laboratoare, etc.
o Stabilirea sistemului de calitate a proiectului
o Formarea echipei de proiect
 Planificarea proiectului – planul proiectului prezintă desfăşurarea normală,
ideală a unui proiect. Acesta oferă reperele necesare evaluării situaţiei
proiectului. Fără existenţa unui plan dinainte stabilit, exercitarea controlului
este practic imposibilă.
 Elaborarea proiectului – în această etapă se stabilesc detaliile tehnice şi de
design, se revizuiesc schemele tehnice, se revizuiesc criteriile de cost şi
performanţă. Această etapă vizează conturarea unui model al aplicaţiei. Se
proiectează bazele de date, se realizează interfeţele aplicaţiei (rapoarte,
ecrane, meniuri etc), se proiectează prelucrările automate, etc.
 Dezvoltarea proiectului
 Implementarea proiectului – constă în instalarea produsului şi testarea sa,
instruirea viitorilor utilizatori. Se testează produsul în condiţii reale, şi se
înlătură eventualele erori depistate în funcţionare. Tot în această fază
personalul implicat în proiect este redus. Se încep activităţile de publicitate.
 Finalizarea proiectului – se elaborează rapoartele finale, se eliberează
personalul angajat în derularea proiectului.

1.4.3. Principiile lucrului în echipă

Colaborarea înseamnă mai ales implicarea oamenilor în crearea propriilor


soluţii la problemele cu care se confruntă. În cadrul unui proces colaborativ,
oamenii au ocazia să afle punctul de vedere şi perspectiva celorlalţi şi să
gândească împreună soluţii la problemele comune.
Colaborarea este o artă ! Sunteţi uneori puşi în situaţia de a vorbi şi
colabora cu persoane pe care nu le cunoaşteţi, cu care nu sunteţi de acord sau pe
care nu le agreaţi.
Mărimea echipei de proiect este un factor important care poate influenţa
modul de conducere al acesteia. Într-o echipă prea mare pot apărea probleme de
comunicare, dificultăţi în luarea deciziilor. În general, se acceptă că o echipă pentru
a putea fi eficientă nu trebuie să depăşească un număr de 10 persoane.
Capitolul 1. Proiectarea bazelor de date 43

În cazul proiectelor cu număr mare de persoane implicate, participanţii la


proiect trebuie organizaţi în mai multe echipe satelit intercorelate, coordonate de o
echipă principală al cărei rol principal este să asigure o comunicare facilă şi
eficientă între toate echipele satelit.
Fiecare membru al unei echipe de proiect trebuie să cunoască ceea ce se
aşteaptă de la el. Trebuie stabilite de la început rezultatele aşteptate de la fiecare
membru al echipei în parte, acţiunile ce trebuie executate pentru obţinerea
rezultatului, relaţiile de subordonare în cadrul echipei, metodele de măsurare a
performanţei fiecărui membru al echipei.
Liderul echipei are în primul rând rolul de a stabili, menţine şi proteja un
proces colaborativ care permite tuturor să participe neîngrădit la munca grupului.

1.4.4. Pregătirea şi susţinerea unei prezentări

În momentul finalizării unui proiect va trebui să prezentaţi rezultatul muncii


voastre în faţa clientului. Susţinerea unei prezentări în public este pentru oricine o
sursă de stres. Mulţi oameni ar prefera să evite complet această problemă, dar de
multe ori este imposibil de evitat. Indiferent că lucrăm singuri sau în echipă, vom
putea fi puşi în situaţia de a face o prezentare publică.
Adevărul este că susţinerea unei prezentări publice nu trebuie să fie un
motiv de stres. Atât timp cât aveţi în minte câteva principii de bază, vorbitul în
public va deveni o experienţă plăcută pentru voi.
Iată câteva principii de care trebuie să ţineţi seama pentru a depăşi
dificultăţile legate de vorbitul în public:

• Vorbitul în public NU este un motiv real de stres.


Mulţi oameni erau la început îngroziţi de ideea de a vorbi în public. Le
tremurau genunchii, vocea, gândurile o luau razna. Totuşi, ei au învăţat
să elimine definitiv teama de a vorbi în public.
• Nu îţi propune să fi genial sau perfect, chiar dacă aşa ţi se pare că ar
trebui. Ţi se poate întâmpla să greşeşti, ţi se poate întâmpla să uiţi
porţiuni întregi din ceea ce vroiai să spui, poţi să nu glumeşti deloc şi
totuşi prezentarea ta să aibă succes.
Totul depinde de cum defineşti tu şi auditorul tău succesul. Auditorul tău
nu aşteaptă de la tine să fi perfect. Cu cât încerci mai tare să fi perfect cu
atât mai mult vei adânci anxietatea pe care o ai şi efectul va fi contrar
celui scontat. Ceea ce este important atunci când faci o prezentare în
faţa unui public este să oferi ceva auditorului. Atâta timp cât auditorul
rămâne cu ceva de pe urma prezentării, ei o vor considera un succes.
• Nu încerca să transmiţi prea multe informaţii într-o prezentare. Nu
trebuie să transmiţi “tone” de informaţii şi detalii, oferă publicului doar
ceea ce el doreşte cu adevărat. Studiile arată că oamenii îşi amintesc
doar foarte puţine elemente din ceea ce vorbitorii prezintă.
44 Manual de Informatică pentru clasa a XII-a

• Nu încerca să mulţumeşti pe toată lumea, acesta este un punct de


vedere nerealist.

• Nu încerca să imiţi alţi prezentatori, e un lucru foarte dificil. Încearcă să fi


tu însuţi, e mult mai uşor.

• Nu încerca să controlezi comportamentul auditorului. Dacă oamenii sunt


agitaţi, nu încerca să le controlezi comportamentul. Dacă cineva
vorbeşte cu vecinul, citeşte ziarul sau chiar a adormit în timpul
prezentării tale, ignoră-l!
• Nu te scuza. Auditorul nu are de unde să ştie că ai uitat să spui ceva.
Vorbeşte cu încredere, fi convins de ceea ce spui.
• Organizează logic conţinutul prezentării. Orice prezentare va avea o
introducere, conţinutul propriu-zis şi o concluzie.

• Utilizează materiale audio-vizuale ajutătoare, dacă acestea sunt


necesare. O prezentare în PowerPoint, bine realizată, poate fi de un real
folos.
o Asigură-te din timp că întregul echipament (calculator,
video-proiector, etc) funcţionează.
o Nu bombarda auditorul cu efecte sonore sau cu animaţii exagerate şi
utilizează în mod echilibrat culorile.
o Include în prezentarea electronică doar cele mai importante idei.
o Nu încărca slide-urile cu prea multe texte. În general, se admit 7-10
cuvinte pe linie şi maximum 10 linii de text pe un slide.
o Preferă un grafic în locul textelor, dar nu exagera cu mai mult de
două grafice pe un slide.

• Păstrează contactul vizual cu auditorul. Încearcă în acest fel să faci


fiecare persoană din public să se simtă implicată.

• Fă scurte pauze. Nu alerga prin prezentare, dă-ţi răgazul să respiri. Dă


timp audienţei să reflecte la ceea ce ai spus.

• Adaugă puţin umor prezentării tale, dacă acest lucru este posibil.
Păstrează treaz interesul auditorului pe parcursul întregii prezentări.

• Nu ţine mâinile în buzunar în timpul prezentării !

• Adoptă o ţinută adecvată în ziua prezentării. Atrage atenţia auditorului


asupra a ceea ce spui, nu a mesajelor de pe tricou sau asupra bijuteriilor
pe care le porţi !

În acest moment v-aţi însuşit elementele de bază ale modelării bazelor de


date. Aţi văzut diverse situaţii ce pot apărea pe parcursul creării modelului
conceptual şi cum să rezolvaţi anumite situaţii problemă.
Capitolul 1. Proiectarea bazelor de date 45

În acest subcapitol aţi aflat cum se organizează un proiect, care sunt etapele
de realizare ale lui şi cum să organizaţi munca într-o echipă. De asemenea, ştiţi
cum să pregătiţi şi să faceţi o prezentare în faţa unui public. Este momentul să
aplicaţi toate aceste cunoştinţe!

Formaţi echipe de 2 - 4 elevi, alegeţi-vă o temă de proiect, fie din temele


propuse în această secţiune, fie una propusă chiar de voi. Realizaţi modelul
conceptual al afacerii modelate. Atenţie! Repartizaţi sarcinile în mod echitabil în
cadrul echipei de proiect.
Pregătiţi o prezentare a proiectului realizat, materialele vizuale (postere,
pliante, prezentarea PowerPoint), care să vă ajute la susţinerea prezentării.
Puteţi chiar organiza împreună cu cadrul didactic, un concurs la nivelul
clasei sau al şcolii, la care să invitaţi şi alţi profesori din şcoală.
Nu uitaţi să documentaţi fiecare presupunere pe care aţi făcut-o în realizarea
proiectului!

Tema 1: „Campionatul Naţional de Fotbal”. O bază de date memorează informaţii


despre jucătorii şi cluburile din cele patru divizii din campionatul naţional de fotbal.
Fiecare club de fotbal are un nume unic în întregul campionat. Un club de fotbal
poate avea mai multe echipe în campionat. Pentru fiecare echipă se cunoaşte
căpitanul său, care este unul dintre jucători.
Jucătorii au asociat un identificator unic, un nume, nu neapărat unic şi sunt
angajaţi la diferitele echipe. În baza de date se păstrează şi detalii privind nivelul
abilităţilor (notă cuprinsă între 1 şi 10) fiecărui jucător pentru fiecare dintre poziţii de
joc (portar, apărător, mijlocaş, etc). De exemplu, jucătorul Ionescu poate avea
nivelul 10 pe postul de portar, 7 pentru poziţia de apărător, etc.
Este important ca în baza de date să se memoreze un istoric al tuturor
jucătorilor, la ce echipe au jucat, în ce perioadă, etc.
Se va memora şi un istoric al golurilor marcate de fiecare jucător de-a lungul
carierei. Pentru fiecare gol se va şti data, meciul în care a fost marcat, minutul, etc.

Tema 2: „Firmă de închirieri de maşini”. Trebuie să proiectaţi baza de date a


unei firme care oferă spre închiriere maşini de diferite tipuri. Trebuie să păstraţi
informaţii despre maşinile firmei, firmele cu care firma are contracte de colaborare
(de exemplu, garaje), maşinile închiriate, veniturile firmei şi bineînţeles date despre
clienţii firmei.
Maşinile sunt descrise prin date precum: producătorul, modelul, anul de
fabricaţie, mărimea motorului, tipul de combustibil, numărul de pasageri, numărul
de înmatriculare, preţul de cumpărare, data cumpărării, preţul de închiriere şi detalii
privind asigurarea maşinii.
46 Manual de Informatică pentru clasa a XII-a

Toate reparaţiile importante asupra maşinilor firmei sunt făcute de firme cu


care colaborează. Unele firme solicită plata serviciilor de service imediat după ce
reparaţia a fost făcută, altele acceptă plata în rate a serviciilor. Trebuie ţinută
evidenţa clară a fiecărei maşini, a celor închiriate, a celor aflate în reparaţii, etc.
Se păstrează de asemenea evidenţa tuturor veniturilor şi cheltuielilor firmei:
cumpărarea de noi maşini, închirierea de maşini, cheltuieli de reparaţii, vânzarea
unor maşini mai vechi din parcul auto (firma preferă să nu păstreze în parcul auto o
maşină mai mult de un an), taxe de asigurare a maşinilor etc.
Firma deţine un portofoliu de clienţi destul de stabil. Pentru clienţii privilegiaţi
oferă reduceri la închirierea de maşini. Aceşti clienţi au de asemenea posibilitatea
de a rezerva o maşină din timp. O maşină poate fi închiriată pentru o perioadă de
timp de la o zi la un an. Plata pentru închirierea unei maşini se poate face cash sau
cu credit card. Se acceptă orice tip de card.
Datele importante despre clienţi precum numele, adresa, numărul de telefon,
seria permisului de conducere, etc. vor fi şi ele memorate în baza de date.
Tema 3: „Firmă IT”. Trebuie să proiectaţi baza de date a unei companii de
dimensiune medie din domeniul IT. Firma livrează diferite produse clienţilor săi, de la
simple aplicaţii create la cerere, până la instalări de echipamente hardware şi
software particularizat. Firma are ca angajaţi diverşi experţi, consultanţi şi personal
auxiliar. Întregul personal este angajat pe termen nelimitat, nu există angajaţi
temporari sau colaboratori. Compania este împărţită în mai multe departamente,
fiecare departament fiind condus de către un angajat din cadrul departamentului
respectiv. Pentru un proiect care trebuie dezvoltat în cadrul firmei, se formează o
echipă de persoane selectate din mai multe departamente. Managerul de proiect
este pe deplin şi exclusiv responsabil de conducerea proiectului, independent de
ierarhia de conducere din cadrul firmei.
Tema 4: „Spital”. Un spital este format din mai multe secţii, precum Pediatrie,
Oncologie, Dermatologie etc. În fiecare secţie sunt internaţi mai mulţi pacienţi, pe
baza recomandării medicului de familie şi a confirmării făcute de către un specialist
al spitalului. La internare, sunt înregistrate datele personale ale pacienţilor. O fişă
separată ţine evidenţa investigaţiilor făcute pacientului pe toată perioada internării,
rezultatele acestor investigaţii, tratamentul aplicat pacientului şi rezultatele obţinute
în urma tratamentelor efectuate. Un pacient este repartizat unui anumit medic care
coordonează toate investigaţiile şi tratamentele aplicate pacientului, însă acesta
poate solicita şi altor colegi să examineze pacientul său. Medicii sunt specialişti în
diverse ramuri ale medicinii, şi pot avea în supraveghere mai mulţi pacienţi, nu
neapărat toţi din aceeaşi secţie.
Tema 5: „Editură”. O editură editează cărţi ştiinţifice din diferite domenii. Cărţile
sunt scrise de autori specializaţi într-un anumit domeniu. Firma are angajaţi mai
mulţi editori care nu sunt neapărat specialişti în diferitele domenii, fiecare editor
fiind responsabil pentru mai multe publicaţii. O carte acoperă unul din domeniile în
care este specialist autorul, fiecare autor lucrează cu un editor, dar poate avea
spre publicare o altă carte de care este responsabil un alt editor.
PARTEA A II-A CAPITOLUL
Limbajul MySQL

În acest capitol veţi învăţa MySQL, limbaj de programare specializat


pentru gestiunea bazelor de date relaţionale pe Internet. Cu ajutorul
programului EasyPHP, veţi putea lucra uşor pe calculatorul dvs.

 Ce este şi de ce învăţăm MySQL ?


 Cum rulăm MySQL pe propriul calculator ?
 Cum creăm o bază de date ?
 Tabele – noţiuni elementare
 Tipuri de date, operatori şi funcţii
 Afişarea c oloanelor care rezultă în urma unui calcul
 Valoarea NULL. Valori implicite
 Ce sunt cheile primare şi cheile unice ?
 Autoincrementare
 Cum sortăm şi cum filtrăm datele ?
 Cum actualizăm datele dintr-un tabel ?
 Funcţii agregate
 Utilizarea subinterogărilor
 Cum putem grupa datele ?
 Ce sunt uniunile de tabele ?

Cuvinte cheie: tipuri de date, operatori, funcţii, valoare implicită,


cheie primară, cheie unică, autoincrementare, sortare, filtrare,
actualizare, funcţii agregate, subinterogări, grupare, uniune
48 Manual de Informatică pentru clasa a XII-a

2.1. Ce este şi de ce învăţăm MySQL ?


În ultimii ani, utilizarea bazelor de date pe Internet a luat o amploare
deosebită. Există o mulţime de aplicaţii, extrem de utile (care le utilizează), cum ar fi:
- Aplicaţii de contorizare, aplicaţii prin care cei care au creat un site au
posibilitatea să-şi contorizeze numărul de vizitatori ai site-ului respectiv sau,
mai mult, contorizarea se poate extinde la nivel de pagină afişată. Pentru a
evita cu un vizitator, care a deschis de mai multe ori pagina respectivă, să
nu fie contorizat de mai multe ori, se va reţine adresa IP a acestuia.
- Comerţ electronic, aplicaţii prin care anumite firme îşi promovează şi vând
produsele de care dispun. În acest caz, bazele date vor reţine, pe de o
parte, informaţii despre produse, iar pe de altă parte, comenzile clienţilor.
Avantajele comerţului electronic sunt uriaşe pentru că nu implică cheltuieli
pentru spaţiile de desfacere (magazine) şi, teoretic, oferta se adresează
clienţilor din toată lumea.
- Votul electronic, aplicaţii prin care se poate afla părerea vizitatorilor
site-ului respectiv referitoare la tema supusă votului. Şi aici este important ca
un vizitator să nu voteze de mai multe ori, motiv pentru care baza de date
reţine adresa IP a vizitatorului.
- Aplicaţii de comunicare - aplicaţii prin care diverşi vizitatori ai site-ului
respectiv dezbat o anumită problemă, supusă discuţiei. În astfel de cazuri,
bazele de date vor reţine informaţii despre cei care scriu (de multe ori,
aceştia, mai întâi, trebuie să se înscrie în baza de date a site-ului) şi
mesajele acestora.
Există o mulţime de alte aplicaţii ale bazelor de date: site-urile diverselor
ziare, posturi de televiziune, bazele de date create şi exploatate de motoarele de
căutare, etc. Şirul acestora este practic infinit. Iată motivul pentru care ne vom iniţia
în crearea şi exploatarea bazelor de date pe Internet.
Ce este SQL ? În practica creării şi utilizării bazelor de date relaţionale s-a
1

impus necesitatea existenţei unui limbaj standard care permite efectuarea acestor
operaţii. Astfel, a apărut SQL - Structured Query Language. Limbajul este
supervizat de comisia de standardizare ANSI (American National Standards
Institute), motiv pentru care se mai numeşte şi ANSI SQL. SQL nu este un limbaj
de firmă, el este implementat de o mulţime de SGBD-uri, de această dată
consacrate, cum ar fi: Microsoft Access, Oracle, Microsoft SQL Server
şi, bineînţeles, MySQL.
Ce este MySQL ? MySQL este un limbaj specializat pentru gestiunea bazelor de
date relaţionale pe Internet. Aşa cum s-a mai spus, are la bază limbajul SQL.
MySQL gestionează baze de date care se găsesc pe server, iar comenzile pot fi
date cu ajutorul limbajului PHP, dar şi cu alte limbaje, de exemplu Java.

Revedeţi “Capitolul 1. Proiectarea bazelor de date” deoarece stă la baza tuturor noţiunilor
1

prezentate aici!
Capitolul 2. Limbajul MySQL 49

⇒ Prin utilizarea pachetului EasyPHP putem să instalăm MySQL pe calculatorul


nostru. Vedeţi Anexa 1! Exact în acest mod vom proceda pentru studiul
limbajului MySQL, adică vom crea baze de date pe calculatorul nostru.

2.2. Cum rulăm MySQL pe propriul calculator ?


Mai întâi, instalaţi pachetul EasyPHP, urmând paşii prezentaţi în Anexa 1.
Există două modalităţi prin care se pot da comenzi MySQL pe calculatorul nostru.

A) Prin utilizarea unei ferestre MS-DOS. Pentru aceasta va trebui să


identificaţi programul ”cmd.exe” care simulează sistemul de operare
amintit şi să creaţi un shortcut către acesta. Pentru comoditatea
apelului, este indicat ca shortcut-ul să se găsească pe Desktop. În
cazul nostru, va trebui ca fereastra CMD să fie deschisă în subfolder-ul
bin, al folder-ului care conţine MySQL. Executaţi clic cu butonul drept al mouse-ului
şi selectaţi Properties. În edit-ul Start in, al ferestrei care apare, introduceţi
calea către subfolder-ul bin al folder-ului mysql. De exemplu, pe calculatorul pe
care experimentăm utilizarea MySQL-ului, această cale este:
"C:\Program Files\EasyPHP1-8\mysql\bin"
Lansaţi în executare programul EasyPHP din meniu: Start, Programs, EasyPHP
şi executaţi dublu-clic pe shortcut-ul către CMD. Daţi comanda:
mysql -u root -p
şi introduceţi parola aleasă. Să observăm că MySQL afişează prompter-ul ”mysql>”
(vedeţi în figura de mai jos fereastra CMD):

Figura 2.1. Prompter-ul MySQL din fereastra CMD

De acum putem da comenzi MySQL!


Această modalitate de lucru prezintă avantajul că orice eveniment are loc
numai ca urmare a unei comenzi date de la tastatură şi pentru început, din
considerente pedagogice, este bine să procedăm aşa. Desigur, există şi
numeroase dezavantaje, cum ar fi faptul că de multe ori se pierde timpul tastând,
pentru că în cazul unei comenzi greşite aceasta trebuie reluată, ş.a.m.d.
50 Manual de Informatică pentru clasa a XII-a

B) Se poate utiliza şi un ansamblu de script-uri PHP aflate în fişierul ”index.php”


din folder-ul de phpmyadmin. Daţi browser-ului pe care-l utilizaţi comanda:
http://localhost/phpmyadmin/. Va fi afişată o fereastră în care vi se va
cere parola (vezi Fig. 2.2.). De acum puteţi lucra cu MySQL prin utilizarea unui
mediu vizual.

Figura 2.2. Fereastra de


autentificare

Observaţie ! Din considerente pedagogice şi pentru generalitatea prezentării, în


această carte vom folosi prima formă, cea în care se lucrează prin utilizarea unei
ferestre MS-DOS.

2.3. Crearea unei baze de date


⇒ În MySQL, pentru a crea o bază de date se dă comanda:
CREATE DATABASE nume_baza;

În urma acestei comenzi, teoretic, se creează baza de date cu numele


indicat. În fapt, se creează un folder cu numele bazei de date în subfolder-ul data
al folder-ului MySQL: C:\Program Files\EasyPHP1-8\mysql\data. Dacă
există deja o bază de date cu acest nume, se refuză crearea uneia noi.
⇒ În cazul în care, după deschiderea aplicaţiei sau în timpul sesiunii de lucru,
se doreşte lucrul cu o anumită bază de date, se dă comada de mai jos:
USE nume_baza;
⇒ Pentru ştergerea unei baze de date se utilizează comanda:
DROP DATABASE nume_baza
⇒ Uneori, din anumite motive, dorim o listă a bazelor de date existente. În
acest caz, se utilizează comanda de mai jos:
SHOW DATABASES
Capitolul 2. Limbajul MySQL 51

2.4. Tabele. Noţiuni elementare


Într-un tabel coloanele sunt identificabile prin nume, iar rândurile, prin
valorile pe care le memorează. Toate datele dintr-o coloană au acelaşi tip. Un
tabel are un număr specificat de coloane, dar are un număr nespecificat de
rânduri. Uneori, când ne referim la un rând, folosim şi termenul de înregistrare,
iar atunci când ne referim la data din rând, situată într-o anumită coloană, folosim
şi termenul de câmp .
1

⇒ O instrucţiune prin care se poate crea un tabel este prezentată mai jos, unde
2
ceea ce este trecut între paranteze drepte este considerat facultativ :
CREATE TABLE nume_tabel
( nume_coloana1 tip_data [specificatori],
nume_coloana2 tip_data [specificatori],
...
nume_coloanan tip_data [specificatori]
);

Specificatorii se referă la cheia primară, valori distincte, valori implicite,


autoincrementare, dacă printre valorile reţinute se poate găsi sau nu valoarea
NULL. Toate acestea sunt tratate separat.

Exemplul 2.1. Se creează un tabel cu 3 coloane: prima conţine codul materialului


şi poate reţine cel mult 5 caractere, a doua conţine denumirea materialului şi poate
reţine până la 20 de caractere, iar ultima reţine cantitatea din fiecare material (în
bucăţi) şi poate reţine un număr natural cu maximum 3 cifre:

CREATE TABLE materiale


(cod char(5),
denumire char(20),
cantitate_buc INT(3)
);

⇒ Pentru introducerea rândurilor în tabel se utilizează comanda de mai jos,


unde se introduc, pe rând, toate câmpurile unei linii, în ordinea în care au
fost declarate coloanele:
INSERT INTO nume_tabel VALUES (data1, data2...datan);

Exemplul 2.2. Se inserează în tabel două linii:


INSERT IMTO materiale VALUES(‘001’, ‘panouri’,78);
INSERT IMTO materiale VALUES(‘007’, ‘placi’,0);

1
Noţiunea de tabel este prezentată pe scurt. O prezentare amănunţită se găseşte în
capitolul anterior, “Proiectarea bazelor de date”.
2
Specificatorii vor fi trataţi separat. Tabelul astfel creat nu conţine nicio înregistrare. Pentru
adăugarea înregistrărilor utilizăm altă instrucţiune MySQL.
52 Manual de Informatică pentru clasa a XII-a

În practica utilizării bazelor de date, instrucţiunea anterioară este considerată ca


generatoare de erori, prin faptul că se poate greşi ordinea de introducere a datelor,
iar efectul este acela că tabelul va conţine date eronate. Din acest motiv, se
preferă forma de mai jos a instrucţiunii, deşi este necesar să scriem mai mult…

⇒ Se inserează în tabel valori pentru coloanele indicate în ordinea în care au


fost declarate coloanele:
INSERT INTO nume_tabel (nume_coloana1,... nume_coloanak)
VALUES (data1,...datak);

⇒ Pentru a afişa întreg tabelul se utilizează comanda:


SELECT * FROM nume_tabel

Exemplul 2.3. Pentru tabelul creat anterior se dă comanda:


SELECT * FROM materiale

Figura 2.3. Exemplu de tabel

Există posibilitatea să afişăm numai anumite coloane ale tabelului, în


ordinea pe care o dorim, dacă folosim instrucţiunea de mai jos:
SELECT nume_coloana1,... nume_coloanak FROM nume_tabel

 Să observăm faptul că, atunci când afişăm un tabel, în capul său se trece
numele coloanelor din tabel. Dacă dorim ca în capul de tabel să figureze alt
nume pentru o coloană, atunci, în instrucţiunea de mai sus, în loc de a scrie
numai numele coloanei, vom scrie numele coloanei urmat de cuvântul cheie
AS şi de numele care dorim să fie afişat în capul de tabel. Astfel, utilizăm
alias-uri pentru numele coloanelor.

Exemplul 2.4. Pentru tabelul de mai sus vom scrie:

SELECT cod AS codul, denumire AS nume, cantitate_buc AS cantitate


FROM materiale;

⇒ Putem vizualiza numele tabelelor existente în baza de date prin utilizarea


instrucţiunii următoare:
SHOW TABLES [FROM nume_baza]

⇒ În caz că am uitat care sunt coloanele dintr-un anumit tabel al bazei de date
şi tipul acestora, putem utiliza instrucţiunea:
SHOW COLUMNS FROM nume_tabel
Capitolul 2. Limbajul MySQL 53

2.5. Tipuri de date în MySQL


Aşa cum am văzut, coloanele au un anumit tip. Până în prezent, am utilizat
câteva tipuri fără a oferi o prezentare unitară a acestora. Este momentul s-o facem
acum.
În linii mari, tipurile de date din MySQL se împart în:
a) tipuri care reţin şiruri de caractere;
b) tipuri numerice;
c) tipuri care reţin data, ora.

În continuare, vom prezenta detaliat pe fiecare în parte.

2.5.1. Tipuri de date care reţin şiruri de caractere

Tipurile care reţin şiruri de caractere sunt prezentate mai jos:

Tip Descriere
Un câmp de acest tip reţine un şir de caractere de lungime
CHAR[(n)] n (fixă). În caz că n nu este precizat, reţine un caracter.
Ocupă n octeţi.
Un câmp de acest tip reţine şiruri de cel mult 255 de
VARCHAR caractere. Un octet reţine lungimea efectivă a şirului.
Ocupă n+1 octeţi.
TINYTEXT La fel ca mai sus.
Un câmp de acest tip reţine şiruri de cel mult 65535 de
TEXT caractere. Doi octeţi reţin lungimea efectivă a şirului. Ocupă
n+2 octeţi, unde n este numărul de caractere al şirului.
Un câmp de acest tip reţine şiruri de cel mult 16.777.215
MEDIUMTEXT caractere. Trei octeţi reţin lungimea efectivă a şirului.
Ocupă n+3 octeţi.
Un câmp de acest tip reţine şiruri de cel mult
LONGTEXT 4.294.967.295 de caractere. Patru octeţi reţin lungimea
efectivă a şirului. Ocupă n+4 octeţi.
Baza va reţine un vector de şiruri de caractere. Un câmp de
acest tip poate reţine un singur şir de caractere din
ENUM
vector. De altfel, coloana reţine indicele din şir. Vedeţi
exemplul 2.5!
Baza va reţine un vector de şiruri de caractere.. Un câmp
de acest tip poate reţine unul sau mai multe şiruri de
SET
caractere din vector. De altfel, se reţine vectorul
caracteristic al şirurilor. Vedeţi exemplul 2.6!
Tabelul 2.1. Tipuri de date care reţin şiruri de caractere
54 Manual de Informatică pentru clasa a XII-a

Exemplul 2.5. Se creează tabelul ”tstA” care are două coloane: prima reţine un
şir de cel mult 65.535 de caractere şi a doua, un şir din mulţimea şirurilor ”luni”,
”marti”, ”miercuri”. În tabel se inserează 3 linii şi, la sfârşit, tabelul este afişat.
Să observăm că în cazul coloanelor de tip SET,
dacă se încearcă memorarea unui şir inexistent
în definiţia coloanei (în exemplu, şirul ”joi”),
atunci acea coloană va reţine şirul vid.

Figura 2.4.
Tabelul “tstA”

CREATE TABLE tstA


( v1 TEXT,
v2 ENUM (‘luni’,‘marti’,‘miercuri’)
);

INSERT INTO tstA VALUES (‘un sir’,’miercuri’);


INSERT INTO tstA VALUES (‘un sir’,’joi’);
INSERT INTO tstA VALUES (‘alt sir’,’luni’);

SELECT * FROM tstA;

Exemplul 2.6. Se creează tabelul ”tstB” care conţine două coloane c1, de
lungime fixă de 3 caractere şi c2 de tip SET. Un element al coloanei poate reţine o
submulţime a mulţimii {”dimineata”, ”pranz”, ”seara”}.
Pentru a vedea cum se introduce submulţimea,
analizaţi cele trei instrucţiuni INSERT. În figura
alăturată puteţi observa tabelul rezultat în urma
introducerii datelor.

Observaţi faptul că, la ultima inserare, se


încearcă introducerea unui şir, ”noaptea”, care
nu este prezent în definiţia tipului coloanei. Nu se
semnalează eroare, dar şirul nu este introdus. Figura 2.5. Tabelul “tstB”
CREATE TABLE tstB
(c1 char(3),
c2 SET (‘dimineata’, ‘pranz’, ‘seara’)
);

INSERT INTO tstB VALUES (‘abc’,‘dimineata,seara’);


INSERT INTO tstB VALUES (‘abc’,‘seara,pranz’);
INSERT INTO tstB VALUES (‘abc’,‘seara’);
INSERT INTO tstB VALUES (‘abc’,‘seara,noaptea’);

SELECT c1,c2 FROM tstB;


Capitolul 2. Limbajul MySQL 55

2.5.2. Tipuri de date numerice

Tipurile numerice se împart la rândul lor în tipuri întregi şi tipuri reale.

Tipurile întregi se găsesc în tabelul de mai jos:

Tip Descriere
Un câmp de acest tip ocupă 1 octet. Reţine numere întregi
TINYINT cuprinse în intervalul [-128,127], iar dacă este urmat de
UNSIGNED reţine numere naturale cuprinse în intervalul [0,255].
Un câmp de acest tip ocupă 2 octeţi. Reţine numere întregi
cuprinse în intervalul [-32768,32767], iar dacă este urmat de
SMALLINT
UNSIGNED, reţine numere naturale cuprinse în intervalul
[0,65535].
Un câmp de acest tip ocupă 3 octeti. Reţine numere întregi
cuprinse în intervalul [-8.388.608, 8.388.607], iar dacă
MEDIUMINT
este urmat de UNSIGNED, reţine numere naturale cuprinse în
intervalul [0, 16.777.215].
Un câmp de acest tip ocupă 4 octet.i Reţine numere întregi
cuprinse în intervalul [-2.147.483.648, 2.147.483.647], iar
INT
dacă este urmat de UNSIGNED, reţine numere naturale cuprinse
în intervalul [0, 4294967295].
Un câmp de acest tip ocupă 8 octet.i Reţine numere întregi
cuprinse în intervalul [-9.223.372.036.854.775.808,
BIGINT 9.223.372.036.854.775.807], iar dacă este urmat de
UNSIGNED, reţine numere naturale cuprinse în intervalul [0,
18.446.744.073.709.551.615].

Tabelul 2.2. Tipuri de date numerice întregi

Observaţie ! Uneori veţi folosi declaraţii de tip de genul int(4). Aceasta


înseamnă că în coloană se rezervă automat o lăţime de 4 caractere pentru
afişarea numerelor. De exemplu, dacă numărul reţinut este 1, atunci el este afişat
ca bbb1, unde prin b am notat blank-ul. Aceasta nu afectează valorile care pot fi
memorate. De exemplu, dacă dorim să memorăm numărul 12345, acesta va fi
memorat şi se va afişa 12345. Dar, astfel este afectată lăţimea întregii coloane.

Tipurile reale se găsesc în tabelul de mai jos:

Tip Descriere
FLOAT Ocupă 4 octeţi.
DOUBLE Ocupă 8 octeţi.
56 Manual de Informatică pentru clasa a XII-a

Numărul este stocat ca şir de caractere. Parametrul n


reprezintă numărul de cifre nenule aflate înaintea virgulei,
plus, dacă este cazul, 1, pentru semnul -, iar d reprezintă
numărul de zecimale. Dacă numărul introdus are înaintea
DECIMAL(n,d)
virgulei un număr de cifre +1 (pentru semn) mai mare decât
n, acesta este trunchiat, iar dacă numărul de zecimale este
mai mare ca d, atunci se reţin exact d zecimale. În acest din
urmă caz, numărul se rotunjeşte la exact d zecimale.

Tabelul 2.3. Tipuri de date numerice reale

Exemplul 2.7. O coloană are tipul decimal(2,3):

Se introduce Se memorează şi afişează


1.1 1.100
23.4567 23.457
1 1.000
-5 -5.000
-15 -9.999

Tabelul 2.4. Cum se memorează şi se afişează diverse valori cu zecimale

2.5.3. Tipuri de date care reţin anul, data şi ora

În tabelul următor aveţi tipurile care reţin anul, data şi ora:

Tip Descriere
Un câmp de acest tip reţine ani. O dată se introduce ca şir
de caractere. De exemplu, pentru anul 2001 se poate
YEAR
introduce ‘2001’ sau ‘1’, iar pentru anul 1989 se poate
introduce ‘1989’ sau ‘89’.
Un câmp de acest tip reţine ora din zi - se introduce ca şir
TIME
de caractere sub forma ‘hh:mm:ss’.
Un câmp de acest tip reţine data. Aceasta se introduce sub
DATE
forma ‘yyyy-mm-dd’. De exemplu, ‘1999-11-24’.
Un câmp de acest tip reţine date de forma dată şi oră. O
DATETIME dată se introduce ca şir de forma:
‘yyyy-mm-dd hh:mm:ss’

Tabelul 2.5. Tipuri de date care reţin anul, data şi ora


Capitolul 2. Limbajul MySQL 57

2.6. Operatori utilizaţi în MySQL

Începem prin a prezenta principalii operatori în ordinea crescătoare a


priorităţii lor. Utilitatea operatorilor va fi evidenţiată în paragrafele următoare,
deocamdată doar îi prezentăm:

1. ||, OR, XOR


2. &&, AND
3. BETWEEN, CASE WHEN, THEN, ELSE
4. ==,>=,<=,<,>,!=,<>,IS,IS,LIKE,IN
5.|
6. &
7. <<, >>
8. -,+ (operatori binari)
9. *, /, DIV, %, MOD
10. ^
11. -,+ (operatori unari)
12. !, NOT

Pentru a putea testa un operator puteţi utiliza instrucţiunea


SELECT. De exemplu, dacă daţi comanda SELECT 1+1;, rezultatul se
1
vede în imaginea alăturată .

Observaţie foarte importantă ! În MySQL există o valoare specială, numită Null.


Semnificaţia ei este valoare necunoscută. Modul în care este posibil ca un câmp
să reţină respectiva valoare va fi prezentat ulterior. Deocamdată reţineţi faptul că,
dacă Null este un operand, atunci rezultatul oricărei operaţii care se efectuează
cu Null este Null. Evident, dacă operandul este Null, atunci el este
necunoscut, iar operaţia va avea rezultat necunoscut, indiferent de celălalt operand
sau de tipul operaţiei.

Exemplul 2.8. 1+Null⇒Null sau Null=Null⇒Null.

Operatorii se împart, aşa cum suntem deja obişnuiţi din alte limbaje de programare,
în mai multe grupe. Acestea sunt prezentate în continuare.

2.6.1. Operatori aritmetici

Operatorii aritmetici acţionează asupra tipurilor numerice şi returnează o


valoare de tip numeric. Pot fi analizaţi în Tabelul 2.6.

1
În cele ce urmează, pentru a evidenţia rezultatul unei operaţii, vom utiliza caracterul “⇒“.
Spre exemplu, 1+1 ⇒ 2.
58 Manual de Informatică pentru clasa a XII-a

Operator Operaţie Rezultat


2+3 ⇒ 1;
+ adunare
2 - 3 ⇒ -1;
- scădere
* înmulţire 3.5*2⇒6
/ împărţire 5 / 2 ⇒ 2.5;
5 DIV 2=2;
DIV împărţire întreagă -5 DIV 2 =-2
5 MOD 2⇒1
-5 MOD 2⇒ -1
MOD sau % restul împărţirii întregi
5 % 2 ⇒1;
-5 % 2 ⇒ -1
-, + Minus şi plus, operatori unari --1⇒1

Tabelul 2.6. Operatori aritmetici

2.6.2. Operatori de comparare

Pot fi comparate două valori numerice sau două şiruri. Şirurile se compară
lexicografic (ordinea din dicţionar) şi nu se face distincţie între literele mari şi cele
mici. Rezultatul este 1 pentru adevărat şi 0 pentru fals.

Operator Operaţie Rezultat


2 < 1 ⇒ 0;
< mai mic. 1 <2 ⇒ 0;
‘ab’<b ⇒ 1;
2 <=2 ⇒ 1;
<= mai mic sau egal
3>2 ⇒1
> mai mare ‘b’>’ab’ ⇒1

7>=7 ⇒ 1;
>= mai mare sau egal
7 XOR 8 ⇒ 0;
7=7⇒1
= egalitate
‘un’=’UN’⇒1
1<>2⇒1;
1!=2⇒1;
<> sau != diferit
1<>1⇒0’
1!=1⇒0;

Tabelul 2.7. Operatori de comparare

Observaţie ! Se pot compara şi date de tipul TIME, DATE, etc. În fapt, o astfel de
comparare este lexicografică. Vedeţi exemplul 2.9!
Capitolul 2. Limbajul MySQL 59

Exemplul 2.9. Analizaţi operaţiile de comparare de mai jos:


‘1:12:3’<‘2:00:00’⇒1, ‘1999-12-29’= ‘1999-12-29’⇒1.
‘1:12:3’<‘13:00:00’⇒0 - compararea s-a facut lexicografic, motiv pentru
care rezultatul este eronat.
‘01:12:3’<‘13:00:00’⇒1 pentru ca rezultatul să fie corect, chiar dacă
compararea este lexicografică, trebuie ca orele, minutele, secundele să fie cu
acelaşi număr de cifre. De fapt, atunci când se memorează în baza de date o astfel
de valoare, operaţia este făcută automat. Acesta este motivul pentru care
comparările efectuate cu date memorate în baza de date sunt corecte.

2.6.3. Operatori logici

În MySQL se consideră 2 valori logice: false, reprezentat de 0 şi true


reprezentat de 1 şi de orice valoare diferită de 0. Operatorii logici acţionează
asupra valorilor logice şi returnează 1, pentru adevărat şi 0, pentru fals.

Operator Operaţie Rezultat


2 || 1 ⇒ 1;
sau logic, dacă ambii operanzi sunt 0,
|| sau OR 0 || 1 ⇒ 1;
rezultatul este 0, altfel rezultatul este 1.
0 || 0 ⇒ 0;
şi, dacă ambii operanzi sunt diferiţi de 2 && 1 ⇒ 1;
&& sau 0, rezultatul este 1, altfel rezultatul este 2 && 0 ⇒ 0;
AND
0. 0 && 0 ⇒ 0;
NOT 3⇒0;
negare, dacă operandul este 0,
NOT NOT 1⇒=0;
rezultatul este 1, altfel rezultatul este 0.
NOT 0⇒=1;
sau exclusiv, dacă un operand este 0 şi 7 XOR 0 ⇒ 1;
XOR altul diferit de 0, rezultatul este 1, altfel, 7 XOR 8 ⇒ 0;
rezultatul este 0. 0 XOR 0 ⇒ 0;

Tabelul 2.8. Operatori logici

2.6.4. Operatori logici pe biţi

Se aplică tipurilor întregi şi acţionează asupra tuturor biţilor aflaţi pe poziţii


corespondente.

Operator Operaţie Rezultat


sau pe biţi, dacă ambii biţi sunt 0,
| 2 | 1 ⇒ 3
rezultatul este 0, altfel rezultatul este 1.
şi pe biţi, dacă ambii biţi sunt 1,
& 2 & 1 ⇒ 0
rezultatul este 1, altfel rezultatul este 0.
60 Manual de Informatică pentru clasa a XII-a

sau exclusiv pe biţi, dacă biţii sunt 10^3⇒9


^ diferiţi, rezultatul este 1, altfel rezultatul (1010
este 0. ^0011⇒1001)
negare, un bit 0 devine 1, un bit 1
~ ~0...01⇒1...10
devine 0.

Tabelul 2.9. Operatori logici pe biţi

2.6.5. Operatori de deplasare

Se aplică tipurilor întregi şi acţionează asupra tuturor biţilor aflaţi pe poziţii


corespondente.

Operator Operaţie Rezultat


deplasare stânga, deplasare către stânga
a biţilor operandului din stânga cu k poziţii, 1<<2⇒4
<<
unde k este operandul din dreapta. Poziţiile (1 trece în 100)
rămase libere se completează cu 0.
deplasare dreapta, deplasare către
4>>2⇒1
>> dreapta a biţilor operandului din stânga cu k
(100 trece în 1)
poziţii, unde k este operandul din dreapta.

Tabelul 2.10. Operatori de deplasare

2.6.6. Alţi operatori

Operatorii IS NULL, IS NOT NULL testează dacă o valoare este sau nu NULL
(sunt singurii operatori prin care se testează acest lucru)!

Exemplul 2.10. Analizaţi operaţiile următoare: 1 IS NULL ⇒ 0;, NULL IS


NULL ⇒ 1;, 1 IS NOT NULL ⇒ 1;, NULL IS NOT NULL ⇒ 0;.

Operatorii IN, NOT IN testează apartenenţa unei valori la o mulţime. Valoarea


poate fi de formă numerică sau de un tip care reţine un şir de caractere. Importanţa
mare pe care o au aceşti operatori va rezulta studiind paragrafele următoare.

Exemplul 2.11. Analizaţi operaţiile următoare: 1 IN(1,2,3,4) ⇒ 1;,


5 IN(1,2,3,4) ⇒ 0;, ‘1sir’ IN (‘1sir’,’2sir’,’3sir’) ⇒ 1;,
‘4sir’ IN (‘1sir’,’2sir’,’3sir’) ⇒ 0;.

Operatorul LIKE, NOT testează dacă un şir de caractere îndeplineşte anumite


condiţii: dacă este prefixat sau nu de un anumit subşir, dacă este postfixat sau nu
de acesta sau dacă subşirul se găseşte în interior. Pentru substituirea unui număr
neprecizat de caractere necunoscute se utilizează caracterul ”%”, iar pentru un
singur caracter neprecizat se utilizează caracterul ”_”.
Capitolul 2. Limbajul MySQL 61

Exemplul 2.12. Analizaţi operaţiile următoare:


‘popescu’ LIKE ‘pop%’⇒1; (‘popescu’ este prefixat de subşirul ‘pop’),
‘ponescu’ LIKE ‘pop%’⇒0; (‘ponescu’ nu este prefixat de subşirul ‘pop’),
‘ionescu’ LIKE ‘%escu’⇒1 (‘ionescu’ este postfixat de subşirul ‘escu’).

Operatorul BETWEEN min AND max testează dacă o valoare se găseşte între o
valoare minimă şi una maximă. În caz afirmativ returnează 1, altfel, 0. Se poate
aplica şi pentru date care reţin şiruri de caractere (ordinea lexicografică), dar şi
pentru datele de timp.

Exemplul 2.13. Analizaţi operaţiile următoare: 1 BETWEEN 0 AND 4 ⇒1;,


‘mama’ BETWEEN ‘min’ AND ‘lin’ ⇒1;, 2 BETWEEN 2 AND 2 ⇒1;,
1 BETWEEN 2 AND 4 ⇒0;, ‘1999-10-31’ BETWEEN ‘1989-12-10’ AND
‘2000-01-01’⇒1.

Operatorul CASE WHEN THEN ELSE. Poate fi aplicat în două forme:

Forma 1. Se evaluează v şi dacă produce valoarea vi se returnează valoarea


vali, iar dacă nicio condiţie vi nu este îndeplinită, se returnează valoarea valn+1:

CASE v
WHEN v1 THEN val1
[WHEN v2 THEN val2]
...
[WHEN vn THEN valn]
[ELSE valn+1]
END

Exemplul 2.14. Se afişează ‘doi’:

CASE 2
WHEN 1 THEN ‘unu’
WHEN 2 THEN ‘doi’
WHEN 3 THEN ‘trei’
ELSE ‘alta valoare’
END;

Forma 2. În această formă, dacă este îndeplinită condiţia i, se returnează


valoarea vi,. Dacă niciuna din condiţiile vi nu este îndeplinită, se returnează
valoarea vn+1:

CASE
WHEN conditie1 THEN v1
[WHEN conditie2 THEN v2]
...
[WHEN conditien THEN vn]
ELSE vn+1
END
62 Manual de Informatică pentru clasa a XII-a

Exemplul 2.14. Se afişează ‘adevarat’:


CASE
WHEN 1<2 THEN ‘adevarat’
ELSE “nu se poate’
END;

2.7. Funcţii MySQL

În MySQL există o serie de funcţii predefinite. Întrucât astfel de funcţii au fost


prezentate pentru limbajul studiat (Pascal sau C/C++), în acest paragraf vor fi
tratate pe scurt. Pot fi testate prin utilizarea instrucţiunii SELECT.

2.7.1. Câteva funcţii matematice

Funcţie Descriere Rezultat


ABS(-2) ⇒ 2;
ABS(x) Modul de x.
CEIL(1.7) ⇒2;
Cel mai mic întreg mai mare sau
CEIL(x) CEIL(2)⇒2;
egal cu x.
CEIL(-1.7)⇒-1;
FLOOR(-1.7) ⇒-2
Cel mai mare întreg mai mic sau
FLOOR(X) FLOOR(2) ⇒ 2;
egal cu x.
FLOOR(1.7) ⇒1;
EXP(x) ex EXP(1) ⇒2.7182...
LOG(b,x) Logaritm în baza b din x. LOG(2,4) ⇒2;
PI()⇒3.141593
PI() π
POW(x,y) xy POW(2,3)⇒8
ROUND(2.3)⇒2;
ROUND(x) Cel mai apropiat întreg de x. ROUND(2.7)⇒3;
ROUND(-2.8)⇒-3;
SIN(x) Sinus de x. SIN(PI()/2)⇒1;
COS(x) Cosinus de x. COS(0) ⇒1
SIGN(2) ⇒ 1;
Semnul lui x: -1, dacă x<0, 0, dacă
SIGN(x) SIGN(0) ⇒ 0;
x=0, 1 dacă x>0.
SIGN(-2) ⇒ -1;
SQRT(x) Radical din x. SQRT(4) ⇒ 2;

Tabelul 2.11. Funcţii matematice


Capitolul 2. Limbajul MySQL 63

2.7.2. Câteva funcţii care lucrează asupra şirurilor de caractere

Funcţie Descriere Rezultat


LENGTH(‘abc’) ⇒ 3;
LENGTH(x) Lungimea şirului x.
CONCAT(x1 CONCAT(‘ab’,’c’)
,x2,..) Concatenează şirurile x1,x2,…. ⇒ ‘abc’
Caută dacă y este subşir pentru
INSTR(‘abc’,’b’)⇒2
x. În caz afirmativ, returnează
INSTR(x,y) INSTR(‘abc’,’d’)⇒0
indicele de început (indicii încep
cu 1), altfel returnează 0.
Returnează subşirul din x care
SUBSTRING(x, SUBSTRING(‘abc’,2,1)
p,l) începe în poziţia p şi are ⇒’b’
lungimea l.
RTRIM(x) Returnează şirul fără blank-urile
RTRIM(‘un ‘)⇒’un’
din dreapta.
LTRIM(x) Returnează şirul fără blank-urile LTRIM(‘ un’) ⇒’un’
din stânga.
TRIM(x) Returnează şirul fără blank-urile
TRIM(‘ un ‘)⇒’un’
din stânga şi din dreapta.
Returnează şirul scris cu litere
UPPER(x) UPPER(‘Un’) ⇒’UN’
mari.
Returnează şirul scris cu litere
LOWER(x) LOWER(‘Un’) ⇒’un’
mici.
Returnează indicele apariţiei
FIND_IN SET
şirului x în şirul de şiruri FIND_IN_SET
(x,’s1,s2,
‘s1,s2,...,sn’. Dacă x nu (‘b’,’a,b,c’) ⇒ 2
..sn’)
este găsit, returnează 0.
Converteşte numărul real x la
FORMAT(x,d) un şir cu d zecimale. Pentru FORMAT(1.789,2)
ultima zecimală se face, dacă ⇒1.79
este cazul, rotunjirea.
Compară lexicografic şirurile x
şi y. Dacă x<y returnează -1, STRCMP(‘ma’,’mama’)
STRCMP(x,y)
dacă x=y returnează 1, iar dacă ⇒-1
x>y, returnează 1.

Tabelul 2.12. Funcţii care lucrează asupra şirurilor de caractere

2.7.3. Câteva funcţii care lucrează asupra datei şi orei

Funcţie Descriere Rezultat


Returnează data şi ora sub forma
NOW()
yyyy-mm-dd hh:mm:ss.
64 Manual de Informatică pentru clasa a XII-a

Dacă x este de tipul DATA, YEAR(NOW())


YEAR(x)
afişează anul extras din x. returnează anul curent.
DAY(NOW())returnează
DAY(X) Ca mai sus, extrage ziua.
ziua curentă.
MONTH(NOW())
MONTH(x) Ca mai sus, extrage luna.
returnează luna curentă.
TIME(NOW())
TIME(x) Ca mai sus, extrage ora.
returnează ora curentă.
HOUR(NOW())
Ca mai sus, extrage ora ca
HOUR(x) returnează ora curentă
număr între 0 şi 23.
ca număr între 0 şi 23.
MINUTE(NOW())
MINUTE Ca mai sus, extrage minutul. returnează minutul
curent
x şi y sunt de tip DATETIME sau
DATEDIFF DATEDIFF(NOW(),
(x,y) DATE. Calculează diferenţa în zile ’1989-12-21’)
dintre x şi y.
Calculează data care se obţine
dacă la valoarea data se adună DATE_ADD(NOW(),
DATE_ADD
nr, unde x specifică ce este nr: INTERVAL, 10 DAY)
(data,INTERV
AL,nr, x) YEAR - ani, DAY - zile, Se obţine data care va fi
MONTH - luni. peste 10 zile.

DATE_SUB(NOW(),
DATE_SUB
(data,INTERV La fel ca mai sus, numai că se INTERVAL, 10 DAY)
obţine data diferenţă. Se obţine data care a
AL,nr, x)
fost acum 10 zile.

Tabelul 2.13. Funcţii care lucrează asupra datei şi orei

2.7.4. Două funcţii speciale

Funcţia IF are forma de mai jos, unde expresie1 este de un tip întreg. Dacă
expresie1 este nenulă, atunci se returnează expresie2, altfel se returnează
expresie3. Atenţie: dacă expresie1 este de tip real, se rotunjeşte la cel mai
apropiat întreg. Dacă, de exemplu, acesta este 0.41, atunci se rotunjeşte la 0, prin
urmare, rezultatul va fi altul...
IF(expresie1,expresie2,expresie3)
Exemplul 2.15. Analizaţi exemplele următoare: IF (1>2, ‘adevarat’,
’fals’) ⇒ ‘adevarat’, IF (0.45, ‘nu’,’da’) ⇒’da’;.

Funcţia IFNULL are forma de mai jos. Dacă expresie1 nu este NULL, returnează
expresie1,, altfel returnează expresie2.
IFNULL(expresie1, expresie2)
Capitolul 2. Limbajul MySQL 65

Exemplul 2.16. Analizaţi exemplele următoare: IFNULL (0,‘este null’) ⇒


0, IFNULL (NULL,‘este NULL’) ⇒’este NULL’.

2.8. Afişarea coloanelor care rezultă în urma unui calcul

O regulă elementară în crearea şi utilizarea bazelor de date spune că


acestea vor reţine numai date care nu rezultă în urma unui calcul.
Nerespectarea ei conduce la baze de date care ocupă mult spaţiu. Acum vom
învăţa să afişăm datele care rezultă în urma unui calcul.

Exemplul 2.17. Priviţi tabelul din Fig. 2.6, numit ”prod”, care reţine produsele
existente într-un depozit. Pentru fiecare produs se cunoaşte cantitatea (”cant”) şi
preţul unitar (”pret_unitar”), preţul unui exemplar din produsul respectiv. Să
presupunem că dorim ca, pe lângă informaţiile afişate, să aflăm valoarea totală
pentru fiecare produs în parte. Valoarea se obţine ca produs între cantitate şi preţul
unitar.

Figura 2.6. Tabelul “prod”

Pentru aceasta, atunci când afişăm tabelul, vom crea o nouă coloană sub forma:
expresie AS nume_coloana, unde expresie calculează valorile din coloana
respectivă, iar ”nume_coloana” va fi numele ei. Iată cum se afişează noul tabel,
prezentat mai jos:

Figura 2.7.
Tabelul rezultat

SELECT den, cant, pret_unitar,


cant*pret_unitar AS valoare FROM prod;

Exemplul 2.18. Se dă tabelul alăturat, numit ”persoane”.


Se cere să se separe numele de prenume şi să se
afişeze datele ca mai jos:

Figura 2.8. Tabelul


“persoane”
Figura 2.9.
Tabelul dorit
66 Manual de Informatică pentru clasa a XII-a

Rezolvare. Se utilizează funcţii care operează asupra şirurilor de caractere:


SELECT SUBSTRING(nume,1,INSTR(nume,’ ‘)-1)
AS prenume
SUBSTRING(nume, 1+INSTR(nume,’ ‘),LENGTH(nume)) AS nume
FROM persoane;

Exemplul 2.19. Se consideră tabelul din Fig. 2.10, numit ”pers”, care cuprinde
numele şi data naşterii pentru două persoane:

Figura 2.10. Tabelul


“pers”

Se cere să se afişeze numele şi vârsta


fiecărei persoane.
Figura 2.11.
Tabelul dorit

Rezolvare. Se utilizează funcţii care operează asupra câmpurilor de tip DATE şi


DATETIME.

SELECT nume, YEAR(NOW())-YEAR(data_n) AS varsta FROM pers;

Exemplul 2.20. Se consideră un tabel, numit ”numar”,


alcătuit dintr-o singură coloană, c de tip INT. Se cere să
se listeze acea coloană şi o alta, numită ”paritate”,
care să conţină două valori: ‘par’ dacă numărul din c
este par şi ‘impar’, în caz contrar (vezi figura alăturată).

SELECT c, IF(C MOD 2, ‘impar’,’par’) AS


paritate FROM numar;
Figura 2.12.
Tabelul rezultat

2.9. Valoarea NULL

În MySQL, aşa cum s-a arătat, există o valoare specială, numită NULL.
Semnificaţia ei este “nicio valoare“.

Atunci când definim o coloană se poate trece specificatorul NULL. Oricum,


se asumă implicit, NULL. De altfel, acest lucru poate fi testat. Creaţi un tabel, de
exemplu, cu o coloană de un anumit tip, fără a specifica NULL sau NOT NULL şi
apoi daţi comanda SHOW COLUMNS FROM nume_tabel; şi analizaţi tabelul
afişat! Exerciţiu!
Capitolul 2. Limbajul MySQL 67

a) Atunci când o coloană are trecut specificatorul NULL sau nu s-a trecut nimic şi
la introducerea unui rând, pentru coloana respectivă, nu este trecută o valoare
pentru acel câmp, acolo se va memora valoarea specială NULL.

b) Atunci când o coloană are trecut specificatorul NOT NULL şi la introducerea


unui rând, în coloana respectivă, nu este trecută o valoare, acolo se va memora:
- 0, dacă coloana este de tip numeric;
- şirul vid, dacă coloana este de un tip care permite reţinerea de şiruri;
- indicele 0 din şir, dacă coloana este de tip ENUM şi aceasta are ca efect
afişarea primului şir al enumerării;
- mulţimea vidă, dacă coloana este de tip SET.

Analizaţi exemplele următoare şi verificaţi, de fiecare dată, tabelul afişat.

Exemplul 2.21. Rulaţi secvenţa de mai jos şi se va afişa


tabelul alăturat:
CREATE TABLE testnull
(c1 INT NULL,
c2 INT NOT NULL);
Figura 2.13.
INSERT INTO testnull (c2) VALUES (10); Tabelul rezultat
INSERT INTO testnull (c1) VALUES (7);

SELECT * FROM testnull;

Exemplul 2.22. Se creează tabelul alăturat, în care


coloanele reţin şiruri de caractere:
CREATE TABLE testnull1
(c1 TEXT NULL,
c2 TEXT NOT NULL); Figura 2.14.
INSERT INTO testnull1(c1) VALUES (‘Un sir’); Tabelul rezultat
INSERT INTO testnull1(c2) VALUES (‘Alt sir’);

SELECT * FROM testnull1;

Exemplul 2.23. Se creează tabelul din figura alăturată, în


care coloanele reţin date de tip ENUM:

CREATE TABLE testnull2


( c1 ENUM(‘sir1’,’sir2’,’sir3’) NULL,
c2 ENUM(‘sir1’,’sir2’,’sir3’) NOT NULL); Figura 2.15.
Tabelul rezultat
INSERT INTO testnull2(c1) VALUES (‘sir2’);
INSERT INTO testnull2(c2) VALUES (‘sir1’);

SELECT * FROM testnull2;


68 Manual de Informatică pentru clasa a XII-a

Exemplul 2.24. Se creează tabelul alăturat, în care


coloanele reţin date de tip SET.
CREATE TABLE testnull3
( c1 SET(‘sir1’,’sir2’,’sir3’) NULL,
c2 SET(‘sir1’,’sir2’,’sir3’) NOT NULL); Figura 2.16.
Tabelul rezultat
INSERT INTO testnull2(c1) VALUES (‘sir1,sir2’);
INSERT INTO testnull2(c2) VALUES (‘sir3’);
SELECT * FROM testnull3;

Aşa cum am arătat, semnificaţia lui NULL este “nicio valoare”. De asemenea, am
învăţat că o operaţie în care un operand este NULL, va avea rezultatul NULL. Acest
fapt este util, pentru că, în caz contrar s-ar putea ajunge la rezultate false.

Exemplul 2.25. Tabelul alăturat


“elev“ prezintă numele, nota la
engleză şi nota la franceză
pentru doi elevi. Unul dintre ei,
nu are notă la franceză (NULL). Figura 2.17. Tabelul “elev”

Se cere să se calculeze mediile celor doi


elevi. Scriem interogarea:
SELECT nume,
(engleza+franceza)/2 AS media;
Figura 2.18. Rezultatul interogării
Să observăm că pentru elevul căruia nu i se cunoaşte nota la franceză, nu i
se cunoaşte nici media. Logic vorbind, aşa este corect. Dacă nu se cunoaşte o
notă, nu se cunoaşte nici media deoarece n-ar fi normal ca pentru acest elev să se
afişeze media 10...

2.10. Valori implicite


În practică, nu întotdeauna se cunosc datele în totalitate. În astfel de cazuri,
atunci când pentru un anumit rând nu se cunoaşte un câmp, fie acesta va reţine
NULL, fie va reţine o valoare implicită, convenabil aleasă. De exemplu, dacă la un
examen de admitere un elev nu se prezintă la o probă, se poate lua decizia ca, la
acea probă, elevul să primească nota 1.
Pentru ca un câmp, în absenţa datelor să aibă o valoare implicită, se
foloseşte specificatorul DEFAULT:
DEFAULT valoare_implicita

 Facem observaţia că pot lua valori implicite câmpurile cu lungime fixă. De


exemplu, un câmp declarat CHAR(20) poate lua o valoare implicită, dar unul
declarat TEXT nu poate lua o astfel de valoare.
Capitolul 2. Limbajul MySQL 69

Exemplul 2.26. În tabelul următor, se reţin numele şi oraşul de domiciliu pentru


mai multe persoane:

Figura 2.19.
Tabelul propus

Dacă oraşul de domiciliu nu este cunoscut, se preferă, în locul valorii NULL, să fie
afişat şirul ‘necunoscut’:

CREATE TABLE pers_oras


(nume CHAR (25),
domiciliu CHAR(30) DEFAULT ‘necunoscut’);

INSERT into pers_oras (nume) VALUES (‘Gulagea Constantin’);


INSERT into pers_oras VALUES (‘Ionescu Mihai’, ‘Galati’ );

SELECT * FROM pers_oras;

2.11. Cheie primară şi cheie unică

A) Cheia primară este constituită dintr-un câmp (sau mai multe câmpuri) şi trebuie
să îndeplinească simultan condiţiile:
a) Valorile reţinute de coloana care alcătuieşte cheia primară trebuie să fie
distincte. În cazul în care cheia este alcătuită din mai multe coloane, pentru a
avea două chei distincte, este necesar ca acestea să fie diferite pentru cel
puţin o coloană dintre ele. Tentativa de a înscrie în tabel o înregistrare care are
cheia primară identică cu alta, existentă în tabel, este sancţionată cu eroare.
b) Câmpul (câmpurile) care alcătuieşte (alcătuiesc) cheia primară trebuie să
aibă o lungime fixă. De exemplu, nu poate fi cheie primară un câmp de tip TEXT.

Raţiunea existenţei cheii primare este dată de accesul foarte rapid la


înregistrarea de cheie dată. Trebuie ştiut că înregistrările unui tabel se reţin în
ordinea introducerii lor. Atunci când, de exemplu, un câmp este declarat cheie
primară, se construieşte un tabel auxiliar, invizibil pentru utilizator, în care pentru
fiecare valoare din câmpul cheie primară se reţine poziţia rândului care are acea
cheie. În acel tabel, cheile sunt în ordine crescătoare (dacă este vorba de şiruri de
caractere, acestea se reţin în ordine lexicografică, ca mai jos). Pornind de la cheie,
în tabelul “invizibil” se identifică rapid rândul cu acea cheie. În acest caz, se
foloseşte căutarea binară, algoritm studiat la informatică (revedeţi) şi, după cum
ştiţi, o astfel de căutare se face în O(log(n)). Din acel rând se află poziţia
înregistrării cu acea cheie din tabelul iniţial. De aici, accesul la înregistrare este
imediat. Căutarea clasică se efectuează în O(n).
70 Manual de Informatică pentru clasa a XII-a

Exemplul 2.27. Presupunem că tabelul principal are drept cheie primară câmpul
"Nume":

Tabel principal Tabel “invizibil”


Nume Vârstă Înălţime (cm) Nume Poziţie
Ion 15 173 Ana 3
Maria 17 159 Cristian 4
Ana 21 159 Ion 1
Cristian 12 171 Maria 2
Mihai 18 182 Mihai 5

Pentru a preciza că o anumită coloană este cheie primară se foloseşte, atunci când
se descrie coloana, specificatorul PRIMARY KEY.

Exemplul 2.28. Se creează un tabel în care prima coloană este cheie primară:
CREATE TABLE ex_cheie_primara_un_camp
(c1 INT PRIMARY KEY,
c2 TEXT
);

Dacă cheia primară este alcătuită din mai multe câmpuri, după descrierea
coloanelor, se utilizează specificatorul PRIMARY KEY sub forma:
PRIMARY KEY(nume_col1, nume_col2,...)

Exemplul 2.29. În tabelul următor cu trei coloane, coloanele c1 şi c2 alcătuiesc


cheia primară:
CREATE TABLE cheie_primara_doua_campuri
(c1 INT,
c2 CHAR(10),
c3 TEXT,
PRIMARY KEY(c1,c2)
);

B) Cheie unică - se poate cere ca o coloană (sau mai multe) să conţină numai
valori distincte. Pentru aceasta se va utiliza specificatorul UNIQUE KEY. În acest
caz, dacă în coloana respectivă se va încerca o inserare cu o valoare care există
deja, se va semnala eroare.
Observaţie ! Şi în acest caz, nu este permis să solicităm valori distincte pentru o
coloană de un tip de lungime variabilă (cum ar fi, de exemplu, tipul TEXT).
Exemplul 2.30. Se creează un tabel în care în ambele coloane vor fi numai valori
distincte:
CREATE TABLE distincte
( c1 INT UNIQUE KEY,
c2 char(10) UNIQUE KEY
);
Capitolul 2. Limbajul MySQL 71

2.12. Autoincrementare

Cu siguranţă, aţi văzut o mulţime de tabele în care rândurile sunt


numerotate. Mai jos, aveţi un astfel de tabel, cu numele unor persoane:

Figura 2.20. Tabelul cu


număr de ordine

Este incomod, ca la introducerea fiecărui rând să se specifice numărul de


ordine pentru rândul respectiv. Din acest motiv, s-a pus la dispoziţia clienţilor un
mecanism prin care incrementarea se face automat.

Pentru ca o coloană să reţină numerele de ordine al rândurilor respective,


este necesar ca, la definirea ei, să se utilizeze specificatorul AUTO_INCREMENT.
Pentru a putea utiliza acest specificator, este necesar să fie îndeplinite condiţiile:
a) coloana să fie de un tip întreg;
b) coloana să reţină numai valori distincte - pentru a determina aceasta,
coloana trebuie să fie declarată ca fiind cheie primară sau cu cheie unică.
Exemplul 2.31. Iată cum am creat tabelul din Fig. 2.20, numit ”auto”:
CREATE TABLE auto
(nr_ord INT UNIQUE KEY AUTO_INCREMENT,
nume CHAR(20)
);
INSERT INTO auto (nume) VALUES(‘Marius Oprean’);
INSERT INTO auto (nume) VALUES(‘Mihai Minca’);

Există şi posibilitatea să se introducă valori dorite în coloana declarată cu


autoincrementare. În acest caz, la următoarele introduceri, valorile implicite vor fi
obţinute pornind de la valoarea introdusă.
Exemplul 2.32. Analizaţi tabelul alăturat,
obţinut din cel anterior, la care s-au mai făcut
inserările de mai jos:
Figura 2.21. Tabel
modificat

INSERT INTO auto VALUES(7,‘Doru Cran’);


INSERT INTO auto (nume) VALUES(‘Dan Bitu’);
72 Manual de Informatică pentru clasa a XII-a

2.13. Sortarea datelor

Uneori este necesar ca datele să fie afişate sortate


după valorile unei coloane sau după valorile mai
multor coloane. Dacă acestea sunt de tip şir de
caractere, ele pot fi sortate în ordine lexicografică.
Alăturat aveţi un tabel, numit “sortare”, pe care
vom exersa modul de afişare a datelor sortate după
anumite criterii.
Figura 2.22. Tabel “sortare”

Exemplul 2.33. Datele sunt afişate sortate crescător,


după valorile existente în coloana ”nume”. Să
observăm că sortarea crescătoare este cea implicită,
pentru a o obţine nu este necesar să o specificăm:
SELECT * FROM sortare ORDER BY nume;

Figura 2.23. Tabelul sortat crescător

Exemplul 2.34. Pentru a sorta datele descrescător,


se foloseşte specificatorul DESC. Mai jos, am sortat
datele descrescător după valorile câmpului
”data_n” (data naşterii):

SELECT * FROM sortare ORDER BY


data_n DESC;
Figura 2.24. Tabelul sortat
descrescător după data naşterii

Există posibilitatea să sortăm datele (crescător sau descrescător) după valorile


existente în mai multe coloane. Practic, mai întâi se sortează datele după prima
coloană specificată, apoi, păstrând această ordine, după a doua coloană, ş.a.m.d.
Exemplul 2.35. Datele sunt sortate crescător
după valorile existente în coloana ”nume”, apoi,
păstrând această ordine, descrescător după
valorile din coloana ”data_n”.

SELECT * FROM sortare ORDER BY nume,


data_n DESC;
Figura 2.25. Tabelul sortat crescător
după ambele coloane

Observaţie ! Avem două persoane cu numele ”Mihai”. Mai întâi este afişată
persoana născută în 1980, apoi cea născută în 1975 (sortate descrescător după
câmpul ”data_n”).
Capitolul 2. Limbajul MySQL 73

Exemplul 2.36. Există posibilitatea să afişăm


numai un număr dorit de rânduri. Pentru aceasta
se foloseşte clauza LIMIT, ca mai jos:
SELECT * FROM sortare ORDER BY nume
LIMIT 3;
Figura 2.26. Afişarea unor rânduri din tabel

2.14. Filtrarea datelor

Uneori nu suntem interesaţi să fie afişate toate liniile tabelului, ci numai


unele, care îndeplinesc anumite condiţii. O astfel de operaţie se numeşte
filtrare. Pentru a realiza operaţia de filtrare se ataşează instrucţiunii SELECT, la
sfârşit, clauza WHERE condiţie. În acest fel, sunt selectate numai liniile pentru
care condiţia din clauza WHERE este îndeplinită. În cazul în care datele se cer
sortate, clauza ORDER BY se va trece după WHERE.

Exemplul 2.37. Se consideră un tabel precum cel de mai jos, în care se prezintă
situaţia şcolară a elevilor unei clase:
CREATE TABLE elevi
( nume TEXT,
matematica INT, engleza INT, informatica INT);

Figura 2.27. Tabelul “elevi”

1. Afişaţi numele elevilor care au la matematică note


mai mari sau egale cu 8.
SELECT nume FROM elevi Figura 2.28.
WHERE matematica>=8; Exemplu de filtrare

2. La fel ca mai sus, numai că se cere ca numele


elevilor să fie afişate în ordine alfabetică.
SELECT nume FROM elevi
Figura 2.29.
WHERE matematica>=8 Exemplu de filtrare
ORDER BY nume;
74 Manual de Informatică pentru clasa a XII-a

3. Se cere să se afişeze numele elevilor care au promovat la fiecare materie şi


media generală pe care aceştia o au.
SELECT nume, (matematica+engleza+informatica)/3 AS media
FROM elevi
WHERE matematica>4 AND engleza>4 AND informatica>4;

Figura 2.30.
Exemplu de filtrare

Observaţie ! Filtrarea datelor este un caz considerat particular al unui concept cu


mult mai general, interogarea! De obicei, interogăm o bază de date cu ajutorul
instrucţiunii SELECT.

2.15. Actualizări într-un tabel

În general, prin actualizarea unui tabel înţelegem modificarea datelor


reţinute de acesta şi/sau modificarea structurii sau numelui tabelului.

A) Prin actualizarea datelor dintr-un tabel înţelegem operaţii precum inserarea


unor linii, modificarea valorilor unor câmpuri şi ştergerea unor rânduri.

A1) Pentru inserare, putem utiliza instrucţiunile de mai jos:

1. INSERT INTO nume_tabel [(nume_col1, nume_col2..)


VALUES(expresie1, expresie2...)

Această instrucţiune a fost deja prezentată, nu vom mai reveni asupra ei.
2. INSERT INTO [DISTINCT} nume_tabel [(nume_col1, nume_col2..)
SELECT ....

Într-un tabel se pot insera linii dintr-un alt tabel. Pentru aceasta se foloseşte
instrucţiunea de mai sus (vezi Exemplul 2.38, pct. 1). Dacă se doreşte inserarea
numai a liniilor distincte din tabelul sursă, utilizaţi specificatorul DISTINCT.

A2) Pentru a modifica valorile reţinute de un câmp sau mai multe, se utilizează
instrucţiunea de mai jos (vezi Exemplul 2.38, pct. 2):

UPDATE nume_tabel
SET coloana1=expresie1,
...
coloanak=expresiek
[WHERE conditie];
Capitolul 2. Limbajul MySQL 75

În urma executării acestei comenzi, pentru fiecare rând din tabel care
îndeplineşte condiţia din WHERE, se actualizează coloanele indicate de SET cu
expresiile corespunzătoare.

Observaţie ! În absenţa clauzei WHERE sunt afectate toate rândurile din tabel.

A3) Ştergerea unui rând sau a mai multor rânduri se face cu instrucţiunea de mai
jos (vezi Exemplul 2.38, pct. 3 şi pct. 4):
DELETE FROM nume_tabel
[WHERE conditie]

Observaţie ! În absenţa clauzei WHERE sunt şterse toate rândurile din tabel.

B) Modificări ale numelui tabelului sau a structurii acestuia.

B1) Pentru a modifica numele unui tabel se utilizează instrucţiunea:

RENAME TABLE nume_vechi TO nume_nou

B2) Pentru ştergerea unei coloane, chiar dacă conţine date, se utilizează
instrucţiunea:
ALTER TABLE nume_tabel
DROP COLUMN nume_coloana

B3) Pentru adăugarea unei coloane cu un tip de date, se utilizează instrucţiunea:

ALTER TABLE nume_tabel


ADD nume_col tip;

Exemplul 2.38. Fie tabelele de mai jos, ambele cu aceleaşi coloane, de acelaşi tip:

Figura 2.31. Tabelul “prs” Figura 2.32. Tabelul “prs1”

1. Se cere să se insereze în tabelul ”prs”, acele


persoane din ”prs1” care sunt din ”Craiova”.
Alăturat, vedeţi tabelul ”prs” actualizat.

INSERT INTO prs (nume, oras)


SELECT nume, oras FROM prs1 WHERE
oras=’craiova’;
Figura 2.33.
Tabelul “prs” actualizat
76 Manual de Informatică pentru clasa a XII-a

2. S-a observat că Ioana şi Florin sunt de fapt


din braila. Corectaţi datele din tabel! Alăturat aveţi
afişat tabelul cu datele actualizate.

UPDATE prs
SET oras=’braila’
WHERE nume IN (‘ioana’, ‘florin’); Figura 2.34. Tabelul actualizat

3. Ştergeţi din tabelul ”prs” înregistrarea în care


numele este Mirela (vezi figura alăturată):

DELETE FROM prs


WHERE nume=’Mirela’; Figura 2.35.

4. Creaţi un nou tabel ”prs2”, cu aceeaşi structură


ca şi ”prs”, care să conţină numai persoanele din
”prs” care sunt din Braila şi Ploiesti.

CREATE TABLE prs2 AS


SELECT nume, oras FROM prs Figura 2.36. Tabelul nou “prs2”
WHERE nume IN (‘braila’, ‘ploiesti’);

Exemplul 2.39. În tabelul alăturat, ”prs”, există


mai multe înregistrări identice. Se cere să se
elimine duplicatele.

a) Creăm un alt tabel, de manevră, numit ”mand”,


care conţine aceleaşi înregistrări cu ”prs”, doar că
au fost eliminate duplicatele:
CREATE mand AS
SELECT distinct nume, oras FROM prs;
Figura 2.37. Tabelul “prs”
b) Ştergem tabelul ”prs”: DROP TABLE prs;

c) Redenumim tabelul ”mand” ca ”prs” şi-l afişăm


pe ”prs”:
RENAME TABLE mans TO PRD;
SELECT * FROM prs; Figura 2.38.
Tabelul rezultat

Observaţie! Mare atenţie când efectuaţi astfel de operaţii. În cazurile reale, în care
tabelele au mii de rânduri, se pot produce pierderi de date. Din acest motiv, înainte
de a actualiza un tabel, este bine să-i creaţi o copie de siguranţă pe care, după ce
aţi rezolvat problema, s-o ştergeţi.
Capitolul 2. Limbajul MySQL 77

2.16. Funcţii agregate


Toate calculele făcute până în prezent au avut ca operanzi doar câmpurile
unui aceluiaşi rând. Întrebarea este: se pot efectua calcule cu valorile reţinute de o
coloană? Răspunsul este afirmativ. Pentru astfel de calcule se utilizează
aşa-numitele “funcţii agregate”. În cele ce urmează, prezentăm aceste funcţii, iar
pentru exemplificare utilizăm tabelul ”elevi”, tabel pe care l-am creat în paragraful
2.14. Funcţiile agregate sunt prezentate în tabelul de mai jos:

Nume funcţie Ce realizează


Sub forma COUNT(*), afişează numărul de linii ale tabelului.
COUNT() Sub forma COUNT(nume_coloana), numără valorile, din
coloana de nume dat, care nu sunt NULL.
Sub forma MIN(nume_coloana), calculează cea mai mică
MIN()
valoare din coloană. Valorile NULL sunt ignorate.
Sub forma MAX(nume_coloana), calculează cea mai mare
MAX()
valoare din coloană. Valorile NULL sunt ignorate.
Sub forma SUM(nume_coloana), calculează suma valorilor
SUM()
dintr-o coloană. Valorile NULL sunt ignorate.
Sub forma AVG(nume_coloana), calculează media aritmetică
AVG()
a valorilor dintr-o coloană. Valorile NULL sunt ignorate.

Tabelul 2.14. Funcţii agregate

Exemplul 2.40. Câţi elevi sunt în tabel?


SELECT COUNT(*)
Figura 2.39.
AS numar_elevi FROM elevi;

Exemplul 2.41. Care este numărul de note la


engleză? Se afişează 4, pentru că un elev nu are
notă la această disciplină (NULL).
SELECT COUNT(engleza) AS Figura 2.40.
numar_note_engleza FROM elevi;

Exemplul 2.42. Care este media notelor la informatică?


SELECT AVG(informatica) AS
media_note_informatica FROM elevi;
Figura 2.41.
Exemplul 2.43. Câţi elevi au nota 10 la engleză?
SELECT COUNT(engleza) AS elevi_de_zece FROM
elevi
WHERE engleza=10;
Figura 2.42.
78 Manual de Informatică pentru clasa a XII-a

Exemplul 2.44. Câţi elevi au media generală peste 8?

SELECT COUNT(nume) AS elevi_peste_8


WHERE (matematica+engleza+informatica)/3>8;
Figura 2.43. Rezultat

2.17. Utilizarea subinterogărilor

Aşa cum am arătat, filtrările sunt cazuri particulare de interogări. În general,


orice rezultat care este obţinut cu ajutorul unei instrucţiuni SELECT este o
interogare. La modul general, o interogare poate returna:
A) o coloană, eventual cu un singur rând;
B) mai multe coloane - în acest caz se poate spune că interogarea
returnează un tabel.
Problema care se pune în continuare este următoarea: pot fi utilizate datele
returnate de o interogare pentru a efectua o nouă interogare? Răspunsul este, în
general afirmativ şi este valabil începând cu versiunea MySQL incorporată în
versiunea EasyPHP 1.8. În aceste cazuri, prima interogare care se efectuează
este interogarea subordonată. Rezultatul ei este utilizat pentru a efectua o nouă
interogare. Vom considera, pe rând, cazurile în care interogarea subordonată
returnează o valoare, o coloană şi un tabel (mai multe coloane). Toate exemplele
care urmează vor avea ca bază de plecare tabelul elevi, utilizat şi în paragrafele
anterioare.

A) Interogarea subordonată returnează o coloană cu un singur rând

Exemplul 2.45. Se cere să se determine numele elevilor care au cea mai mare
notă la matematică.

Figura 2.44.
Rezultatul dorit

Practic, ar trebui să vedem care este cea mai mare notă la matematică, o primă
interogare, problemă pe care o rezolvăm utilizând funcţia agregată MAX(), apoi
într-o nouă interogare, aflăm numele elevilor care au această notă. În acest caz,
interogarea subordonată returnează o valoare, cea maximă.
SELECT nume, matematica FROM elevi
WHERE matematica=(SELECT MAX(matematica) FROM elevi);

Mai întâi, se execută interogarea subordonată, apoi cea care o subordonează. În


acest caz, interogarea subordonată calculează nota maximă obţinută la
matematică (să observăm că aceasta nu este în mod obligatoriu 10), iar cealaltă
interogare returnează numele elevilor cu această notă.
Capitolul 2. Limbajul MySQL 79

Exemplul 2.46. Se cer numele elevilor care au cea mai mare medie la obiectele
matematică şi informatică. Vom proceda în acelaşi mod. În primul rând, selectăm
media maximă la obiectele amintite, apoi numele elevilor cu această medie.
SELECT nume, (matematica+informatica)/2 AS media FROM elevi
WHERE (matematica+informatica)/2=
(SELECT MAX((matematica+informatica)/2) FROM elevi);

Figura 2.45.
Rezultatul obţinut

Exemplul 2.47. Se cer numele elevilor şi media generală, unde media generală a
lor este strict mai mare decât media elevilor din tabel. Se cere, de asemenea, ca
elevii să fie ordonaţi în ordinea crescătoare a mediilor.

Interogarea subordonată calculează media generală a elevilor, iar prima interogare


afişează elevii care au media generală peste aceasta.
SELECT nume, (matematica+informatica+engleza)/3 AS media FROM elevi
where (matematica+engleza+informatica)/3>
(SELECT AVG((matematica+engleza+informatica)/3) FROM elevi)
ORDER BY media DESC;

Figura 2.46.
Rezultatul obţinut

Exemplul 2.48. Care este numele elevilor care au aceeaşi notă la matematică ca
şi elevul Popescu Marius? În acest caz, interogarea subordonată returnează
nota la matematică a elevului Popescu Marius, iar interogarea care o
subordonează returnează numele elevilor care au această notă:
SELECT nume FROM elevi WHERE matematica=
(SELECT matematica FROM elevi
WHERE nume=’Popescu Marius’); Figura 2.47.
Rezultatul obţinut

B) Interogarea subordonată returnează un tabel

În acest caz, tabelul returnat de interogarea subordonată trebuie să aibă un


nume. Acesta se dă cu ajutorul clauzei AS. De asemenea, interogarea care
subordonează adresează câmpurile tabelului, pornind de la numele său, urmat de
‘.’ şi de numele coloanei.

Exemplul 2.49. Care este media generală la matematică şi la informatică a elevilor


care au cel puţin 8 la una dintre discipline?
80 Manual de Informatică pentru clasa a XII-a

Tabelul returnat de interogarea subordonată conţine notele la matematică şi


la informatică ale elevilor care au cel puţin 8 la una dintre aceste discipline. Acest
tabel se numeşte virtual. Interogarea principală calculează mediile la matematică şi
informatică ale acestor elevi.
SELECT AVG(virtual.matematica) AS medie_mate,
AVG(virtual.informatica) AS medie_info FROM
(SELECT matematica, informatica FROM elevi
WHERE matematica>=8 OR informatica>=8) AS virtual;

Figura 2.48.
Rezultatul obţinut

2.18. Gruparea datelor

Datele dintr-un tabel pot fi grupate în funcţie de valorile dintr-o anumită


coloană. De exemplu, datele din tabelul din Fig. 2.49 pot fi grupate după valorile
din coloana ”data”. Astfel, un grup este alcătuit din rândurile de tabel
corespunzătoare datei ‘2006-03-15‘, altul, corespunzătoare datei ‘2006-03-16‘,
..., altul corespunzător unei date necunoscute (NULL). Prelucrările datelor din
fiecare grup se fac cu ajutorul funcţiilor agregate, aşa cum suntem deja obişnuiţi.
Pentru a grupa datele din tabel după valorile unei coloane se utilizează clauza
GROUP BY nume_coloana, adăugată după numele tabelului. Exemplele care
urmează vă vor lămuri!

Exemplul 2.50. Se consideră tabelul


“vanzari” cu structura de mai jos
care conţine data vânzării, numele
produsului vândut şi valoarea
vânzării din produsul respectiv:

CREATE TABLE vanzari


( data DATE,
produs CHAR(15),
valoare INT);

Figura 2.49.
Tabelul “vanzari”

Întrebări:

1. Care este numărul de vânzări din fiecare zi? Grupăm datele după dată şi
numărăm vânzările pentru fiecare grup.
Capitolul 2. Limbajul MySQL 81

SELECT data, COUNT(*) AS numar_vanzari FROM vanzari


GROUP BY data;

Figura 2.50. Numărul de


vânzări din fiecare zi

2. Care este suma vânzărilor zilnice? Grupăm datele după dată şi însumăm
vânzările pentru fiecare dată în parte:
SELECT data, SUM(valoare) AS
suma_vanzari FROM vanzari
GROUP BY data;

Figura 2.51. Suma


vânzărilor zilnice

3. Care este numărul de vânzări şi suma vânzărilor în fiecare zi (se va afişa un


singur tabel)?
SELECT data, COUNT(*) AS nr_vanzari, SUM(valoare) AS suma_incasata
FROM vanzari GROUP BY data;

Figura 2.52. Numărul de


vânzări şi suma încasată
din fiecare zi

4. Care este data în care am am vânzări în valoare maximă, câte vânzări au fost
şi care este suma încasată?

Ar trebui să obţinem un tabel care să conţină data şi suma vânzărilor zilnice, apoi,
din aceasta să selectăm vănzarea maximă şi, apoi, data la care s-a efectuat
vânzarea zilnică. În MySQL, în varianta de care dispunem, nu este permisă mai
mult de o interogare cu subordonata sa. Din acest motiv, vom crea un tabel de
manevră (“manevra“) care conţine data şi suma vânzărilor zilnice (ca la punctul 2).
Apoi din acesta, utilizând o interogare cu subinterogare, vom extrage datele cerute.
În final, vom şterge tabelul “manevra“.
CREATE TABLE manevra AS
SELECT data, SUM(valoare) AS vanzare
FROM vanzari GROUP BY data;

Pentru probă, afişăm tabelul manevra.


SELECT * FROM manevra;
Figura 2.53. Tabelul “manevra”
82 Manual de Informatică pentru clasa a XII-a

Pornind de la “manevra”, obţinem datele cerute.


SELECT data, vanzare FROM manevra
WHERE vanzare=
(SELECT MAX(vanzare) FROM manevra);

Ştergem tabelul ”manevra”: Figura 2.54. Rezultatul final


DROP TABLE manevra;

2.19. Uniuni de tabele

Un punct de maximă importanţă şi eficienţă în utilizarea bazelor de date este


dat de uniunea de tabele. Uniunea este alcătuită din două sau mai multe tabele
între care există o legătură. De cele mai multe ori, legătura este dată de valorile
existente în câte o coloană a fiecărui tabel din uniune. Pentru tabelele care
alcătuiesc uniunea se pot utiliza alias-uri de nume, sub forma nume_tabel AS
alias_nume, introduse în clauza FROM. Alias-urile pot fi utilizate în orice parte a
instrucţiunii select. În aceste cazuri, adresarea unei coloane a tabelului se face
sub forma: alias_nume.nume_col.

Avantajele utilizării alias-urilor sunt:


- se pot asigura nume scurte pentru tabele, gen A, B,..., etc.
- în cazul auto-uniunilor, caz care este prezentat în actualul paragraf, un
singur tabel poate avea alias-uri diferite, fapt care permite anumite
interogări speciale ca şi cum am avea mai multe tabele: A, B, etc. În astfel
de cazuri, atunci când ne referim la o coloană, pentru a nu se crea
confuzie, trebuie precizat tabelul, cum ar fi de exemplu: A.nume_col,
B.nume_col, etc.

1) O primă formă de realizare a unei uniuni este utilizarea instrucţiunii SELECT în


care la clauza FROM se trec, pe rând, toate tabelele care o alcătuiesc, iar legătura
este precizată cu ajutorul clauzei WHERE. Vezi exemplele 2.51, pct. 1.a), 4, 5.
2) Atunci când uniunea este alcătuită din două tabele, se poate preciza o
legătură de tip INNER sub forma de mai jos. În astfel de cazuri, se afişează datele
din tabel1 şi din tabel2, pentru care este îndeplinită condiţia din ON. O astfel de
uniune se mai numeşte şi uniune interioară. Vezi exemplul 2.51, pct. 1.b)!
nume_tabel1 [AS...]INNER JOIN nume_tabel2 [AS...]
ON conditia de uniune

3) Atunci când uniunea este alcătuită din două tabele, se poate preciza o
legătură de tip LEFT OUTER sub forma de mai jos. În astfel de cazuri, se afişează
toate datele din tabel1, iar datele din tabel2 se afişează numai dacă este
Capitolul 2. Limbajul MySQL 83
îndeplinită condiţia din ON, altfel, în locul lor se afişează valoarea implicită (NULL,
de cele mai multe ori). O astfel de uniune se mai numeşte şi uniune exterioară
stânga. Vezi exemplul 2.51, pct. 2.
nume_tabel1 [AS...]LEFT JOIN nume_tabel2 [AS...]
ON conditia de uniune

4) Atunci când uniunea este alcătuită din două tabele, se poate preciza o
legătură de tip RIGHT OUTER sub forma de mai jos. În astfel de cazuri, se afişează
toate datele din tabel2, iar datele din tabel1 se afişează numai dacă este
îndeplinită condiţia din ON, altfel, în locul lor se afişează valoarea implicită (NULL,
de cele mai multe ori). O astfel de uniune se mai numeşte şi uniune exterioară
dreapta. Vezi exemplul 2.51, pct. 3.
nume_tabel1 [AS...]LEFT JOIN nume_tabel2 [AS...]
ON conditia de uniune

Exemplul 2.51. Priviţi tabelele de mai jos, numite "produse" (cel din stânga) şi
"date_produse" (cel din dreapta). Logic, legătura dintre ele este dată de
coloanele "cod", din fiecare tabel. Astfel, pentru un cod dat, din tabelul "produse"
se poate extrage cantitatea existentă într-un magazin dintr-un anumit produs şi
denumirea produsului, producătorul său din tabelul "date_produse".

Figura 2.55. Cele două tabele propuse ca exemplu

1. Pentru fiecare produs existent în magazin,


care este trecut în tabelul "date_produse", să
se afişeze denumirea şi cantitatea. Pentru a
rezolva această problemă, vom utiliza două forme
de interogare şi ambele dau acelaşi rezultat.
a)
Figura 2.56.
SELECT B.denumire, A.cantitate Rezultatul interogărilor
FROM produse AS A, date_produse AS B
WHERE A.cod=B.cod;

b)
SELECT B.denumire, A.cantitate
FROM produse AS A INNER JOIN date_produse AS B
ON A.cod=B.cod;
84 Manual de Informatică pentru clasa a XII-a

2. La fel ca la punctul anterior, numai că se vor


trece datele existente pentru toate produsele din
tabelul ”produse”:

SELECT B.denumire, A.cantitate


FROM produse AS A LEFT OUTER JOIN
date_produse AS B
ON A.cod=B.cod; Figura 2.57. Rezultat

3. La fel ca mai sus, numai că se vor trece datele


existente pentru toate produsele din tabelul
”date_produse”:

SELECT B.denumire, A.cantitate


FROM produse AS A RIGHT OUTER JOIN
date_produse AS B
ON A.cod=B.cod; Figura 2.58. Rezultat

4. O problemă serioasă care apare în cerinţele de acest tip este dată de faptul că
nu întotdeauna, orice cod din primul tabel, în exemplu ”produse”, se află printre
codurile din al doilea tabel, în exemplu, ”date_produse”. Se cere să afişăm
codurile din tabelul ”produse” care nu se regăsesc între codurile din tabelul
”date_produse”. Analizaţi interogarea de mai jos, este şi un exemplu de utilizare
a operatorului NOT IN:
SELECT cod FROM produse Figura 2.59.
WHERE
cod NOT IN (SELECT cod FROM date_produse);

5. Selectaţi codurile de produse din tabelul ”date_produse” care nu


1
se regăsesc printre codurile din tabelul ”produse” .
SELECT cod FROM date_produse
WHERE Figura 2.60.
cod NOT IN (SELECT cod FROM produse);

Auto-uniuni. Se pot obţine rezultate interesante


dacă cele două tabele sunt, de fapt, unul şi acelaşi,
dar au aliasuri diferite şi se consideră unite printr-o
coloană.

Exemplul 2.52. În tabelul alăturat, numit “st_or“


(referitor la localităţile din care provin studenţii unei
grupe dintr-o facultate), care sunt persoanele care
locuiesc în acelaşi oraş cu Ioana? Figura 2.61. Tabelul “st_or”

1
În cazul în care considerăm tabelul ”produse” drept tabel tată şi tabelul ”date_produse”
drept tabel fiu, pentru a fi respectată integritatea referenţială, ar trebui ca mulţimea acestor
coduri să fie vidă.
Capitolul 2. Limbajul MySQL 85

Privim acelaşi tabel ca pe două tabele diferite legate prin câmpul


oras. Unul dintre tabele are numele A şi al doilea are numele B.
Interogarea constă în afişarea tuturor numelor din B care au
aceeaşi valoare în câmpul oras cu înregistrarea din A care,
pentru câmpul nume, reţine ‘Ioana’.
Figura 2.62.
SELECT B.nume Rezultatul interogării
FROM st_or AS A INNER JOIN st_or AS B
ON A.oras=B.oras AND
A.nume=’Ioana’;

Observaţie ! Evident, aceeaşi problemă poate fi rezolvată prin utilizarea


mecanismului subinterogărilor. Exerciţiu!

2.20. Elemente care privesc securitatea bazelor de date

Asigurarea securităţii bazelor de date este o problemă extrem de serioasă.


Paragraful are numai rolul de a vă iniţia în această activitate. În realitate, problema
este cu mult mai complexă.

Sistemul de privilegii MySQL. O primă problemă care apare este de a


securiza, pe cât posibil, bazele de date. Din acest punct de vedere, în afara
administratorului, există posibilitatea ca la bazele de date să aibă acces şi alte
persoane, identificabile prin nume şi parole. Totuşi, aceste persoane au acces
numai la anumite operaţii cu bazele de date. Pentru ca o astfel de persoană (care
nu este utilizator) să acceseze baza de date este necesar ca administratorul să
introducă numele ei, parola şi operaţiile pe care le poate efectua. Astfel,
administratorul va utiliza instrucţiunea MySQL numită GRANT, a cărei formă
simplificată o prezentăm mai jos:
GRANT operaţii
ON nume_bază
TO nume_utilizator IDENTIFIED BY ‘parola’;

Operaţiile permise sunt: SELECT, UPDATE, INSERT, INDEX, ALTER, CREATE,


DROP şi trebuie să fie separate prin virgule. Atunci când accesul utilizatorului este
permis pentru orice bază de date, se utilizează *.*.

Exemplul 5.70. De acum, utilizatorul lavinia cu parola puful are acces la


operaţii de tip SELECT şi INSERT pentru orice bază de date.
GRANT SELECT, INSERT
ON *.*
TO lavinia IDENTIFIED BY ‘puful’
86 Manual de Informatică pentru clasa a XII-a

Pentru a revoca unele drepturi ale unui utilizator sau chiar toate,
administratorul foloseşte instrucţiunea REVOKE. Pentru a revoca toate operaţiile
permise, se utilizează ALL.

REVOKE operaţii
ON nume_bază
FROM nume_utilizator

Exerciţiu. Acordaţi drepturi unor utilizatori, verificaţi dacă le au, revocaţi anumite
drepturi şi verificaţi apoi dacă le mai au.

1. ”Materiale”. O firmă dispune de mai multe depozite. În fiecare depozit există


mai multe materiale. Pentru fiecare material se cunoaşte preţul şi cantitatea. Se
cere să se răspundă la întrebările de mai jos. Tabelul se numeşte ”materiale”.

Figura 2.63.
Tabelul “materiale”

1.1. Care sunt materialele existente într-un anumit depozit (în exemplu,
‘Depozit 2’) ?
1.2. Care sunt depozitele în care există un anumit material (în exemplu,
‘material 3’? Se presupune că numele materialului poate fi precedat de blank-uri.
1.3. Care este valoarea totală a tuturor materialelor din depozite?
1.4. Care este valoarea totală a materialelor din fiecare depozit?
1.5. Presupunem că ‘material 1’ se scumpeşte cu 10%. Actualizaţi datele din
tabel.
1.6. Să se şteargă un anumit material (‘material 2’) din tabel.

2. “Împrumuturi”. Există persoane care au credite, în acelaşi timp, la mai multe


bănci. O astfel de situaţie este prezentată în tabelul de mai jos, numit
”imprumuturi”. Se cere să se răspundă la următoarele întrebări:
Capitolul 2. Limbajul MySQL 87

Figura 2.64.
Tabelul “imprumuturi”

2.1. Care sunt persoanele care au împrumutat de la ‘Banca 1’?


2.2. Care este suma împrumutată de fiecare bancă populaţiei?
2.3. Afişaţi, pentru fiecare persoană, numărul împrumuturilor pe care le-a efectuat.
2.4. Care sunt persoanele care au împrumutat o sumă maximă şi care este
această sumă?
2.5. Care sunt persoanele care au împrumutat bani cel puţin de la o bancă la
care a împrumutat şi ‘Ionescu Grigore’?

3. “Proprietari, proprietăţi”. Se dă un tabel (“proprietari“), în care pentru


fiecare persoană se cunoaşte codul (cod) şi numele (nume). Se dă şi un alt tabel
(“proprietati“) în care se cunoaşte codul proprietarului (cod_proprietar),
tipul proprietăţii (tip_p) şi valoarea proprietăţii (valoare):

Figura 2.65. Tabelul


“proprietari”

Figura 2.66. Tabelul “proprietati”


3.1. Afişaţi, pentru fiecare proprietar care are cel puţin o proprietate, numărul
proprietăţilor.
3.2. Afişaţi numele proprietarilor care nu au proprietăţi.
3.3. Afişaţi codurile proprietarilor din tabelul “proprietati“ care nu au
corespondent în tabelul “proprietari“.
3.4. Afişaţi valoarea proprietăţilor pe care le are fiecare proprietar. Datele vor fi
afişate în ordinea descrescătoare a proprietăţilor.

4. “Prietenii”. Se dau două tabele (“baieti” şi “fete”) în care pentru fiecare


persoană se cunoaşte codul (cod), numele (nume) şi vârsta (varsta). De
asemenea, mai există un tabel, numit “prietenii”, în care sunt reţinute relaţiile
dintre băieţi şi fete.
88 Manual de Informatică pentru clasa a XII-a

Figura 2.67. Tabelul ” baieti” Figura 2.68. Tabelul ” fete”


4.1 Care sunt prietenele lui Mihai, cel care are 18 ani?
Observaţie ! Se presupune că există un singur băiat
Mihai care are 18 ani.
4.2 Afişaţi numele fetelor care nu au prieten.
4.3 Pentru fiecare băiat care are cel puţin o prietenă,
afişaţi numele prietenelor pe care acesta le are.
4.4 Afişaţi numele unei fete cu un număr maxim de
prieteni şi numărul prietenilor ei.
4.5 Afişaţi media de vârstă a băieţilor şi a fetelor.
Figura 2.69.
Tabelul ” prietenii”
5. ”Angajaţi”. O firmă doreşte să reţină într-o bază de date un tabel referitor la
angajaţi. Motivul este dat de faptul că se vrea obţinerea rapidă a răspunsurilor la
întrebările de mai jos. Ce date va reţine tabelul? Cum obţinem răspunsul la întrebări?
5.1 Care sunt numele angajaţilor (în ordine alfabetică)?
5.2 Care sunt angajaţii cu vârsta sub 30 de ani?
5.3 Realizaţi o listă a femeilor angajate şi o alta a bărbaţilor angajaţi.
5.4 Realizaţi o listă a angajaţilor care au studii superioare.
5.5 Care sunt angajatele care sunt în concediu de maternitate?
5.6 Care sunt angajaţii cu o vechime în meseria pe care o practică la firmă de sub
trei ani?
5.7 Care sunt angajaţii care au salariul minim pe economie?
5.8 Care sunt angajaţii care au salariul brut mai mare decât cel minim, dar mai
mic decât 1000 de lei?
5.9 Care sunt angajaţii care ies la pensie anul următor?
5.10 Care sunt angajaţii care au copii şi câţi copii au?
5.11 Mâine este Sfânta Maria. Care este lista sărbatoritelor?
5.12 Găsiţi angajaţii care îşi sărbătoresc mâine ziua de naştere!
6. ”Cheltuieli / Venituri”. George este o persoană căreia îi place să-şi ţină
evidenţa veniturilor şi cheltuielilor. El are un tabel cu următoarele câmpuri: Data,
Cheltuiala/Venit, Suma cheltuită sau încasată, Explicaţii (Text). Să presupunem că
George şi-a completat tabelul câteva luni, în fiecare zi. Fiecare sumă cheltuită sau
încasată este înregistrată pe o linie a tabelului. Se cere:
6.1 Care sunt veniturile totale ale lui George şi care sunt cheltuielile sale pe toată
perioada cât a ţinut evidenţa?
Capitolul 2. Limbajul MySQL 89

6.2 A reuşit George să economisească o sumă de bani în această perioadă sau


a fost nevoit să se împrumute? Care este suma economisită sau împrumutată?
6.3 În care lună George a cheltuit cea mai mare sumă?
6.4 În care lună George a avut cele mai mari încasări?
6.5 Care este luna în care George a economisit cea mai mare sumă?
6.6 Creaţi un tabel care să conţină toate veniturile lui George pe întreaga
perioadă şi un altul care să conţină toate cheltuieliule în aceeaşi perioadă.
6.7 Creaţi un tabel care să conţină, pentru fiecare lună în parte, suma încasărilor
şi suma cheltuielilor.
7. ”Biblioteca”. Ioana s-a angajat la o bibliotecă şi doreşte să ţină evidenţa
cărţilor pe calculator.
7.1 Ioana doreşte, în primul rând, să ţină evidenţa titlurilor pe care le are la
bibliotecă. Pentru aceasta, Ioana codifică toate titlurile şi reţine pentru fiecare
titlul, editura şi autorul.
7.2 Pentru a ţine evidenţa numărului de exemplare din fiecare titlu, existente în
gestiune, este nevoie de un alt tabel, numit Nr Exemplare. Creaţi-l!.
7.3 Care este legătura între cele două tabele?
7.4 În continuare, trebuie creat un tabel, numit Cititori, care conţine
persoanele care împrumută cărţi de la bibliotecă (Nume, Adresa, Nr. telefon)
Înainte de a împrumuta o carte, cititorul este înscris în acest tabel. Creaţi-l!.
7.5 De asemenea, trebuie creat un tabel (Imprumuturi) în care, pentru fiecare
carte împrumutată, este scrisă o înregistrare care conţine numele cititorului şi codul
cărţii (o înregistrare conţine un singur exemplar dintr-un titlu). Creaţi-l!
7.6 Se cere o situaţie în care sunt afişaţi cititorii care au împrumutat o carte de
mai mult de două săptămâni.
7.7 Câte exemplare sunt împrumutate din fiecare carte?
7.8 Câte exemplare sunt împrumutate din cartea care are codul x?
7.9 Pentru fiecare carte împrumutată, se cere codul cărţii, tilul şi numărul
exemplarelor aflate la cititori.
7.10 Un cititor solicită un anumit titlu. Ioana vrea să vadă dacă există exemplare
neîmprumutate din acesta.
8. Problemă pentru lucrul în colectiv! “Grilă“. Scrieţi o grilă cu 18 itemi (18
întrebări la care răspunsul corect este unul singur, ales dintre 4 răspunsuri). În final
se va afişa nota obţinută de cel care este testat prin utilizarea acestei grile. Fiecare
răspuns corect este punctat cu 0.5 puncte şi un punct se acordă din oficiu. Desigur,
dacă este necesar, itemii vor fi însoţiţi de imagini. Problema va fi rezolvată de
echipe diferite, pe diverse domenii: informatică, matematică, biologie, limbi străine,
chimie, istorie, ş.a.m.d. Un set de astfel de probleme va fi util elevilor din toată ţara!
9. Problemă pentru lucrul în colectiv! “Magazin“. Creaţi un site prin care o firmă
vinde calculatoare şi diverese componente de calculatoare. Comenzile se pot face
prin intermediul site-ului şi ele sunt stocate în baza de date. Se cere să se
efectueze validarea datelor de intrare. De asemenea, reprezentanţii firmelor pot
extrage din baza de date comenzile dintr-o anumită zi şi pot memora date
referitoare la expedierea produselor.
(pentru verificare, rezolvările se găsesc la pag. 381)
CAPITOLUL
Primii paşi către construcţia unui site

În acest capitol recapitulăm noţiunile referitoare la Internet care


au fost studiate la ”Tehnologia Informaţiei şi a Comunicaţiilor”. De asemenea,
vom învăţa să instalăm şi să utilizăm un program FTP prin intermediul căruia
vom putea transfera fişiere între calculatorul personal şi server.

 Ce este Internet-ul ?
 Protocolul TCP / IP
 Ce trebuie să ştim despre site-uri ?
 Un program FTP
 Cum scriem un fişier HTML?

Cuvinte cheie: pagină web, site web, host, ISP,


protocol, TCP/IP, DNS, URL, FTP, SMTP,
client, server, proxy, HTML, browser
Capitolul 3. Primi paşi către construcţia unui site 91

3.1. Ce este Internet-ul ?

⇒ Prin Internet înţelegem totalitatea calculatoarelor,


aflate oriunde în lume, care comunică între ele.

 Spunem că două calculatoare comunică dacă între ele are loc un


schimb de date. Convenim să numim “host“ (în română, gazdă)
un calculator care participă la schimbul de date.

Reţeaua Internet conţine calculatoare de mare viteză, care comunică prin


fibră optică şi/sau prin satelit şi au rolul de a transmite rapid informaţia, oriunde în
lume. Anumite firme, numite ISP (Internet Service Provider, pe scurt
“provider“), dispun de calculatoare performante, numite “server“-e, legate la
unul dintre calculatoarele cu rol de transmitere a informaţiei. Provider-ul oferă,
contra cost sau din alte raţiuni, diverşilor clienţi posibilitatea cuplării propriilor PC-uri
la server, adică accesul la Internet. Provider-ul oferă şi alte servicii, cum ar fi
“webhosting“-ul (spaţiu pe hard-disc pentru găzduirea paginilor web, conturi
pentru e-mail, precum şi soft specializat pentru manipularea acestora).

⇒ Pentru a accesa Internet-ul de la un oarecare calculator, acesta trebuie


să fie conectat la server-ul unui provider. Există mai multe variante de
conectare. Precizăm faptul că modalităţile de conectare sunt prezentate în
ordinea crescătoare a vitezei de transmisie a datelor. Nu vom prezenta
vitezele de transmisie, deoarece acestea sunt într-o continuă creştere,
mărginindu-ne numai la a preciza faptul că rata (viteza) de transfer
(“Transfer Rate“) a datelor se exprimă în “Mbps“ (mega biţi pe secundă).

Principalele tipuri de conexiuni la Internet

1) Conectare prin intermediul cablului telefonic. Practic, calculatorul se


conectează temporar la un server, prin intermediul unui dispozitiv numit “modem“.
Prin formarea unui număr de telefon de acces, se obţine conexiunea cu acesta.
Cât timp calculatorul este conectat, nu se mai poate utiliza telefonul.
2) Conectare prin ISDN (“Integrated Services Digital Network“) este
un serviciu pus la dispoziţie de firma de telefonie fixă. Şi aici, conexiunea este
temporară, deci se plăteşte în funcţie de timpul în care suntem conectaţi. Faţă de
modalitatea anterioară, în afara vitezei mai mari pentru schimbul de date, aceasta
prezintă avantajul că se poate utiliza în acelaşi timp şi telefonul.
3) Conectare prin intermediul liniilor telefonice închiriate. În acest caz,
conexiunea este permanentă. Practic, utilizatorul face un contract cu furnizorul de
telefonie fixă, care montează o linie telefonică între calculatoarele utilizatorului şi
server-ul provider-ului.
4) Conectare prin cablu TV (coaxial). Conectarea permite transmisia datelor şi
recepţia programelor TV în acelaşi timp.
92 Manual de Informatică pentru clasa a XII-a

5) Conectare prin fibră optică. Mediul fizic prin care sunt transferate datele este
fibra optică, obţinând o rată de transfer mult mai ridicată decât cele anterioare.

6) Conectare prin cablu UTP (Unshielded Twisted Pair) - una dintre cele mai
frecvente conexiuni la Internet. Principiul de bază este simplu: mai multe PC-uri
se interconectează prin intermediul unui hub/switch, formând o reţea locală.
Această reţea de calculatoare se conectează, la rândul ei, printr-o conexiune
rapidă (de exemplu, prin fibră optică), cu provider-ul de Internet.

7) Conectare prin unde electro-magnetice terestre sau prin satelit. Aceste


tehnologii sunt numite “wireless“ (fără fir). În acest caz, echipamentele sunt mult
mai costisitoare şi necesită operaţii complexe de instalare.

⇒ În linii mari, putem considera că Internet-ul oferă următoarele servicii:

• World Wide Web (www) - putem crea şi vizita diverse pagini web;
• E-mail - serviciu de poştă electronică;
• Chat - modalitate prin care doi sau mai mulţi utilizatori pot discuta în
acelaşi timp.

Bineînţeles, acestea trei sunt doar baza de la care pornesc o multitudine de alte
servicii, cum ar fi: e-commerce (comerţ pe Internet), e-banking (management
financiar, plăţi on-line), diverse tipuri de liste de discuţii (forum, newsgroup), etc.

3.2. Protocolul TCP/IP

Pentru ca două sau mai multe calculatoare să poată comunica este necesar
să existe un “protocol“, adică un ansamblu de norme care trebuie respectate de
calculatoare (de programale care rulează pe ele) pentru ca schimbul de date să
aibă loc. Normele se referă la:

• găsirea calculatorului destinatar al transferului de date;

• transmiterea efectivă a datelor;

• modalităţi prin care expeditorul comunică faptul că au fost transmise


toate datele, iar destinatarul că le-a recepţionat;

• compresia datelor - prin aplicarea anumitor algoritmi matematici, datele


care urmează să fie expediate sunt prelucrate, de aşa natură, încât să
fie memorate prin utilizarea unui spaţiu mai mic de memorie. Prin
urmare, transmiterea lor durează mai puţin. Invers, la destinaţie sunt
decompresate prin utilizarea aceloraşi algoritmi matematici.
Capitolul 3. Primi paşi către construcţia unui site 93

• identificarea erorilor care pot interveni în transmiterea datelor. Problema


este următoarea: de unde “ştie” calculatorul care a recepţionat date
dacă acestea sunt corecte? Şi aici există mai mulţi algoritmi care permit
identificarea şi corectarea erorilor.

⇒ Pe Internet se foloseşte protocolul TCP/IP (Transmission Control


Protocol/Internet Protocol). Protocolul este, de fapt, numele comun
al unei familii de protocoale utilizate pentru transferul datelor în reţea. În
continuare vom prezenta pe scurt câteva dintre protocoalele din familia
TCP/IP.

Orice calculator conectat la Internet are o adresă, numită adresă IP


(Internet Protocol Adress). O adresă IP este alcătuită din 4 numere între 0
şi 255. Prin urmare, o astfel de adresă ocupă 4 octeţi. Cum transmisia datelor se
face între două calculatoare, datele se transmit de la o adresă IP la alta.

 Protocolul IP (Internet Protocol) reglementează transmiterea


datelelor de la o adresă IP la alta. Datele sunt transmise divizate în pachete
(packets). Fiecare pachet conţine IP-ul expeditorului şi IP-ul destinatarului.

 Prin protocolul TCP (Transmission Control Protocol) se verifică


corectitudinea transmisiei.

În Internet se pot accesa anumite resurse, fişiere de orice tip (html,


imagine, date, etc). Orice resursă are, aşa cum ştim, o anumită adresă, numită
adresa URL (Uniform Resource Locator). De exemplu, dacă adresa unui site
este “http://www.exemplu.ro“, ea este o adresă URL. De fapt, este adresa
fişierului index, care are adresa completă
“http://www.exemplu.ro/index.html“,

în cazul în care fişierul index are extensia html. De asemenea, un fişier imagine,
să spunem “iepure.jpg“, aflat în folder-ul “img“ al site-ului din exemplu, are
adresa URL:
“http://www.exemplu.ro/img/iepure.jpg“.

 DNS (Domain Name System) asigură legătura dintre adresa URL a unui
site şi adresa IP a acestuia. Practic, în edit-ul browser-ului se tastează
adresa URL, acesta o transmite, dar prin algoritmul impus de acest protocol
se găseşte adresa IP asociată. Transferul datelor se efectuează, aşa cum
s-a arătat, utilizând adresa IP găsită.

 FTP (File Transfer Protocol) are rolul de a reglementa transferul


fişierelor între două calculatoare. Există programe specializate care, prin
utilizarea acestui protocol, transferă fişiere. De regulă, utilizarea lor se
face în situaţia în care o persoană gestionează un site web aflat pe un
alt calculator (server). Atunci când aceasta actualizează site-ul, transferă
fişiere către server.
94 Manual de Informatică pentru clasa a XII-a

 SMTP (Simple Mail Transfer Protocol) are rolul de a reglementa


transferul e-mail-urilor.

Din cele prezentate până în acest moment, rezultă că fiecare calculator care
participă la schimbul de date pe Internet are o adresă IP permanentă. În realitate
nu este chiar aşa… Unele calculatoare au într-adevăr o adresă IP permanentă,
însă altele nu. Să prezentăm două cazuri:

1) Ne conectăm de la PC-ul de acasă, prin linie telefonică, la Internet. În acest


caz, calculatorul nostru se numeşte client, iar cel al provider-ului server. Provider-ul
dispune de o mulţime de adrese IP care urmează să fie alocate. Calculatorului
nostru i se alocă, automat, o adresă IP care este disponibilă în acel moment. Un
astfel de server rulează un soft special, care utilizează protocolul DHCP (Dynamic
Host Configuration Protocol). După închiderea conexiunii, acea adresă IP
se va putea aloca altui client.

2) Dispunem de o reţea de calculatoare şi dorim ca de pe fiecare calculator din


reţea să putem accesa Internet-ul. În acest caz, se obişnuieşte ca un calculator al
reţelei, numit “server proxy“, să fie cuplat la Internet printr-o linie închiriată
(aceasta asigură o viteză de transfer suficient de mare). Toate celelalte
calculatoare ale reţelei accesează Internet-ul prin intermediul său. Evident, pe
server-ul proxy trebuie să existe un soft specializat. Toate calculatoarele din reţea
au şi ele adrese IP, dar interne, nerecunoscute decât în reţeaua locală, nu şi pe
Internet, dar server-ul proxy utilizează o adresă IP recunoscută pe Internet.

3.3. Despre site-uri

⇒ Dacă o persoană (sau societate comercială), care are acces la Internet,


doreşte să aibă un site, va apela la serviciile unei firme specializate (numită
“provider“). Provider-ul dispune (sau a închiriat la rândul lui) de unul sau
mai multe calculatoare extrem de performante, cuplate la Internet prin linii
care permit transferul rapid al datelor şi care rulează programe specializate,
numite “server“-e şi pune la dispoziţie:

• spaţiu pe hard-disc-ul server-ului de cel puţin 10Mb;


• o adresă de Internet (de exemplu, www.adresa.ro ).
1

⇒ În spaţiul rezervat, persoana (firma) pune mai multe fişiere care conţin, de
regulă, fişiere HTML (Hyper Text Markup Language), dar şi alte fişiere
(gif, jpeg, doc). Prin aceste fişiere se poate descrie activitatea firmei, se
poate face comerţ electronic, se poate prezenta o anumită temă, etc).

Aveţi posibilitatea ca site-ul să aibă asociată o adresa URL oferită gratuit de provider sau
1

să cumpăraţi o astfel de adresă.


Capitolul 3. Primi paşi către construcţia unui site 95

⇒ Pentru a putea vizita o pagină, este necesar un program specializat, numit


generic “browser“. Acesta trebuie să se găsească pe calculatorul celui care
doreşte să viziteze pagina respectivă şi, în linii mari, are funcţiile:

1. permite utilizatorului să introducă adresa URL a paginii respective şi


transmite cererea către server, pentru ca acesta să-i furnizeze fişierul
HTML care conţine codul respectivei pagini, dar şi fişierele care reţin
imaginile din pagină (cu extensia jpeg, gif, etc).

2. după ce primeşte codul HTML al paginii respective, interpretează


comenzile pe care le conţine şi îl afişează.

Evident, conţinutul site-ului poate fi accesat de pe orice alt calculator


conectat la Internet.

Terminologie. Calculatorul pe care se găseşte site-ul se numeşte, aşa cum am


precizat, “server“, iar calculatoarele care accesează conţinutul site-ului se
numesc, în acest caz, “client“. Un astfel de model de transmisie a datelor poartă
denumirea de “client-server“ (vezi Fig. 3.1).

Server

Cerere Răspuns
Răspuns
Cerere

Cerere Răspuns

Client 3
Client 1

Client 2

Figura 3.1. Exemplu de model de tip client-server

Întrebările fireşti în acest moment sunt este: ce software este necesar să


existe pe calculatorul client şi ce software trebuie să existe pe server?
96 Manual de Informatică pentru clasa a XII-a

3.3.1. Software-ul necesar pentru calculatorul “client”

Orice calculator client trebuie să dispună de un browser, cu ajutorul căruia


să se poată vizualiza fişierele HTML. Există mai multe programe de tip browser,
cum ar fi: Internet Explorer, Firefox, Mozilla, Opera, Netscape,
fiecare dintre acestea având mai multe versiuni. Din păcate, între acestea există
anumite diferenţe atunci când afişează fişierele HTML. Evident, există multe puncte
comune. Este recomandabil, ca atunci când scriem codul necesar unei pagini web,
să utilizăm specificaţiile de HTML standard şi, mai ales, să testăm pagina utilizând
cât mai multe tipuri de browser-e.
Pentru a gestiona un site web, aflat evident pe server, utilizatorul are nevoie
de un program FTP prin care să poată efectua mai multe operaţii asupra spaţiului
rezervat pe server: transfer sau ştergere de fişiere şi creare, modificare sau
ştergere de folder-e.

3.3.2. Software-ul necesar pentru calculatorul “server”

În primul rând, pe server trebuie să se găsească un program care răspunde


cererilor browser-rui aflat, aşa cum s-a spus, pe calculatorul client. Un astfel de
program se numeşte program de tip server.
Atunci când, de exemplu, dorim să vizualizăm o anumită pagină, tastăm
adresa URL în edit-ul browser-ului şi apăsăm tasta Enter sau efectuăm clic pe
butonul GO. Browser-ul emite o cerere către server pentru ca acesta să-i trimită
fişierul respectv. Evident, dacă este posibil, server-ul va furniza browser-ului fişierul
solicitat. Cererea efectuată de browser şi răspunsul server-ului se fac prin
respectarea unui anumit protocol. Acest proticol se numeşte HTTP (Hyper Text
Transfer Protocol). Prin urmare, un program de tip server răspunde cererilor
care se conformează protocolului HTTP.

Există mai multe programe de tip server, cel mai popular fiind Apache, care
lucrează pe server-e cu sistemul de operare Linux, dar şi pentru cele cu sistemul
de operare Windows. El este dezvoltat de Apache Software Foundation şi
1
este de tip “open source“ . Un alt program de tip server este Microsoft IIS
(Microsoft Internet Information Services), destinat sistemelor de
operare de tip Windows.

Facultativ, pe server se găsesc programele PHP şi MySQL. Bineînţeles,


închirierea unui spaţiu pe un server care deţine aceste programe este mai scumpă.
PHP-ul permite ca paginile web sa fie personalizate, iar cu ajutorul MySQL-ului se
pot crea baze de date pe Internet. De asemenea, cu ajutorul PHP-ului se pot da
comenzi MySQL-ului pentru crearea şi actualizarea bazelor de date.

Termenul descrie accesul gratuit la codul sursă al unui produs software, care este
1

disponibil spre a fi copiat, modificat şi personalizat de către oricine, fără a fi impuse drepturi
intelectuale restrictive asupra programului.
Capitolul 3. Primi paşi către construcţia unui site 97

Observaţie. Puteţi să obţineţi gratuit spaţiu pe server şi adresa URL pentru site-ul
dvs., pentru că există firme care oferă aceasta utilizatorilor. Căutaţi cu Google! Din
păcate, este puţin probabil să găsiţi gratuit un server care are PHP şi MySQL.
Oricum, chiar şi în aceste condiţii, se pot crea site-uri reuşite utilizând doar limbajul
HTML. Dacă doriţi un site care să conţină PHP şi MySQL, limbaje care vor fi
prezentate în această carte, atunci trebuie să plătiţi acest serviciu suplimentar.

Modalitatea de instalare a programelor Apache, PHP şi MySQL este detaliată


în Anexa 1, care se găseşte la pag. 370.

3.4. Un program care lucrează sub FTP

Să presupunem că am obţinut un anumit spaţiu pe un server, avem o adresă


URL pentru site şi acum vrem să-l construim şi să-l putem întreţine. Problema care
se pune în continuare este transferul fişierelor de pe calculatorul personal (client)
către server şi invers. În această carte vom utiliza un program care lucrează sub
protocolul FTP şi anume “WS_FTP95“. Acest program poate fi descărcat de pe
pagina web
“www.uottawa.ca/help/ws_ftpe.html“,
iar dacă această adresă nu mai este actuală, identificaţi o nouă locaţie de unde
poate fi download-at (cu Google, textul “ws_ftp95 download“).

După ce aţi instalat programul, va apărea o cutie de dialog în care trebuie să


introduceţi datele de identificare. Am presupus că adresa URL a site-ului este:
“www.invatare.b0x.com“ (vezi Fig. 3.2).

Figura 3.2.
Fereastra de introducere a
datelor de identificare

Dacă introducerea datelor de identificare s-a făcut în mod corect, automat


programul va afişa conţinutul fişierelor din site în cadrul din partea dreaptă şi a unui
folder de pe propriul calculator în stânga. De aici şi modalitatea de lucru: vom avea
pe hard-disc un folder care reţine fişierele care trebuie să fie transferate pe site.
Acesta este folder-ul (în exemplu, “PTest“) care este afişat de programul FTP
(vezi Fig. 3.3). Pe server avem două fişiere, iar cel care ne interesează iniţial este
“index.html“.
98 Manual de Informatică pentru clasa a XII-a

Trecerea unui fişier de pe propriul calculator pe site se face prin operaţia


Drag and Drop (se mută cursorul grafic asupra sa, apăsăm butonul stâng şi-l
“tragem” către panoul din dreapta) sau selectăm fişierul şi-l transferăm cu ajutorul
butonului săgeată. Analog, se poate muta un fişier de pe site pe calculatorul nostru.

Figura 3.3. Fereastra programului WS_FTP95

⇒ Ştergerea unui fişier sau folder se face cu butonul Delete.


⇒ Crearea unui folder (director) se face prin apăsarea butonului MkDir.
⇒ Apăsarea săgeţii are ca efect trecerea în folder-ul părinte.

⇒ Schimbarea unităţii de disc pe propriul calculator se face prin


executarea unui clic asupra numelui ei (vezi fig. alăturată).

Figura 3.4. Lista unităţilor de disc


de pe calculatorul client

 După cum observaţi, este foarte simplu să lucrăm cu un program FTP.


Pentru transfer, bifaţi butonul ASCII. Veţi fi scutiţi astfel de anumite erori
care pot apărea la executare.
Capitolul 3. Primi paşi către construcţia unui site 99

3.5. Cum scriem un fişier HTML ?

Presupunem că avem un site web şi putem să transferăm fişiere de la


calculatorul nostru către el şi invers. Ştim că, pentru a scrie o pagină web, trebuie
să cunoaştem limbajul HTML (HyperText Markup Language). Acesta este
prezentat detaliat în Capitolul 4.

Întrebarea la care răspundem în acest moment este următoarea: cum se


scrie codul HTML?

⇒ Browser-ul poate afişa un fişier HTML aflat pe calculatorul nostru. Un astfel


de fişier are una dintre extensiile: htm sau html. Puteţi căuta cu Find un
astfel de fişier şi executaţi dublu clic pe icon-ul său. Imediat va fi apelat
browser-ul, iar acesta va afişa fişierul.

⇒ Mai ştim că, atunci când browser-ul afişează un astfel de fişier, putem vedea
codul său sursă (din meniul View, apelăm comanda Source). Automat, se
va lansa programul NOTEPAD care realizează aceasta.

De aici rezultă şi modul în care vom scrie astfel de fişiere:

a) Vizualizăm cu My Computer folder-ul unde dorim să se găsească fişierul.

b) Apelăm la meniul flotant (clic cu butonul drept al mouse-ului) şi alegem New


şi Text Document. Programul NOTEPAD va crea un fişier fără conţinut, cu
extensia txt.

c) Modificăm numele şi extensia fişierului. La fel, atunci când cursorul grafic se


găseşte deasupra icon-ului său, apăsăm butonul drept al mouse-ului şi
alegem Rename. Vom scrie un nume dorit de noi, iar extensia va fi html.
Fie numele său ”primul.html”. Întrucât extensia html este asociată
browser-ului (Internet Explorer, la noi), fişierul va avea de această dată
icon-ul browser-ului (vezi Fig. 3.4).

Figura 3.4.
Exemplu de fişier HTML

d) Executarea unui dublu clic asupra icon-ului are ca efect lansarea browser-ului
care va afişa fişierul. Evident, în această fază, conţinutul său este vid.

e) Apelaţi din meniu View şi Source. Programul NOTEPAD va încărca codul


HTML al fişierului (conţinutul este vid), deschizând-ul astfel pentru editare.
100 Manual de Informatică pentru clasa a XII-a

f) Scrieţi un text la alegerea dvs. Exemplu: “Acesta este primul text”.


Salvaţi-l!

g) În fereastra browser-ului apăsaţi butonul Refresh. Prin această operaţie am


comandat reîncărcarea fişierului, întrucât i-am schimbat conţinutul. Textul va
fi afişat de browser:

Figura 3.5. Vizualizarea fişierului prin browser

Observaţii

 Procedând astfel, putem scrie uşor cod HTML. Din când în când, vizualizăm
efectul modificărilor şi identificăm eventualele erori.

 După cum vă puteţi da seama, operaţia de scriere a codului nu presupune


accesul la Internet.

Validatoare HTML

Am văzut cum se scrie, în mod clasic, codul HTML. Dacă dorim, în scrierea
codului se pot utiliza diverse validatoare (programe specializate) HTML. Care este
rostul lor?

• Validatoarele HTML lucrează la fel de uşor ca NOTEPAD-ul. Ele scriu


direct fişiere cu una din extensiile htm sau html.

• Apăsarea unui buton al validatorului are ca efect lansarea browser-ului


care afişează fişierul (procedând astfel, lucrăm mai eficient).

• Putem valida fişierele HTML (adică verificăm corectitudinea din punct de


vedere sintactic - la identificarea unei erori, ne este indicată locaţia sa).
Capitolul 3. Primi paşi către construcţia unui site 101

De ce este utilă operaţia de validare a fişierelor HTML?

Trebuie urmărit modul în care procedează browser-ul atunci când codul


HTML nu este corect. Browser-ul va afişa ceea ce “distinge” din cod, deci nu va
semnala eroarea. Uneori, o eroare poate trece neobservată deoarece browser-ul
de care dispunem trece peste ea. Dar, cum nu există un singur program de tip
browser, un alt tip ar putea afişa informaţia incorect.

 Un exemplu de astfel de validator, gratuit, este CSE HTML Validator


Lite, care poate fi descărcat de pe pagina:
“www.htmlvalidator.com/lite“.

 Nimeni nu vă opreşte să căutaţi şi alte validatoare HTML. Folosiţi motorul de


căutare GOOGLE!

Comentarii în documentul HTML

Un document HTML poate conţine comentarii. Un comentariu arată ca mai


jos şi poate fi aşezat oriunde în document. Evident, comentariile nu sunt afişate de
către browser.
<!-- Un comentariu -->

<!-- Un comentariu
pe mai multe linii -->

 În cazul unor pagini complexe, cu multe elemente, comentariile sunt extrem


de utile pentru realizatorul site-ului. Indicând printr-un comentariu o anumită
porţiune din fişier, el va şti mult mai uşor locaţia codului respectiv pentru a
efectua modificarea.

Prin Internet înţelegem totalitatea calculatoarelor, aflate oriunde în lume,


care comunică între ele. Pentru a comunica ele pot fi conectate printr-una dintre
formele de mai jos:

 cablul telefonic;
 ISDN (Integrated Services Digital Network);
 linii telefonice închiriate;
 cablu TV (coaxial);
 cablu UTP (Unshielded Twisted Pair);
 fibră optică;
 unde electro-magnetice terestre sau prin satelit.
102 Manual de Informatică pentru clasa a XII-a

Pentru ca două sau mai multe calculatoare să poată comunica este necesar
să existe un ”protocol”, adică un ansamblu de norme care trebuie respectate de
către calculatoare (de programale care rulează pe ele) pentru ca schimbul de date
să aibă loc.

Protocolul TCP/IP (Transmission Control Protocol/Internet


Protocol) este numele comun al unei familii de protocoale utilizate pentru
transferul datelor în reţeaua Internet. Dintre acestea, cele mai importante sunt:
 Orice calculator conectat la Internet are o adresă, numită IP, alcătuită din 4
numere între 0 şi 255. Protocolul IP (Internet Protocol) este
răspunzător de transmiterea datelor de la o adresă IP la alta. Datele sunt
transmise divizate în pachete (packets). Fiecare pachet conţine IP-ul
expeditorului şi IP-ul destinatarului.
 Prin protocolul TCP (Transmission Control Protocol) se verifică
corectitudinea transmisiei.
 DNS (Domain Name System) asigură legătura dintre adresa URL a unui
site şi adresa IP a acestuia.
 FTP (File Transfer Protocol) are rolul de a reglementa transferul
fişierelor între două calculatoare.
 SMTP (Simple Mail Transfer Protocol) are rolul de a reglementa
transferul e-mail-urilor.
În cazul site-urilor web folosim următoarea terminologie: calculatorul pe care
se găseşte site-ul se numeşte ”server”, iar calculatoarele care accesează
conţinutul site-ului se numesc ”clienţi”. Acest model de transmisie a datelor se
numeşte “client-server”.
1. Pe calculatorul client trebuie să avem instalat un browser, program cu
ajutorul căruia să putem vizualiza fişiere HTML. Există mai multe programe de tip
browser, cum ar fi: Internet Explorer, Firefox, Mozilla, Opera sau
Netscape. În cazul în care o persoană gestionează un site, aflat evident, pe
sever, atunci aceasta trebuie să dispună pe calculatorul său de un program FTP
prin care să transfere fişiere pe server, şă steargă fişiere aflate pe acesta, să creeze
şi să şteargă folder-e de pe server. În această carte folosim programul ws_ftp95.
2. Pe server trebuie să avem instalat un program specializat care să răspundă
cererilor browser-rului. Un astfel de program se numeşte program de tip server. Cel
mai des utilizat este Apache. Conversaţia între browser şi programul de tip server
respectă protocolul HTTP (Hyper Text Transfer Protocol). De asemenea,
pentru a studia materia din această carte trebuie să avem instalate PHP şi MySQL.
Toate acestea se găsesc în pachetul EasyPHP care trebuie descărcat şi instalat pe
calculatorul nostru.

 Fişierele HTML pot fi scrise cu ajutorul programului NOTEPAD, dar se pot


folosi şi validatoare HTML. Acestea din urmă pot fi descărcate de pe Internet.
Capitolul 3. Primi paşi către construcţia unui site 103

1. Stabiliţi legăturile logice dintre protocoale (stânga) şi ce reglementează ele


(dreapta):

1. DNS a) transfer de fişiere


2. HTTP b) controlul transmisiei
3. TCP c) legătura dintre URL şi IP
4. FTP d) dialogul între client şi server

2. Stabiliţi legătura dintre coloanele din stânga şi cele din dreapta:

1. server a) program FTP


2. client b) Apache

3. Stabiliţi legătura dintre coloanele din stânga şi cele din dreapta:

1. server a) MySQL
2. client b) browser

4. Vizualizaţi codul HTML al unei pagini web aleasă de dvs. Multe puteţi învăţa
privind modul în care au făcut alţii...

5. Creaţi-vă un site gratuit. Reţineţi adresa, numele de autentificare (user ID) şi


parola. Acest site îl veţi utiliza pentru teste.

6. Creaţi un fişier pe hard-disc-ul dvs. un director numit ”PTest”. Folder-ul va


conţine un fişier numit ”index.html”, iar în interiorul fişierului, textul: ”Asteptati
sa invat in capitolul urmator HTML”.

7. Upload-aţi fişierul pe site (adică treceţi fişierul de pe calculatorul dvs. pe server).


Verificaţi operaţia prin afişarea fişierului de către browser.

8. Creaţi pe site-ul dvs. două folder-e: ”Images” şi ”Personal”. În viitor, primul va


reţine fişierele imagine, iar al doilea, fişierele HTML auxiliare.

9. Lucrare de tip referat. Întocmiţi un referat despre un validator HTML.

10. Lucrare de tip referat. Întocmiţi un referat despre un program FTP.

(pentru verificare, rezolvările exerciţiilor 1-3 se găsesc la pag. 383)


CAPITOLUL
HTML, CSS – primele noţiuni

În acest capitol vom învăţa să creăm pagini Web utilizând limbajele


HTML şi CSS, esenţiale în dezvoltarea oricărei aplicaţii hipermedia.

 Care este structura de bază a unei pagini HTML+CSS ?


 Elemente HTML pentru afişarea textelor
 Atribute CSS pentru font-uri şi texte
 Cum realizăm o listă ?
 Care este structura unui element HTML ?
 Atribute de culoare şi fond
 Atribute pentru margini, padding şi bordură
 Cum introducem o imagine ?
 Dar un tabel ?
 Hiperlegături (link-uri)
 Hărţi imagine
 Ce rol au elementele BASE, META, SCRIPT ?
 Ce sunt cadrele ? La ce folosesc ?
 Care sunt modalităţile de aşezare în pagină a elementelor ?
 Caractere HTML
 Aspecte generale ale proiectării interfeţelor web

Cuvinte cheie: HTML, CSS, element, tag, atribut, id, class, stil,
listă, tabel, hiperlegătură, download, hartă imagine, cadru,
bordură, margine, ţesătură, etichetă, proiectare
Capitolul 4 – HTML, CSS - primele noţiuni 105

În cele ce urmează vom învăţa să creăm pagini web utilizând limbajul HTML.
Pentru aceasta, vom recapitula cunoştinţele dobândite la orele de “Tehnologia
Informaţiei şi a Comunicării”, dar vom învăţa si multe lucruri noi. Desigur, o pagină
astfel creată, poate arăta foarte bine, dar, din păcate, lucrând numai cu HTML-ul,
textele şi imaginile nu pot fi personalizate pe cât am dori, iar tehnicile prin care
putem crea animaţie aproape că lipsesc. De asemenea, server-ul oferă vizitatorului
o pagină care nu ţine cont şi de preferinţele acestuia şi nu-i oferă posibilitatea să
“scrie” date pe site. Cu toate acestea, pentru a crea pagini web, studiul limbajului
HTML este indispensabil, iar neajunsurile arătate pot fi eliminate studiind acest
capitol.

4.1. Structura de bază a unei pagini HTML+CSS

Mai jos, puteţi observa o pagină aşa cum este scrisă în Notepad şi aşa cum
este afişată de browser-ul Internet Explorer:

a) În Notepad b) În Internet Explorer

Figura 4.1. Exemplu de pagină web

Din analiza exemplului de mai sus, observăm că:

• pagina începe cu tag -ul <HTML> şi se termină cu tag-ul </HTML>;


1

• pagina conţine un antet (HEAD) şi corpul propriu-zis (BODY);


• antetul este cuprins între etichetele <HEAD> şi </HEAD>;
• corpul este conţinut între etichetele <BODY> şi </BODY>.

 Opţional, antetul poate conţine titlul paginii cuprins între tag-urile <TITLE> şi
</TITLE>. Titlul apare pe bara de titlu a ferestrei afişată de Explorer
(pentru noi, acesta este "Exemplul 1").

Termenul tag provine din limba engleză şi semnifică “etichetă”. În acest manual vom folosi
1

ambii termeni: element si tag.


106 Manual de Informatică pentru clasa a XII-a

Dvs. aţi studiat câteva noţiuni despre HTML în clasa a-IX-a. Acum trebuie
să le recapitulăm, dar şi să le prezentăm într-o formă nouă, utilizând limbajul CSS
(Cascading Style Sheets), limbaj recunoscut de către browser.

Conform CSS, vom imagina elementele HTML ca având formă


dreptungiulară. Pentru fiecare element HTML se poate selecta dimensiunea lui,
culoarea, mărimea şi stilul de scriere a font-ului, culoarea de fond, culorile
marginilor... şi, după cum vom vedea, chiar poziţia în document. A stabili toate
acestea pentru un element sau pentru toate elementele de acelaşi tip (de exemplu,
toate paragrafele) înseamnă a stabili un stil. Un fişier HTML + CSS poate conţine
mai multe stiluri. Modul în care se stabilesc stilurile va fi tratat în amănunt,
deocamdată ne mărginim să exemplificăm modul în care se pot preciza stilurile
într-un fişier HTML.

A) Prin utilizarea elementului <STYLE>...</STYLE>, care va fi conţinut de antet. În


interiorul său se pot descrie stiluri pentru un grup de elemente, de exemplu P,
pentru paragrafe sau pentru un singur element de un tip oarecare.

A1. Toate elementele de un anumit tip au acelaşi stil.

Exemplul 4.1. Paragraful are înălţimea de 4 cm, lăţimea de 3 cm, font-ul cu


mărimea de 20 de puncte, culoarea de fond - galben, culoarea textului - roşu, iar
scrisul italic. Oricâte paragrafe ar conţine documentul, toate vor avea acelaşi stil.

<HTML>
<HEAD>
<STYLE>
P {font-size:20pt; color:Red;
background:yellow; font-style:italic;
width:3cm; height:4 cm;}
</STYLE>
</HEAD>
<BODY>
<P> Acesta este primul exemplu de
pagina...</P>
</BODY>
</HTML>
Figura 2.2. Pagina rezultată
pentru Exemplul 4.1.

A2. Stilul este aplicat unui element, care este identificat prin intermediul atributului
id al acestuia.

Exemplul 4.2. Formăm un stil cu numele ”P1”. Elementul care va avea acest stil va
trebui să conţină atributul id care să aibă valoarea ”P1”. Observaţi că, în exemplu,
sunt două paragrafe. Numai unul dintre ele are asociat un stil, celalat se scrie aşa
cum am văzut deja…
Capitolul 4 – HTML, CSS - primele noţiuni 107

<HTML>
<HEAD>
<STYLE>
#P1 {font-size:20pt; color:red;
background:YELLOW; font-style:italic;
width:3cm; height:4 cm;}
</STYLE>
</HEAD>
<BODY>
<P id="P1"> Un paragraf care are
atasat un stil </P>
<P> alt paragraf </P>
</BODY>
</HTML> Figura 4.3. Pagina rezultată
pentru Exemplul 4.2.

A3. Stilul este aplicat unui element sau mai multor elemente, care sunt identificate
prin intermediul atributului class.

Exemplul 4.3. Se descrie clasa ”Stil”, iar efectul este cel din exemplul anterior:

<HTML>
<HEAD>
<STYLE>
.Stil {font-size:20pt; color:red;
background:yellow;
font-style:italic;
width=3cm; height:4 cm;}
</STYLE>
</HEAD>
<BODY>
<P class="Stil"> Un paragraf care are atasat un stil </P>
<P> alt paragraf </P>
</BODY>
</HTML>

Important ! Există posibilitatea ca stilurile să fie memorate într-un fişier text (creat,
de exemplu, cu programul Notepad), cu extensia ”.css”. Codul HTML îl va apela
utilizând tag-ul LINK.

Elementul LINK reprezintă o modalitate prin care definim legătura între cele
două fişiere (css şi html). Acesta are următoarele atribute:

rel - defineşte tipul de fişier css;


type - indică browser-ului în ce limbaj este scris codul;
href - se specifică locaţia fişierului (dacă fişierul css nu se găseşte în
aceiaşi locaţie cu cel html, se scrie adresa completă a sa).
108 Manual de Informatică pentru clasa a XII-a

Exemplul 4.4. Reluând exemplul anterior, formăm un fişier text cu numele


”unstil.css”, care va conţine definiţia stilului:

.Stil {font-size:20pt;
color:red;
background:yellow;
font-style:italic;
width=3cm;
height:4 cm;}

În aceste condiţii, fişierul HTML devine:

<HTML>
<HEAD>
<LINK rel="stylesheet" type="text/css" href="unstil.css">
</HEAD>
<BODY>
<P class="Stil"> Un paragraf care are atasat un stil </P>
<P> alt paragraf </P>
</BODY>
</HTML>

B) Există posibilitatea să scriem un stil pentru un anumit element, prin utilizarea


atributului style. Cu ajutorul acestui atribut, putem defini ad-hoc orice stil.

Exemplul 4.5. Testaţi codul sursă de mai jos:

<HTML>
<HEAD>
</HEAD>
<BODY>
<P style="font-size:20pt; color:Red; background:yellow;
font-style:italic; width=3cm; height:4cm;">
Un paragraf care are
atasat un stil </P>
<P> alt paragraf </P>
</BODY>
</HTML>

Din cele prezentate, rezultă că un element HTML are atributele: id, class şi
style, iar acestea pot fi utilizate în funcţie de necesitate.
Capitolul 4 – HTML, CSS - primele noţiuni 109

4.2. Elemente HTML pentru afişarea textelor

Elementul P – are rolul de a permite introducerea unui paragraf. Pentru a-l


folosi, utilizăm tag-urile:
<P atribute> conţinut paragraf </P>

Observaţii !

 Atunci când sunt afişate, paragrafele sunt separate printr-o linie vidă.
 Tag-ul </P> poate să lipsească, nu este obligatoriu! Un nou paragraf poate
fi depistat prin tag-ul <P>.

 În Notepad, WordPad sau Word, paragrafele se separă prin tastarea unui


Enter. În schimb, în HTML, Enter-ul nu are nici un efect. Vedeţi în
exemplul anterior, al doilea paragraf (aşa cum a fost tastat în Notepad). El
conţine un Enter (de fapt, în Notepad, sunt două paragrafe). Acesta a fost
ignorat de Explorer.

 Fără o altă comandă, un rând al unui paragraf are lăţimea ferestrei afişată
de browser. De exemplu, dacă micşorăm fereastra browser-ului, acelaşi
paragraf va ocupa mai multe rânduri.

 Dacă două cuvinte ale unui paragraf sunt separate prin mai multe spaţii,
browser-ul afişează doar un singur spaţiu.

Elementul &nbsp

Câteodată, avem nevoie să prevenim trecerea unui cuvânt pe linia


următoare. Folosim elementul &nbsp pentru a evita acest lucru, prin scrierea sa
înaintea cuvântului de interes. În cazul în care nu încape pe linie, se coboară şi
cuvântul precedent pe linia următoare.

Exemplul 4.6. Testaţi forma de mai jos:

<P>Acest paragraf a fost afisat


de Internet&nbspExplorer.</P>

În figura alăturată se observă faptul că


browser-ul a fost forţat să treacă cuvântul
”Internet” pe rândul următor.

Figura 4.4. Exemplu de utilizare


a elementului &nbsp
110 Manual de Informatică pentru clasa a XII-a

În continuare, vom prezenta cele mai importante elemente de formatare


ale textului.

Elementul BR - are ca efect forţarea afişării a ceea ce urmează pe rândul


următor. Pentru a-l utiliza, se foloseşte un singur tag: <BR>.

Exemplul 4.7. Paragraful următor este afişat pe


două rânduri:
<P> Mama merge <BR> la piata </P>

Figura 4.5. Exemplu de utilizare


a elementului <BR>

 Tag-ul <BR> nu creează un alt paragraf. Nu uitaţi, între două paragrafe se


lasă o linie vidă. În cazul etichetei <BR>, rândul următor nu este separat de
rândul curent prin linie vidă.

Elementul B - are rolul de a determina browser-ul să afişeze îngroşat (bold)


textul cuprins între cele două tag-uri ale sale: <B> şi </B>.

Exemplul 4.8. Cuvintele ”trebuie” şi ”ai” sunt afişate îngroşat:

<P> Ceea ce-ti <B>trebuie</B> vei gasi in ceea


ce <B>ai</B>! </P>

Figura 4.6. Exemplu de utilizare


a elementului <B>

Elementul I - are rolul de a determina browser-ul să afişeze înclinat (italic) textul


cuprins între cele două tag-uri ale sale: <I> şi </I>.

Exemplul 4.9. Cuvintele ”trebuie” şi ”ai” sunt afişate înclinat:

<P> Ceea ce-ti <I>trebuie</I> vei gasi in ceea


ce <I>ai</I>! </P>

Figura 4.7. Exemplu de utilizare


a elementului <I>
Capitolul 4 – HTML, CSS - primele noţiuni 111

Elementul U - are rolul de a determina browser-ul să afişeze subliniat textul


cuprins între cele două tag-uri ale sale: <U> şi </U>.

Exemplul 4.10. Cuvintele ”trebuie” şi ”ai” sunt afişate subliniat:

<P> Ceea ce-ti <U>trebuie</U> vei gasi in ceea


ce <U>ai</U>! </P>

Figura 4.8. Exemplu de utilizare


a elementului <U>

Elementul S - are rolul de a determina browser-ul să afişeze tăiat textul cuprins


între cele două tag-uri ale sale: <S> şi </S>.

Exemplul 4.11. Cuvintele ”trebuie” şi ”ai” sunt afişate tăiat:

<P> Ceea ce-ti <S>trebuie</S> vei gasi in ceea


ce <S>ai</S>! </P>

Figura 4.9. Exemplu de utilizare


a elementului <S>

Elementul BIG - are rolul de a comanda browser-ului ca textul cuprins între


tag-urile <BIG> şi </BIG> să fie scris mai mare decât restul textului.

Exemplul 4.12. Textul ”elementul BIG” este scris mărit:

<P>Un paragraf care foloseste <BIG>elementul BIG</BIG> !</P>

Figura 4.10. Exemplu


de utilizare a
elementului <BIG>

Atenţie ! Elementul BIG nu este suportat de toate browser-ele, deci este de


preferat utilizarea tag-ului FONT. De exemplu:

<P>Exemplu de <FONT size="+1">text marit</FONT> !</P>


112 Manual de Informatică pentru clasa a XII-a

Elementul SMALL - are rolul de a comanda browser-ului ca textul cuprins între


tag-urile <SMALL> şi </SMALL> să fie scris mai mic decât restul textului.

Exemplul 4.13. Textul ”elementul SMALL” este scris micşorat:

<P>Un paragraf care foloseste


<SMALL>elementul SMALL</SMALL> !</P>

Figura 4.11. Exemplu


de utilizare a
elementului <SMALL>

Elementul TT - are rolul de a comanda browser-ului ca textul cuprins între


tag-urile <TT> şi </TT> să fie scris monospaţiat (adică toate caracterele ocupă
aceeaşi lungime de spaţiu, precum font-ul ”Courier New”).

Exemplul 4.14. Textul ”elementul TT” este scris monospaţiat:

<P>Un paragraf care foloseste <TT>elementul TT</TT> !</P>

Figura 4.12. Exemplu


de utilizare a
elementului <TT>

Elementul DEL - are rolul de a comanda browser-ului ca textul cuprins între


tag-urile <DEL> şi </DEL> să fie scris tăiat, pentru a arăta că a fost şters
(păstrându-l, totuşi, în document pentru a nu mai antrena şi alte modificări
ale acestuia).

Exemplul 4.15. Textul ”elementul DEL” este scris tăiat:

<P>Un paragraf care foloseste <DEL>elementul DEL</DEL> !</P>

Figura 4.13. Exemplu


de utilizare a
elementului <DEL>

Elementul SUP - are rolul de a comanda browser-ului ca textul cuprins între


tag-urile <SUP> şi </SUP> să fie scris mai sus (ca o putere, exponent).
Capitolul 4 – HTML, CSS - primele noţiuni 113

Exemplul 4.16. Textul ”x*ln(x)” este scris ca o putere:

<P> 3<SUP>x*ln(x)</SUP> </P>

Figura 4.14. Exemplu de utilizare a


elementului <SUP>

Elementul SUB - are rolul de a comanda browser-ului ca textul cuprins între


tag-urile <SUB> şi </SUB> să fie scris mai jos (ca un indice).

Exemplul 4.17. Textul ”i,j” este scris ca un indice:

<P> a<SUB>i,j</SUB> </P>

Figura 4.15. Exemplu de utilizare a


elementului <SUB>

Elementele H1, H2, ..., H6


Pentru scrierea titlurilor se utilizează elementele H1, H2, ..., H6. Fiecare titlu
este scris între tag-urile:
<H1> </H1>, <H2> </H2>, …, <H6> </H6>.

Mărimea diferă: pentru <H1> titlul este scris utilizând font-ul de dimensiune
maximă, iar pentru <H6> dimensiunea este minimă.

Exemplul 4.18. Mai jos, observaţi


cum este scris un titlu:
<H1>Despre lenesi...</H1>
<P>Lenesul gaseste in orice
sarbatoare un prilej sa nu
munceasca !</P>

Figura 4.16. Exemplu de utilizare a


elementului <H1>

Atenţie !

 Titlurile trebuie să fie folosite în ordine ierarhică.


 În general, un document HTML trebuie să aibă exact un element H1, pentru a
indica titlul principal al paginii.
 Motoarele de căutare pot utiliza informaţiile din aceste titluri, deci ele trebuie
să sintetizeze cât mai bine conţinutul textului.
114 Manual de Informatică pentru clasa a XII-a

4.3. Atribute CSS pentru font-uri

În continuare vor fi prezentate principalele atribute CSS care pot fi utilizate,


în cadrul unui stil, pentru a personaliza fontul cu care se va afişa textul.

A) font-style – poate lua valorile:

normal italic

B) font-variant – poate lua valorile:

normal small-caps
C) font-weight – poate lua valorile:

normal bold

100 900

D) font-size – mărimea. Există mai multe modalităţi de a indica dimensiunea


font-ului. Cea mai simplă este de a o indica în puncte:

10pt 15pt 20pt


E) font – grupează primele patru atribute, deci dacă îl folosim putem renunţa la
acestea. Nu contează ordinea în care sunt scrise...

Exemplul 4.19. Mai jos, am descris un stil pentru


paragrafe care are ca rezultat pagina din Figura 4.17:
<HTML>
<HEAD>
<STYLE>
P { font:italic bold 15pt; }
</STYLE>
Figura 4.17. Exemplu de
</HEAD>
paragraf personalizat cu
<BODY> <P>Un exemplu...</P> </BODY> ajutorul atributului font
</HTML>
Capitolul 4 – HTML, CSS - primele noţiuni 115

F) font-family – are rolul de a stabili o familie de font-uri cu care vor fi afişate


textele. Vă daţi seama că nu se poate şti dacă cel care vizitează pagina are pe
calculatorul său instalat sau nu un anumit font. Din acest motiv se trec, în ordine,
familiile de font-uri care vor fi utilizate. La vizualizarea documentului, se verifică
dacă există un font din prima familie. În caz afirmativ, se afişează textul cu un font
din prima familie. Dacă un astfel de font nu există, se caută dacă există un font din
a doua familie, ş.a.m.d.
Exemple de valori: times, courier, arial, etc.

Este recomandabil ca ultima valoare din listă să fie una dintre valorile de mai
jos. Ele nu specifică o familie de font-uri, ci mai degrabă un stil de scriere. El va fi
folosit atunci când nici una din familiile de font-uri nu a fost găsită, caz în care
browser-ul caută un font apropiat de ultima valoare:

serif sans-serif

cursive monospace

Exemplul 4.20. Analizaţi stilul de mai jos:


P { font-size:20pt;
font-family:courier, monospace; }

4.4. Atribute CSS pentru texte

Limbajul CSS permite stilizarea la nivel de text prin intermediul unor atribute
care sunt detaliate în cele ce urmează.

A) text-decoration – poate lua valorile: underline (cu o linie sub el),


overline (cu o linie peste el), line-through (taiat în interior) şi none (fără
nicio linie, clasic).

underline overline

line-through none
116 Manual de Informatică pentru clasa a XII-a

Exemplul 4.21. Putem să folosim şi combinaţii între aceste variante, precum cea
de mai jos. Efectul poate fi observat în Figura 4.18.
<HTML>
<HEAD>
<STYLE>
P {text-decoration: underline overline;}
</STYLE>
</HEAD>
<BODY>
<P>Un exemplu ...</P> Figura 4.18. Exemplu de
paragraf personalizat cu
</BODY>
atributul text-decoration
</HTML>

B) text-align – alinierea textului – poate lua valorile de mai jos:

left right

center justify

Figura 4.19. Exemple de aliniere a textului

C) text-indent – este folosit pentru indentarea textelor. Primul rând al


textului va începe mai în dreapta cu o valoare precizată.

Exemplul 4.22. Pentru a obţine indentarea din figura alăturată, am folosit stilul de
mai jos:
P {text-indent:1cm;}

Figura 4.20. Exemplu de indentare


aplicată unui paragraf
Capitolul 4 – HTML, CSS - primele noţiuni 117

D) line-height - înălţimea liniei – atributul este folosit pentru a stabili distanţa


dintre rândurile unui paragraf.

Exemplul 4.23. Am format două stiluri pe care le-am aplicat apoi celor două
paragrafe (vezi Figura 4.21):
<HTML>
<HEAD>
<STYLE>
#unu {font-size: 15pt; line-height: 0.5cm;}
#doi {font-size: 15pt; line-height: 1cm;}
</STYLE>
</HEAD>
<BODY>
<P id="unu">Acest text a fost scris pentru a exemplifica
spatierea intre randuri.</P>
<P id="doi">Acest text a fost scris pentru a exemplifica
spatierea intre randuri.</P>
</BODY>
</HTML>

Figura 4.21. Exemple de


paragrafe cu linii de
înălţime diferită

4.5. Liste
În HTML, există posibilitatea ca anumite enunţuri să fie numerotate sau
marcate într-un anumit fel. O astfel de organizare poartă denumirea de listă.

Astfel, în HTML se pot descrie trei tipuri de liste:

 liste ordonate, în care elementele sunt numerotate;


 liste neordonate, în care elementele sunt marcate de aşa natură încât
nu se sugerează o anumită ordine a lor;
 liste de tip definiţie.

În continuare, puteţi observa un exemplu pentru fiecare tip de listă:


118 Manual de Informatică pentru clasa a XII-a

1. Bloc • Bloc Bloc


2. Vila • Vila Multe etaje, zeci de familii
3. Casa • Casa Vila
Unu sau doua etaje, cel mult 5 familii
Casa
N-are etaje, o familie
a) Listă ordonată; b) Listă neordonată; c) Listă de tip definiţie.

Pentru a forma astfel de liste, avem nevoie de câteva elemente HTML care
vor fi detaliate în cele ce urmează.

Elementul OL (Ordered Lists) - creează o listă ordonată. Elementele listei


sunt trecute între tag-urile <OL> şi </OL>.

Elementul LI (List Item) - descrie un element al listei. Tag-ul obligatoriu este


cel de început <LI>, cel de sfârşit fiind facultativ: </LI>.

Exemplul 4.24. Priviţi lista ordonată de mai jos:


<P>Cine nu ... nu castiga!</P>
<OL>
<LI> pierde
<LI> risca
<LI> ajunge
</OL>

Figura 4.22. Exemplu


de listă ordonată

⇒ Elementul OL are atributul ”type”. Valorile pe care le poate lua acest atribut,
precum şi modul în care arată lista, se pot observa în continuare:

a. pierde i. pierde 1. pierde


b. risca ii. risca 2. risca
c. ajunge iii. ajunge 3. ajunge
<OL tyle="a"> <OL tyle="i"> <OL tyle="1">

A. pierde I. pierde
B. risca II. risca
C. ajunge III. ajunge
<OL tyle="A"> <OL tyle="I">
Capitolul 4 – HTML, CSS - primele noţiuni 119

Elementul UL (Unordered Lists) - descrie o listă neordonată. Elementele


listei sunt cuprinse între tag-urile <UL> şi </UL>.

Exemplul 4.25. Priviţi lista neordonată de mai jos:


<P>Periferice esentiale:</P>
<UL>
<LI> monitor
<LI> tastatura
<LI> mouse
</UL>
Figura 4.23. Exemplu
de listă neordonată

⇒ Elementul UL are atributul type. Valorile pe care le poate lua acest atribut,
precum şi modul în care arată lista se observă în continuare:

<UL type="circle"> <UL type="square"> <UL type="disc">

Observaţii !

 Desigur, putem construi liste imbricate, aşa cum se poate observa cu


uşurinţă din exemplul următor:

Exemplul 4.26. Analizaţi lista de mai jos:


<P><U>Echipa castigatoare:</U></P>
<UL type="square">
<LI>Jucatori:
<OL type="1">
<LI> George
<LI> Lavinia
<LI> Mihai
</OL>
<LI>Rezerve:
<OL type="1">
<LI> Cristian
<LI> Flavius
</OL>
</UL> Figura 4.24. Exemplu
de liste imbricate

 Pentru a lăsa un rând liber, putem marca un paragraf prin <P> </P> sau...
numai prin <P>.
120 Manual de Informatică pentru clasa a XII-a

Elementul DL (Definition Lists) - are rolul de a descrie o listă de definiţii,


delimitată de tag-urile <DL> şi </DL>.

Elementul DT (Definition Term) - defineşte termenul din listă care trebuie


descris. Se utilizează tag-ul <DT>.

Elementul DD (Definition Description) - are rolul de a reţine descrierea


termenului. Se utilizează tag-ul <DD>.

Exemplul 4.27. Priviţi lista de definiţii de mai jos:


<DL>
<DT>to elapse <DD>a trece, a se scurge
<DT>I've never seen <DD> n-am (mai) vazut (niciodata)
</DL>

Figura 4.25. Exemplu


de listă de definiţii

4.6. Structura unui element HTML


În general, un element HTML, P, OL, H6, etc. este alcătuit sub formă de cutie
(box), cu structura următoare:

Conţinut

Ţesătură (padding)

Bordură (border)

Margine (margin)

Figura 4.26. Structura unui element HTML


Capitolul 4 – HTML, CSS - primele noţiuni 121

 Marginea (margin) – nu este vizibilă de vizitatorul paginii. Rostul ei este de


a păstra distanţa dintre cutie şi celelalte elemente.

 Bordura (border) – în cazul în care creatorul paginii doreşte, aceasta


poate fi făcută vizibilă (de exemplu i se stabileşte o altă culoare).

 “Ţesătura” (padding) poate fi dimensionată, dar nu poate fi făcută vizibilă


printr-o culoare distinctă. Vom prefera termenul de padding.

 Conţinutul este dat de text şi/sau imagine.

Observaţii !

 În ansamblu, părţile unor elemente de acelaşi tip pot fi dimensionate. Vedeţi


paragrafele următoare!

 În general, pentru majoritatea elementelor se poate trece spaţiul ocupat de


acestea: lăţimea (width) şi înălţimea (height). Înălţimea şi lăţimea cutiei
include bordura, dar nu include marginile. În cazul în care conţinutul nu
încape în cutie, nu se respectă înălţimea şi lăţimea dată de aceste atribute.

În continuare, vom da exemple de elemente pentru care a fost scris un stil. În


acest mod, vă puteţi face de la început o idee despre puterea limbajului CSS. De
multe ori, putem face ca un element să arate cu totul altfel decât arată în forma
implicită. În paragrafele următoare vor fi prezentate toate atributele, dar acum, vă
prezentăm câteva elemente HTML cu înfăţişare “neobişnuită”.

Exemplul 4.28. Am creat un stil pentru un element H1. Bordura are culoare
distinctă, iar textul este aliniat la stânga. Faptul că există un spaţiu între bordură şi
text confirmă existenţa padding-ului (de 0.5 cm).

H1 {border:solid 10pt red;


background-color:green;
padding:0.5cm 0.5cm 0.5cm 0.5cm;
text-align:left; width:3cm;}
...
<H1>Un element H1</H1>
Figura 4.27. Exemplu
de element H1 stilizat

Exemplul 4.29. Am creat un stil pentru paragrafe. În acest


caz, bordura are o formă specială. Fontul utilizat este din
famila "Arial", scris îngroşat (bold) şi înclinat (italic).
Textul este aliniat la centru (center):

Figura 4.28. Exemplu


de paragraf stilizat
122 Manual de Informatică pentru clasa a XII-a

P {border:groove 1cm red;


background-color:yellow;
padding: 1cm 1cm 1cm 1cm;
width:5cm; height:5cm;
text-align:right;
font-family:arial;
font-weight:bold;
font-style:italic;}
...
<P> Un exemplu de paragraf </P>

Exemplul 4.30. O listă pentru care s-a stabilit dimensiunea font-ului, culoarea de
fond, culoarea, etc.:
OL {font-size:20pt;
font-weight:bold;
color:black;
background-color:blue;}
...
<OL>
<LI> masina
<LI> bicicleta
</OL>
Figura 4.29. Exemplu
de listă stilizată

4.7. Atribute de culoare şi fond

În general, o culoare poate fi recunoscută prin numele ei ("red", "green",


"gray", ...) sau prin valorile RGB (Red, Green, Blue). Puteţi alege culoarea în
Paint (opţiunea Edit Colors), după care treceţi valorile în HTML. Este de preferat
a doua variantă, pentru că prima este depreciată conform noilor standarde HTML.

A) color – specifică culoarea textului.

Exemplul 4.31. Mai jos, am setat o culoare pentru textul paragrafelor:

P {font-size:40pt;
color:RGB(12,56,23);}

Observaţie ! Background-ul acoperă suprafaţa conţinutului şi a padding-ului.

B) background-image – pentru fundal se poate folosi chiar şi o imagine. Dacă


imaginea este mai mică decât suprafaţa care trebuie afişată, atunci ea este
multiplicată astfel încât să acopere întreaga suprafaţă.
Capitolul 4 – HTML, CSS - primele noţiuni 123

Exemplul 4.32. Se stabileşte imaginea ca fundal pentru întreg documentul (body).


De asemenea, paragrafele vor avea textul de culoare albă, de 40 de puncte.
<HTTML>
<HEAD>
<STYLE>
P {font-size:40pt; color:RGB(255,255,255);}
body {background-image:url(c:\Catelus\1.jpg);}
</STYLE>
</HEAD>
<BODY>
<P> Un exemplu
de catelus </P>
</BODY>
</HTML>
Figura 4.30. Exemplu
de pagină cu o imagine
pe fundal

C) background-color – stabileşte culoarea fundalului. Uneori este trecut şi în


cazul în care pe fundal avem o imagine, pentru că este posibil ca, dintr-un motiv
sau altul, imaginea să nu apară.

Exemplul 4.33. Paragrafele se scriu cu alb, pe fond roşu:


P {font-size:12pt;
color:RGB(255,255,255);
background-color:RGB(255,0,0);}
sau
P {font-size:12pt; color:white;
background-color:red;}
Figura 4.31. Un paragraf
cu fundalul roşu şi textul alb
Exemplul 4.34. Pentru body se alege o imagine pentru fundal, iar dacă aceasta
nu apare, ca măsură de siguranţă, s-a ales culoarea neagră:
body {background-image:url(c:\Catelus\1.jpg);
background-color:black;}

D) background-repeat – am văzut faptul că, dacă o imagine este mai mică


decât spaţiul necesar pentru un element, atunci aceasta se repetă atât pe
orizontală cât şi pe verticală până când se umple acest spaţiu.
Există posibilitatea să controlăm această repetare prin valorile pe care le
ataşăm acestui atribut:
 repeat – repetarea se face atât pe orizontală cât şi pe verticală;
 repeat-x – repetarea se face numai pe orizontală;
 repeat-y – repetarea se face numai pe verticală;
 no-repeat – imaginea nu se repetă.
124 Manual de Informatică pentru clasa a XII-a

E) background-attachment – poate lua două valori: fixed şi scroll


(valoare implicită). În cazul în care pe fundal se găseşte o imagine, efectul este
deosebit. Dacă valoarea este fixed, atunci defilează numai obiectele care se
găsesc pe fundal (imaginea rămânând fixă), iar dacă valoarea este scroll, atunci
defilează şi imaginea.

Exemplul 4.35. Analizaţi paginile de mai jos:

body {background-repeat:fixed;}

body {background-repeat:scroll;}

Figura 4.32. Exemple de pagini cu fundal fix sau mobil

F) background-position – dacă pe fundal se afişează o imagine, atunci i se


poate preciza poziţia în raport cu fereastra. Există mai multe posibilităţi de
precizare a poziţiei:
 procentual: de exemplu, 33% 50% (la 1/3 de partea stângă a ferestrei şi la
1/2 din înălţimea ei);
 în valori absolute: de exemplu, 2cm 3cm (la 2 cm de partea stângă a
ferestrei şi la 3 cm de partea de sus);
 mixt: de exemplu, 2cm 50% (la 2 cm de partea stângă a ferestrei şi la
jumătate raportat la înălţime);
 numai o valoare – caz în care se referă numai la alinierea pe orizontală în
raport cu marginea din stânga a ferestrei;
 prin cuvinte cheie: left (stânga), right (dreapta), top (sus) şi bottom
(jos) – de exemplu:
body {background-position: left bottom;} (în stânga-jos).
Exemplul 2.36. Mai jos, a fost creat un stil care defineşte o singură imagine pe
fundal, la mijlocul ferestrei, care nu defilează (rămâne fixă):
body {background-image: url(c:\Catelus\1.jpg);
background-repeat: no-repeat;
background-position: 50% 50%;
background-attachment: fixed;}
G) background – o singură caracteristică pentru toate celelalte. Se trec, în
ordine, toate valorile pentru background-image, background-repeat, ...
Capitolul 4 – HTML, CSS - primele noţiuni 125

4.8. Atribute pentru margini

Fiecare element poate avea margini. Rolul lor este de a o separa de alte
elemente. Iată cum se pot stabili marginile:
A) Margin-left – mărimea marginii din stânga;
B) Margin-right – mărimea marginii din dreapta;
C) Margin-top – mărimea marginii de deasupra;
D) Margin-bottom – mărimea marginii de dedesupt;
E) Margin – toate marginile în ordinea: sus, drepta, jos şi stânga.

Exemplul 4.37. Pentru elementele de tip paragraf, a fost realizat un stil care
defineşte marginile acestuia (fereastra este micşrată, pentru a evidenţia marginile):
P {font-size:15pt;
margin-left:1cm;
margin-right:2cm; top
margin-top:3cm;}

Figura 4.33. Un paragraf left right


cu margini modificate

4.9. Atribute pentru padding


Padding-ul poate fi doar dimensionat, dar nu i se poate aplica o culoare
distinctă: Padding-top – partea de sus; Padding-left – partea din stânga;
Padding-bottom – partea de jos; Padding-right – partea din dreapta;
Padding - toate marginile, în ordinea: sus, dreapta, jos şi stânga.

4.10. Atribute pentru bordură


Mai întâi, putem stabili dimensiunile bordurii: Border-top-width – partea
de sus, Border-left-width – partea din stânga, Border-bottom-width –
partea de jos şi Border-right-width – partea din dreapta.

Border-width – le înlocuieşte pe primele 4. Se trec valorile în ordinea: sus,


dreapta, jos şi stânga. Dacă se trece o singură valoare, aceasta va fi ataşată
tuturor marginilor.
126 Manual de Informatică pentru clasa a XII-a

Observaţie ! Pentru grosimea bordurii se mai pot folosi valorile: thin (subţire),
medium (medie) sau thick (groasă).

Border-color – culoarea bordurii. Se pot folosi maximum 4 culori, în ordinea:


sus, dreapta, jos şi stânga. Dacă se trece o singură culoare, aceasta va fi ataşată
tuturor marginilor.
Border-style – se trece în mod obligatoriu. Contrar, bordura nu este vizibilă.
Valorile mai importante pe care le poate lua acest parametru se pot observa în
figura de mai jos:

solid double groove

ridge inset outset


Figura 4.34. Diverse tipuri de borduri

Border-top-style – stilul bordurii în partea de sus;


Border-right-style – stilul bordurii în partea dreaptă;
Border-bottom-style – stilul bordurii în partea de jos;
Border-left-style – stilul bordurii în partea stângă.

4.11. Elementul IMG

Ce farmec are o pagină dacă nu conţine una sau mai multe imagini?

Elementul IMG - se utilizează pentru a ataşa unei pagini o imagine. Vom folosi
tag-ul <IMG>. Forma generală a acestui element este: <IMG atribute>.

Atributele lui sunt:

⇒ src - identifică fişierul care conţine imaginea respectivă (poate fi de tipul:


jpg, gif, etc.).
Capitolul 4 – HTML, CSS - primele noţiuni 127

Observaţie ! În această etapă învăţăm să creăm paginile pe propriul calculator,


fără a fi conectaţi la Internet. Prin urmare, fişierul care conţine imaginea se va găsi
într-un folder oarecare (în exemplul următor, el se găseşte în acelaşi folder în care
găsim şi fişierul cu extensia htm (cel care conţine pagina). Din acest motiv, sursa
nu conţine şi calea, dar, dacă este cazul, calea poate fi introdusă.

⇒ ALT="nume" – există posibilitatea ca imaginea să nu se poată încărca.


Pentru astfel de situaţii este folosit parametrul ALT, unde nume conţine un
text (alternativ) care va fi afişat în locul imaginii.

Exemplul 4.38. Fie tag-ul IMG următor:


<IMG src="C:/Eric.jpg", alt="Eric">
Dacă imaginea este găsită, se face afişarea ca în figura din
dreapta, altfel se afişează ce se vede mai jos:

Figura 4.35
Figura 4.36. Exemplu de pagină
care conţine o imagine

Exerciţiu ! Luaţi o imagine oarecare şi faceţi diverse exerciţii de afişare a ei,


utilizând cunoştinţele de CSS prezentate în paragrafele 4.7, 4.8 şi 4.9. Spre
exemplu, analizaţi codul de mai jos (vezi şi Figura 4.37):
<HTML>
<HEAD>
<STYLE> IMG {width:3cm; height:4cm;}</STYLE>
</HEAD>
<BODY>
<P> Acest paragraf este scris pentru a verifica modul de
aliniere pe orizontala in cazul unui element IMG, care este
de tip INLINE
<IMG src="Eric.jpg",
alt="Eric">, deci se
insereaza exact ca
un cuvant intr-un
paragraf</P>
<P> Paragraful este un
element de tip BLOC,
asa ca se insereaza
pe o linie noua!
</BODY>
</HTML>

Figura 4.37. Exemplu


de pagină web
128 Manual de Informatică pentru clasa a XII-a

4.12. Tabele

În cadrul unei pagini web se pot introduce şi tabele, extrem de utile pentru
evidenţierea unor date sau, pur şi simplu, pentru a delimita spaţiul paginii. Desigur,
tabelul rezultat poate fi privit în mod clasic, cu linii şi coloane, aşa cum suntem
obişnuiţi, dar poate fi folosit şi în alte scopuri, cum ar fi: aliniarea imaginilor
(elemente de tip IMG în raport cu textul) sau scrierea în coloane. Din acest motiv,
în sens larg, prin tabel vom înţelege o grupare în linii şi coloane a mai multor
elemente HTML.

Elementul TABLE - descrie un tabel, utilizând etichetele:


<TABLE> şi </TABLE>.

Elementul TR - descrie o linie a tabelului, care începe cu <TR> şi se termină


atunci când este întâlnit un nou <TR>. Opţional, se poate folosi şi tag-ul </TR>
pentru a închide linia curentă.

Elemenul TD - descrie o celulă a tabelului. Se utilizează tag-urile <TD> şi,


opţional, </TD>.

Exemplul 4.39. Mai jos, puteţi observa un prim tabel, cu două linii, aşa cum este
descris şi aşa cum apare afişat (vezi Fig. 4.38):
<TABLE border="5">
<TR>
<TD> Un text </TD>
<TD> Un text cu mult mai lung!</TD>
</TR>
<TR>
<TD> Text </TD>
<TD> Text </TD>
</TR>
</TABLE>

Figura 4.38.
Exemplu de tabel

În continuare, prezentăm câteva atribute ale elementului TABLE.

⇒ Border defineşte grosimea liniilor (în pixeli) care înconjoară tabelul. Pe


pagina următoare (în Fig. 4.39), puteţi observa cum arată acelaşi tabel, în
care atributul Border lipseşte. Simpla trecere a acestui atribut, fără a
preciza numărul de pixeli, are ca efect crearea unui chenar standard.
Capitolul 4 – HTML, CSS - primele noţiuni 129

Iată tabelul, fără atributul Border:

Figura 4.39. Exemplu


de tabel fără chenar

Observaţii !

 În absenţa altor formatări, toate celulele unei coloane


au lăţimea impusă de cel mai lung conţinut al uneia
dintre ele! În situaţia în care reducem dimensiunile
ferestrei browser-ului, textul va fi dispus modificat,
pentru ca tabelul să încapă în totalitate. Dincolo de
această limită, fereastra nu mai poate fi micşorată.

Figura 4.40. Efectul redimensionării


ferestrei browser-ului

 În cazul în care o linie conţine mai multe celule decât


restul liniilor, automat toate liniile vor avea acelaşi
număr maxim de celule:

<TABLE BORDER="5">
<TR>
<TD> O noua celula </TD>
<TD>Un text </TD>
<TD> Un text cu mult mai lung!
</TD>
</TR>
<TR>
<TD> Text </TD>
<TD> Text </TD>
</TR> Figura 4.41. Exemplu de tabel în care
</TABLE> două linii au un număr diferit de celule

 Un tabel poate conţine şi una sau mai multe imagini, aşa cum se vede mai
jos, unde imaginea este conţinută de o celulă a tabelului:

<TABLE BORDER="5">
<TR>
<TD><IMG SRC="BP1.jpg"></TD>
<TD>Un text cu mult mai lung!
</TD></TR>
<TR><TD>Text</TD><TD>Txt</TD>
</TR>
</TABLE> Figura 4.42. Exemplu de tabel care
conţine o imagine
130 Manual de Informatică pentru clasa a XII-a

⇒ cellspacing - determină spaţiul, în pixeli, dintre celule.

Exemplul 4.40. În figura alăturată, este


prezentat un tabel cu cellspacing="10".

Figura 4.43.
Exemplu de tabel

⇒ cellpadding determină, în pixeli, spaţiul lăsat în fiecare celulă a


tabelului între text (imagine) şi marginile celulei.

Exemplul 4.41. Acelaşi tabel, din exemplul


anterior, cu cellpadding = "15".

Figura 4.44.
Exemplu de tabel

Atenţie! Pentru ultimele două atribute, se poate alege o valoare procentuală, astfel
încât marginile să aibă dimensiunea procentual, în raport cu dimensiunea
disponibilă totală (lăţime şi înălţime).

⇒ rules – defineşte modul în care vor fi trasate liniile care separă celulele
tabelului. Poate lua valorile:

None Rows Cols All

Figura 4.45. Exemple de trasare a liniilor separatoare

⇒ frame - defineşte părţile care vor fi trasate din chenarul care înconjoară
tabelul. Atributul poate lua valorile:

Above Below Hsides

Vsides Lhs Rhs

Figura 4.46. Exemple de variante de trasare a chenarului unui tabel


Capitolul 4 – HTML, CSS - primele noţiuni 131

Iată şi câteva atribute ale elementului TD:

⇒ colspan="nr" - inserează în dreapta celulei, nr-1 celule al căror


conţinut este vid, dar pot fi folosite pentru afişarea valorii reţinute de celula
care are acest parametru. Efect secundar: pentru păstrarea formei
dreptunghiulare, toate celelalte linii vor avea, în dreapta, câte o celulă al
cărei conţinut este vid.

Exemplul 4.42. Considerăm tabelul de mai jos:

<TABLE BORDER="5">
<TR> <TD> T11</TD> <TD> T12 </TD>
<TD> T13</TD> </TR>
<TR> <TD> T21</TD> <TD> T22 </TD>
<TD> T23</TD> </TR>
<TR> <TD> T31</TD> <TD> T32 </TD>
<TD> T33</TD> </TR>
</TABLE>
Figura 4.47. Tabelul iniţial

care arată ca în Fig. 4.47. A doua celulă din linia


1 va conţine parametrul colspan:
<TD colspan="2"> T12 </TD>.
În figura alăturată, puteţi observa efectul!

Figura 4.48. Efectul obţinut

Pentru a evita o astfel de situaţie, neplăcută, linia respectivă va conţine o


celulă în minus, ca în exemplul următor. În plus, textul conţinut de celula cu acest
parametru va fi aliniat în centru, pentru a vedea cum se poate folosi spaţiul astfel
obţinut:
<TABLE BORDER="5">
<TR> <TD> T11</TD>
<TD colspan="2"
align="center">T12 </TD></TR>
<TR> <TD> T21</TD> <TD> T22 </TD>
<TD> T23</TD></TR>
<TR> <TD> T31</TD> <TD> T32 </TD>
<TD> T33</TD></TR>
</TABLE>
Figura 4.49. Ajustarea tabelului

⇒ rowspan="nr" - inserează pe următoarele nr-1 linii, în aceeaşi coloană,


câte o celulă al cărei conţinut este vid. Efect secundar: pentru păstrarea
formei dreptunghiulare, toate liniile vor conţine câte o celulă în plus.
132 Manual de Informatică pentru clasa a XII-a

Exemplul 4.43. Considerăm tabelul de mai jos:


<TABLE BORDER="5">
<TR> <TD> T11</TD>
<TD rowspan="2" align="center">
T12</TD> <TD>T13</TD></TR>
<TR> <TD> T21</TD> <TD> T22 </TD>
<TD> T23</TD></TR>
<TR> <TD>T31</TD><TD>T32</TD>
<TD>T33</TD></TR>
</TABLE> Figura 4.50. Exemplu de tabel

Pentru a corecta acest dezavantaj, următoarele nr-1 linii vor conţine câte o
celulă mai puţin. Reluăm exemplul:
<TABLE BORDER="5">
<TR> <TD>T11</TD>
<TD rowspan="2" align="center">
T12</TD> <TD>T13</TD></TR>
<TR> <TD>T21</TD><TD>T22</TD></TR>
<TR> <TD>T31</TD><TD>T32</TD>
<TD>T33</TD></TR>
</TABLE>

Figura 4.51. Ajustarea tabelului

Exemplul 4.44. Vom extinde celula T12 şi în dreapta şi în jos (cei doi parametri
pot fi folosiţi şi simultan). Textul va fi scris în centrul pătratului astfel format (vezi
Fig. 4.52):
<TABLE BORDER="5">
<TR> <TD>T11</TD>
<TD rowspan="2" colspan="2"
valign="middle" align="center">
T12</TD></TR>
<TR> <TD>T21</TD></TR>
<TR> <TD>T31</TD> <TD>T32</TD>
<TD>T33</TD></TR>
</TABLE>
Figura 4.52. Extinderea unei celule

Elementul CAPTION - are rolul de a permite scrierea titlului unui tabel. Titlul se
scrie între cele două tag-uri, <CAPTION> şi </CAPTION>. Cele două etichete
trebuie să se găsească imediat după <TABLE>.

Exemplul 4.45. Mai jos am introdus un titlu pentru un tabel oarecare:


<TABLE>
<CAPTION> Un titlu </CAPTION>
...
Capitolul 4 – HTML, CSS - primele noţiuni 133

⇒ Elementul CAPTION are atributul align. Cele patru valori pe care le poate
lua şi efectul lor, le puteţi observa mai jos:

top bottom left right

Figura 4.53. Exemple de tipuri de aliniere a titlului unui tabel

1. Să se realizeze tabelul de mai jos. Acesta este un caz clasic de tabel. În afara
tabelului propriu-zis, trebuie să utilizăm limbajul CSS pentru capul de tabel şi
alinierea din coloana a doua.

Figura 4.54. Tabelul propus pentru exerciţiul 1


Rezolvare. Mai jos este prezentat codul sursă:
<HTML>
<HEAD>
<STYLE>
.Stil {font-size:20pt; background:yellow;
font-style:bold; text-align:"center";}
.Stil1 {text-align:"center";}
</STYLE>
</HEAD>
<BODY>
<TABLE border="5">
<TR class="Stil">
<TD> <B> Nume tip </B> </TD>
<TD> <B> Numar octeti </B> </TD>
<TD> <B> Valoare </B> </TD>
</TR>
134 Manual de Informatică pentru clasa a XII-a

<TR>
<TD> <B> float </B> </TD>
<TD class="Stil1"> 4 </TD>
<TD> 3.4*10 <SUP> -38</SUP> si 3.4*10 <SUP> 38</SUP> </TD>
</TR>
<TR>
<TD> <B>double</B> </TD>
<TD class="Stil1"> 8 </TD>
<TD> 1.7*10 <SUP>-308</SUP> si 1.7*10 <SUP>308</SUP> </TD>
</TR>
<TR>
<TD> <B>long double</B> </TD>
<TD class="Stil1"> 10 </TD>
<TD>3.4*10<SUP>-4932</SUP> si 3.4*10<SUP>4932</SUP> </TD>
</TR>
</TABLE>
</BODY>
</HTML>

2. Formaţi o pagină web care să conţină un text oarecare, scris în stânga unei
imagini (vezi Fig. 4.55).

Rezolvare. Aparent, ar fi o problemă


de aliniere în dreapta a unei imagini. În
realitate, mascat, avem un tablel cu o
singură linie şi două coloane. În prima
se găseste un text, în a doua o
imagine. Evident, dacă se inverează
conţinutul celor două coloane, obţinem
efectul alinierii la stânga a imaginii.
<HTML>
<HEAD>
<STYLE>
P {width:3cm; height:4cm;} Figura 4.55. Pagina web propusă
IMG {width:3cm; height:4cm;} pentru exerciţiul 2
</STYLE>
</HEAD>
<BODY>
<TABLE>
<TR>
<TD><P>Un text; Un text; Un text; Un text; Un text;
Un text; Un text; Un text; Un text; Un text;
Un text; Un text; Un text; Un text; Un text;</P></TD>
<TD> <IMG src="Eric.jpg", alt="Eric"> </TD>
</TR>
</TABLE>
</BODY>
</HTML>
Capitolul 4 – HTML, CSS - primele noţiuni 135

3. Se cere să se scrie un text în două coloane, precum în imaginea de mai jos:

Figura 4.56. Pagina web pentru exerciţiul 3

Rezolvare. În fapt, vom construi un tabel cu două linii şi două coloane. Cele două
elemente de pe prima linie sunt unite şi conţin titlul. În cele două coloane se scriu
mai multe paragrafe. După cum ştiţi deja, lăţimea coloanelor depinde de mărimea
ferestrei browser-ului, dar, mai ales, de conţinutul lor. Din acest motiv, s-a forţat
prin CSS ca paragrafele să aibă lăţimea de 4 cm. În rest, analizaţi modul în care
s-a realizat pagina respectivă:
<HTML>
<HEAD>
<STYLE>
P { width:4cm; }
H2 {text-align:"center"}
</STYLE>
</HEAD>
<BODY>
<TABLE>
<TR><TD colspan="2"><H2>Scrierea pe coloane</H2></TD></TR>
<TR>
<TD>
<P>Un text scris pe doua coloane.</P>
<P>Formam un tabel cu o singura linie si doua
celule de date.</P></TD>
<TD>
<P>Trebuie sa ne asiguram ca textul este impartit de asa
natura astfel incat sa ocupe aproximativ acelasi spatiu
in cele doua coloane.</TD></TR>
</TABLE>
</BODY>
</HTML>
136 Manual de Informatică pentru clasa a XII-a

4.13. Hiperlegături 1 (link-uri)

Elementul A (ancoră) - începutul unei ancore este marcat prin <a>, iar sfârşitul
său prin </a>. O ancoră conţine adresa URL a unei resurse oarecare aflată pe un
server şi un text lămuritor (sau o imagine) asupra legăturii. Practic, se afişează,
subliniat, doar textul lămuritor.

Ideea de bază este următoarea: dacă se execută clic pe acest text lămuritor,
resursa indicată este adusă pe calculatorul vizitatorului, opţional sau nu şi este
lansat programul care prelucrează resursa respectivă.

⇒ Cel mai important atribut al unei ancore este href 2 (calea către legătură,
referinţa). Numeroasele exemple care vor fi date în acest paragraf vă vor
lămuri asupra modului de utilizare a acestui atribut.

4.13.1. Legături către alte pagini

O legătură către un fişier HTML este afişată de browser cu o altă culoare şi


este subliniată. Când este deasupra ei, cursorul grafic ia forma unei mâini,
indicându-ne astfel că este o legătură pe care o putem utiliza.

Exemplul 4.47. Mai jos, puteţi observa modul în care am scris un paragraf care
conţine o legătură. Dacă se execută dublu-clic asupra ei, de pe server este adus
fişierul index care va fi afişat de browser.
<P>Pentru mai multe informatii,<BR>
<A href="http://www.nasa.gov"> vizitati site-ul NASA</A> !
</P>

Figura 4.57. Exemplu de paragraf care


conţine o hiperlegătură

 De asemenea, o legătură poate fi creată şi cu ajutorul unei imagini (nu


numai cu ajutorul unui text).

Exemplul 4.48. Analizaţi codul de mai jos:


<A href="http://www.nasa.gov"> <IMG src="Racheta1.bmp"></A>

Termenul este o traducere a celui din limba engleză, “hyperlink”. Din comoditate, este
1

utilizată forma prescurtată a acestuia: “legătură” (“link”).


2
Denumirea atributului este un acronim pentru Hypertext REFerence.
Capitolul 4 – HTML, CSS - primele noţiuni 137

4.13.2. Operaţia download

Uneori, este necesar ca utilizatorul paginii noastre să poată descărca, dacă


doreşte, anumite fişiere. Descărcarea fişierelor poartă numele de download-are,
termen care provine din limba engleză.

Exemplul 4.49. Considerăm o pagină care va conţine legătura către fişierul care
trebuie download-at (”bpro2003.zip”). Iată cum am construit ancora:
<A href="http://www.unsite.ro/personal/bpro2003.zip">
Programa la informatica </A>

După ce vizitatorul execută un clic pe legătură, va apărea o cutie de dialog


precum cea de mai jos:

Figura 4.58. Cutia de dialog File Download

Prin ea, vizitatorul poate comanda ca după descărcare, fişierul să fie


automat deschis (Open) cu un program care are asociată respectiva extensie (în
exemplu WinRAR, pentru a-l dezarhiva) sau să fie salvat pe hard, urmând a fi
utilizat mai târziu, prin comanda Save.

Exemplul 4.50. Presupunem că utilizatorul are pe calculatorul de pe care


accesează pagina, placă de sunet şi boxe, iar placa de suet este instalată. De
asemenea, presupunem că acesta are instalat un program de redare a sunetelor,
cum ar fi celebrul Winamp şi că site-ul conţine fişierul ”Trumpet1.wav”. Se pune
problema ca, atunci când vizitează pagina noastră, să poată asculta, la propria
comandă, anumite mesaje audio.
<A href="http://www.unsite.ro/personal/Trumpet1.wav">
Sunetul unei trompete </A>
138 Manual de Informatică pentru clasa a XII-a

La executarea unui clic pe legătură, se download-ează fişierul


”Trompet1.wav” şi este lansat în executare programul Winamp care realizează
redarea sunetelor (în particular, sunetul unei trompete).

Figura 4.59. Legătură către


un fişier audio

Exemplul 4.51. Similar exemplului anterior, presupunem că avem în ”C:\” fişierul


video ”Party-1.avi”. Considerăm că pentru extensia “.avi” avem asociat
programul implicit, adică Windows Media Player. Pentru a apela fişierul, vom
utiliza ancora de mai jos:
<A href="C:/Party-1.avi">
Imagini si sunete (fisier avi) </A>

Figura 4.60. Legătură către


un fişier video

Efectul este că se lansează programul amintit şi redă fişierul.

4.13.3. Legături relative la document

Uneori, documentele HTML sunt lungi şi pot fi greu parcurse de vizitator.


Desigur, utilizatorul le poate parcurge cu ajutorul barelor de defilare. Există
posibilitatea ca, în anumite cazuri, să-l scutim de acest efort. Pentru aceasta, vom
proceda astfel:

⇒ În punctele de unde dorim să fie vizualizat documentul, creăm ancore cu


nume. Numele unei ancore îl vom da prin atributul id.

Exemple:

<A id="top"></A> (am “aşezat-o” în partea de sus a documentului).


<A id="mijloc"></A> (am "aşezat-o” la mijlocul documentului).

⇒ În punctele de unde dorim ca utilizatorul să poată vizualiza imediat


documentul începând de la o anumită ancoră definită anterior creăm, tot cu
ajutorul unei ancore, o hiperlegătură.

Exemple:
<A href="#top"> in top </A> <BR> (salt în partea de sus a documentului).

<A href="#mijloc"> la mijloc </A> <BR> (salt la mijlocul documentului).


Capitolul 4 – HTML, CSS - primele noţiuni 139

 Pentru a vedea “pe viu” cum funcţionează acest mecanism, este necesar ca
fişierul să fie suficient de mare, astfel încât zona care conţine ancora
destinaţie să nu fie vizibilă în momentul “trimiterii”.

Există posibilitatea ca alte pagini către care se face trimitere să fie


vizualizate începând dintr-un anumit punct, care conţine o anume ancoră.

Exemplul 4.52. Un alt fişier HTML conţine o ancoră către fişierul anterior (numit
“lung.html”):

<A href="c:\lung.html#mijloc"> Salt la fisierul HTML


"lung.html", la mijloc </A>

Figura 4.61. Exemplu de hiperlegatură spre o pagină cu ancoră relativă

Observaţie ! Există cărţi sau documentaţii scrise utilizând HTML-ul. În loc să avem
un cost ridicat al tipăririi ei pe hârtie, se preferă scrierea ei în format HTML şi
livrarea ei către cititor pe un CD. Acesta va citi cartea direct pe calculator. Vă daţi
seama. că, în astfel de cazuri, referinţele relative la document devin extrem de
importante. Acest procedeu este des utilizat şi în cazul documentaţiilor on-line,
oferite pe Internet.

4.13.4. Trimiterea automată a unui e-mail

Dorim ca o persoană să ne poată trimite un e-mail, direct din pagina noastră.


Ea nu va avea decât să execute un clic pe respectiva legătură şi, imediat, se va
lansa programul de trimitere a e-mail-ului, iar adresa noastră va fi trecută automat
în câmpul destinatarului (To).

Exemplul 4.53. Pentru a obţine acest efect, pentru atributul href se va completa
”mailto”, urmat de “:” şi de adresa de e-mail:

<ADDRESS><A href="mailto:eu@unsite.ro"> Puteti sa-mi scrieti


Puteti sa-mi scrieti </A></ADDRESS>

Observaţie ! În ultimul timp, acest procedeu este mai puţin folosit. Anumite
motoare de căutare, identifică cuvântul cheie ”mailto” şi extrag adresa de e-mail.
Ulterior, această adresă este utilizată pentru a trimite mesaje publicitare nedorite
(spam). Din acest motiv, este bine să scrieţi adresa fără acest atribut, iar cei
interesaţi, cu un efort suplimentar, o copiază şi vă trimit e-mailul.
140 Manual de Informatică pentru clasa a XII-a

4.14. Hărţi imagine

Poate aţi întâlnit pe anumite site-uri o hartă. Dacă se execută click pe o


anumită regiune a ei, se afişează anumite informaţii, specifice regiunii respectve,
dacă se ewxecută click pe altă porţiune se afişează alte informaţii, ş.a.m.d. În acest
caz s-a folosit procedeul hartă-imagine. Un alt exemplu de folosire a aceluiaşi
procedeu: a pagină web în care se prezintă un anumit tip de mobilă. Dacă se dă
click pe imaginea ce reprezintă un scaun, se afişează preţul scaunui, dacă se dă
click pe imaginea ce reprezintă masa se afişează preţiul mesei, etc. Cum s-au
obţinut aceste efecte?.

Problema este următoarea: se dă o imagine şi se cere ca, prin executarea


unui clic asupra unei anumite parţi a ei, să se efectueze una dintre operaţiile
prezentate în paragraful anterior, prin executarea unui clic în altă parte a ei, să se
efectueze o altă operaţie de acelaşi tip, ş.a.m.d. Cu alte cuvinte, trebuie să se
creeze un meniu care să se prezinte sub formă de imagine.

Priviţi imaginea alăturată.


Ea cuprinde 4 regiuni marcate.
Una sub formă de dreptunghi, alta
sub formă de cerc şi două sub
formă de poligoane. Dorim ca
atunci când executăm clic pe una
din aceste regiuni, să se execute
o anumită operaţie.

Browser-ul va afişa poza


fără a evidenţia aceste zone, dar
atunci când cursorul grafic trece
deasupra unei astfel de zone, el
va lua forma unei mâini şi, aşa
cum am spus, executarea unui
clic determină efectuarea unei
operaţii specifice zonei, de Figura 4.62. Exemplu de imagine
exemplu vizualizarea unei pagini. care cuprinde patru zone marcate

4.14.1. Cum se introduce în HTML o hartă imagine ?

Mai jos, puteţi observa modul în care au fost scrise zonele din imaginea
anterioară (câinele):

<HTML>
<BODY>
<IMG src="c:/web/caini3.jpg" usemap="#caine">
Capitolul 4 – HTML, CSS - primele noţiuni 141

<MAP NAME="caine">
<AREA SHAPE=RECT COORDS="25,14,90,44" HREF="patrat.htm">
<AREA SHAPE=CIRCLE COORDS="36,70,23" HREF="cerc.htm">
<AREA SHAPE=POLY COORDS="185,39,193,37,204,36,221,34,244,
47,246,47,247,50,248,57,257,62,262,64,269,67,264,73,259,81,
249,82,232,78,230,79,223,87,212,87,184,80,183,66,184,57,185,
41,186,35" HREF="cap.htm">
<AREA SHAPE=POLY COORDS="116,106,112,116,110,121,110,126,
107,128,104,132,104,141,104,147,104,152,99,156,95,163,97,165,
99,165,99,169,99,180,97,188,97,193,103,192,111,190,116,192,11
9,192,119,184,123,174,123,166,126,156,128,153,131,148,132,144
,132,142,132,139,134,138,138,135,138,128,143,125,150,121,150,
117,150,115,152,113,152,110,116,106" HREF="picior.htm">
</MAP>
</BODY>
</HTML>

Din analiza exemplului de mai sus, observăm că trebuie să utilizăm


următoarele elemente:

Elementul MAP - cu acesta descriem o hartă, utilizând două tag-uri: <MAP> şi


</MAP>. Între ele se găseşte descrierea diverselor zone care alcătuiesc harta.
Elementul are următorul atribut:

⇒ name - numele hărţii. El trebuie trecut în atributul usemap al elementului IMG


care descrie imaginea folosită ca o hartă:
<IMG src="c:/web/caini3.jpg" usemap="#caine">

Elementul AREA - are rolul de a descrie o zonă din hartă pentru care, la
executarea unui clic, se produce un anumit efect. Acest element utilizează tag-ul
<AREA atribute>. Principalele atribute ale elementului AREA sunt:

⇒ shape – descrie tipul regiunii respective;


⇒ href – adresa fişierului html sau a unei alte resurse (la fel ca la ancore).

După cum ştim, fiecare imagine este alcătuită din pixeli. Fiecare pixel este
caracterizat de două coordonate (x,y), în sistemul de axe de mai jos:

0,0
X

Figura 4.63. Sistemul de coordonate


asociat unei imagini Y
142 Manual de Informatică pentru clasa a XII-a

Atributul SHAPE poate lua valorile:

 RECT COORDS="X1,Y1,X2,Y2" – dreptunghi, unde X1,Y1 reprezintă


coordonatele colţului din stânga-sus şi X2,Y2 sunt coordonatele colţului
din dreapta-jos.
 CIRCLE COORDS="X1,Y1,R" – cerc, unde X1,Y1 reprezintă
coordonatele centrului, iar R raza cercului.
 POLY COORDS="X1,Y1, X2,Y2, ..., Xn,Yn" – poligon, unde
X1,Y1, X2,Y2, ... reprezintă coordonatele vârfurilor.
x2,y2
x1,y1
x4,y4
x1,y1
x1,y1
R x3,y3

x2,y2
xn,yn

RECT CIRCLE POLY

Figura 4.64. Coordonatele celor trei forme ale atributului SHAPE

Totuşi, cum au fost obţinute coordonatele punctelor? Dacă pentru dreptunghi


sau cerc aceste coordonate pot fi găsite relativ uşor (de exemplu, Paint-ul
afişează coordonatele cursorului), în cazul poligoanelor închise, problema devine
serioasă! Din acest motiv, s-au realizat mai multe programe prin care coordonatele
se obţin automat.

4.14.2. Programul Map This!

Programul Map This! este destinat obţinerii automate


a coordonatelor punctelor care definesc regiunile, pentru o
imagine cu extensia .gif sau .jpeg. Practic, se încarcă
o imagine într-unul dintre formatele enumerate anterior şi se
trasează, cu mouse-ul, regiunile pe ea. Imaginea arată precum
cea din Fig. 4.62 (câinele). După ce regiunile au fost trasate, se
salvează sub formă de fişier HTML coordonatele astfel obţinute.

 Programul este freeware şi poate fi obţinut de pe


Internet. Căutaţi-l cu GOOGLE!

 El “ştie” mai multe decât ce este prezentat în acest


paragraf, dar noi ne vom limita doar la ceea ce este strict
necesar!
Figura 4.65. Programul
Map This!
Capitolul 4 – HTML, CSS - primele noţiuni 143

1) După apelul programului, se încarcă imaginea. Apelaţi File şi New. Va


apărea o cutie de tip Open, cu ajutorul căreia puteţi selecta fişierul dorit
(.jpeg sau .gif).

2) Pentru a putea lucra uşor cu imaginea, puteţi folosi Zoom in (măreşte


imaginea) sau Zoom out (o micşorează).

Figura 4.66. Butoane de marire şi


micşorare a imaginii
Zoom in Zoom out

3) Pentru a trasa un dreptunghi, selectaţi butonul alăturat. Apoi,


selectaţi dreptunghiul dorit (ca în Paint), de la colţul din stânga-sus,
către colţul din dreapta-jos.

În exemplu, am selectat un dreptunghi care include


cuvântul PETS.

Figura 4.67. Selectarea unei forme


dreptunghiulare

4) Pentru a trasa un cerc, apăsaţi butonul alăturat. Apoi, selectaţi cercul


dorit.

În exemplu, încadrăm în cercuri capetele celor doi:

Figura 4.68. Trasarea unor


forme circulare

5) Pentru a trasa un poligon oarecare, apăsaţi butonul alăturat şi trasaţi


poligonul. Executaţi un clic în punctul de unde doriţi să începeţi
trasarea. Apoi deplasaţi cursorul pe prima latură, apoi executaţi un
click, deplasaţi cursorul pe a doua latură, executaţi un clic, ş.a.m.d. În final,
executaţi un dublu-clic şi figura se va închide.

În exemplu, am încadrat în poligon căţelul. Atenţie:


pentru a obţine o cât mai fină încadrare, trasaţi laturi mici
pentru poligon.

Figura 4.69. Trasarea unei


forme poligonale
144 Manual de Informatică pentru clasa a XII-a

6) După ce am încadrat toate regiunile care ne interesează, putem trece la


scrierea referinţei (link-ului) pentru fiecare dintre ele. Din meniu, apelaţi
View şi Area List. Va apărea o listă, aşa cum este cea de mai jos.
Întrucât am selectat 4 regiuni, lista are
4 elemente. Selectarea unui element al
ei (în exemplul 1) are ca efect faptul că
zona care îi corespunde va apărea în
imagine cu o culoare diferită, pentru a
le putea distinge. Figura 4.70. Lista Area List

Un dublu-clic în listă, pe reprezentarea unei anumite regiuni, are ca efect


scrierea link-ului respectiv.

În exemplul următor, comandăm


browser-ului încărcarea unui anumit fişier
HTML (o pagină). Procedaţi la fel pentru
fiecare regiune în parte. După ce aţi
terminat această operaţie, treceţi la pasul
următor. Spre exemplu, pentru zona 3
(Area #3), avem:

Figura 4.71. Fereastra de


setări a une zone

7) Urmează salvarea hărţii. Apelaţi File şi Save As. Selectaţi


CSIM. Salvaţi sub formă de fişier HTML.

Există posibilitatea să salvaţi într-un fişier HTML deja scris (acesta va conţine
src-ul cu imaginea). Dacă salvaţi într-un fişier diferit, puteţi apoi să-l
deschideţi, să selectaţi descrierea (între <MAP> şi </MAP>) şi să o includeţi în
fişierul dvs. De acum, puteţi folosi fără probleme hărţi imagine.

În final, câteva amănunte “de lucru”:


Ştergerea unei regiuni. Apăsaţi butonul alăturat şi aşezaţi cursorul grafic
deasupra ei. Apoi, apăsaţi butonul drept al mouse-ului. Din meniul flotant
care va apărea, selectaţi Delete Area.

Ştergerea unui punct al liniei poligonale. Atunci punct şters


când cursorul grafic staţionează asupra sa, cursorul ia
formă de cruce. Dacă se apasă butonul drept şi se
selectează Delete Point, punctul va fi şters şi, deci,
ignorat pentru poligon. Figura 4.72

Exerciţiu de tip referat! Întocniţi un referat despre programul Map This! sau un
altul cu acelaşi rol. Este foarte important să învăţaţi să vă autoducumentaţi. Nu
întotdeauna, pentru orice temă, veţi găsi o carte care s-o trateze!
Capitolul 4. HTML, CSS – primele noţiuni 145

4.15. Elementele BASE, META şi SCRIPT


Vom prezenta în continuare câteva elemente esenţiale care pot fi scrise în
cadrul antetului (HEAD), extrem de utile în foarte multe situaţii.

Elementul BASE - are forma generală <BASE href="adresa"> şi are rolul de


a preciza o adresă de bază pentru resurse, iar celelalte adrese se obţin adăugând
după adresa de bază o adresă specifică. Tag-ul <BASE> se va scrie în antetul
paginii, adică în HEAD.
Exemplul 4.54. Pe calculatorul meu, am câteva imagini în folder-ul ”C:\LaMare”
(1.jpg, 2.jpg, etc.). Valoarea folder-ului va fi trecută în BASE (href). De acum,
pot scrie adresa pe scurt (”1.jpg”).
<HEAD>
<BASE href="C:/LaMare/">
...
<BODY>
...
<IMG src="1.jpg">

Observaţii !

 Practic, se formează C:/LaMare/1.jpg.


 Vă daţi seama că în acest mod pot scrie şi o adresă de internet:
<BASE href = "http://www.paginamea.ro/">, etc.

Elementul META - este folosit pentru a furniza informaţii motoarelor de


căutare. Unele dintre ele vizitează doar antetul pentru a obţine informaţii.
Informaţiile conţinute de acest element nu sunt afişate de browser, dar este
important să-l folosim pentru ca informaţiile conţinute în site-ul nostru să fie
accesibile. Tag-ul <META> se găseşte în antet (HEAD).

Observaţie ! În antet se pot găsi mai multe elemente META.

Atributele elementului META sunt:

⇒ Atributul NAME – pentru el se pot utiliza câteva cuvinte cheie care vor fi
prezentate în cele ce urmează.
⇒ Atributul CONTENT – are un conţinut variabil în funcţie de valoarea trecută
pentru NAME.

Cum utilizăm cele două atribute ?


 Pentru a specifica autorul unui document:
<META NAME="Author" CONTENT="Mihai Popescu">
146 Manual de Informatică pentru clasa a XII-a

 Pentru a specifica titlul unui document:


<META NAME="TITLE" CONTENT="Cresterea albinelor">

 Pentru a specifica cuvintele cheie după care să fie regăsit site-ul dvs. Vă daţi
seama de importanţa acestora...
<META NAME="KEYWORDS" CONTENT="albine, matca, trantor,
stup, polen, miere">

Important ! Trebuie să treceţi forma scurtă a unui cuvânt. De exemplu, dacă


trec "stup", motoarele vor furniza adresa site-ului, chiar dacă o persoană
caută după cuvântul cheie "stupi".

 Pentru a specifica limba în care este scris site-ul (este utilă în cazul căutărilor
avansate). În exemplu, site-ul este scris în limba română:
<META NAME="LANGUAGE" CONTENT="RO">

 Pentru a specifica textul pe care îl va afişa un motor de căutare, la listarea


paginilor. Dacă acesta nu este trecut, motorul va afişa primele linii din
pagină, ceea ce nu e foarte relevant.
<META NAME="DESCRIPTION" CONTENT="Acest site este
dedicat modalitatilor de crestere a albinelor">

Observaţii importante !

 Există şi alte atribute ale elementului META, dar aceştia doi sunt suficienţi.
Majoritatea motoarelor de căutare se bazează în principal pe aceştia:
Description şi Keywords.

 Optimizarea site-urilor pentru motoarele de căutare (SEO – Search


Engine Optimization) reprezintă o unealtă indispensabilă pentru a fi
eficient pe Internet. Există firme specializate care se ocupă strict de această
problemă, iar preţurile sunt mari…
 La început, cei care au realizat motoarele de căutare au vrut să ajute
programatorii web prin utilizarea tag-urilor META, pentru a evidenţia mai uşor
şi mai bine conţinutul paginilor. Apoi, anumite persoane au folosit acest lucru
pentru a obţine un avantaj şi au introdus cuvinte care nu aveau nici o
legătură directă cu paginile respective, ci doar pentru a fi listaţi “mai bine”.
Aşadar, tag-urile META nu mai erau utile, ci doar o unealtă pentru spam
(informaţie nedorită). De aceea, unele motoare au renunţat definitiv la ele,
iar altele, dimpotrivă, pun paginile la sfârşitul listei dacă elementele cheie din
META nu se regăsesc în conţinutul paginii. În concluzie, reţineţi:

Folosiţi tag-urile META cu grijă şi nu introduceţi cuvinte ce nu sunt


incluse şi în fişierul HTML. Nu repetaţi cuvintele!
Capitolul 4. HTML, CSS – primele noţiuni 147

Elementul SCRIPT - este folosit pentru introducerea anumitor secvenţe de


program în cadrul paginilor web. Există mai multe limbaje (numite de scriptare)
care permit scrierea acestor secvenţe, cum ar fi JavaScript sau VBScript.
Programa nu include studiul acestor limbaje.

4.16. Cadre (FRAMESET, FRAME şi IFRAME)


Există oare posibilitatea ca aceeaşi fereastră a browser-ului să afişeze mai
multe fişiere HTML (sau alte resurse) simultan? Răspunsul este afirmativ.

Exemplul 4.55. Priviţi imaginea din Fig.4.73: fereastra este împărţită în 4 părţi:
două dintre ele afişează două fişiere HTML, iar celelalte două afişează două imagini.
Blocurile în care a fost împărţită fereastra poartă denumirea de cadre (frame-uri).

Figura 4.73. Exemplu de pagină web împărţită în cadre

Cum s-a obţinut acest efect? Înainte de a prezenta sistematic noţiunile, ca să


vă faceţi o idee, priviţi fişierul HTML de mai jos:
<HTML>
<HEAD>
</HEAD>
<FRAMESET rows="30%, 70%">
<FRAME scrolling="yes" src="c:/test.html">
<FRAMESET cols="30%,30%, 40%">
<FRAME scrolling="yes" src="c:/poze/cladire.jpg">
<FRAME scrolling="yes" src="c:/poze/birou.jpg">
<FRAME scrolling="yes" src="c:/c1.html">
</FRAMESET>
</FRAMESET>
</HTML>
148 Manual de Informatică pentru clasa a XII-a

Elementul FRAMESET - are rolul de a împărţi fereastra în mai multe cadre. În


fişierul HTML el înlocuieşte <BODY>. Pentru a-l folosi, vom utiliza două etichetele:
<FRAMESET atribute> şi </FRAMESET>.

Vom studia câteva atribute ale acestui element:


⇒ Rows – descrie liniile în care este împărţită fereastra;
⇒ Cols – descrie coloanele în care este împărţită fereastra.

Observaţie ! În exemplul dat iniţial, fereastra este împărţită în două linii. Apoi, a
doua linie este împărţită în trei coloane.

Probabil că vă veţi întreba: de ce a fost împărţită a doua linie în trei coloane


şi nu prima? Observaţi cum se închid tag-urile <FRAMESET> şi </FRAMESET>.
Iniţial, avem două linii. Prima linie conţine un element FRAME şi a doua un element
FRAMESET. Acesta din urmă declară 3 coloane, deci între tag-urile lui se vor găsi 3
elemente FRAME:
<FRAMESET rows="30%, 70%">
<FRAME ...>
<FRAMESET cols="30%,30%, 40%">
<FRAME ...>
<FRAME ...>
<FRAME ...>
</FRAMESET> Figura 4.74. Schema
</FRAMESET> paginii obţinute

Exemplul 4.56. Două linii, iar prima linie este împărţită în trei coloane. Prima linie
conţine un FRAMESET, a doua un FRAME:

<FRAMESET rows="30%, 70%">


-<FRAMESET cols="30%,30%, 40%">
<FRAME ...>
<FRAME ...>
<FRAME ...>
-</FRAMESET>
<FRAME ...> Figura 4.75. Schema
</FRAMESET> paginii obţinute

Pentru a stabili dimensiunile liniilor (coloanelor), există mai multe modalităţi:

1) Procentual, ca în exemplele date:

<FRAMESET rows="30%, 70%"> Avem 2 linii. Prima linie ocupă 30% din
înălţimea ferestrei, iar a doua, 70%.

<FRAMESET cols="30%,30%, 40%"> Avem 3 coloane. Prima coloană ocupă


30% din lăţimea ferestrei, a doua 30%, iar a treia 40%.
Capitolul 4. HTML, CSS – primele noţiuni 149

2) Proporţional:

<FRAMESET cols="1*, 2*, 3*">. 1+2+3=6. Prima coloană ocupă 1/6 din
lăţime, a doua 2/6=1/3 din lăţime, iar a treia 3/6=1/2 din lăţime.

3) Mixt:

<FRAMESET cols="50%*, 1*, 2*, 200"> Prima coloană ocupă 50% din
lăţime, iar ultima 200 de pixeli. Ce a rămas se împarte proporţional între coloanele
2 şi 3, deci coloana 2 ocupă 1/3 şi coloana 3, 2/3.

Observaţie ! În cazul în care valorile sunt incoerente, nu s-au dat norme privind
modul în care trebuie procedat. Prin urmare, fiecare tip de browser va proceda
în modul său specific. Încercaţi...

Elementul FRAME - este utilizat pentru a preciza conţinutul unui anumit cadru.
Se utilizează un singur tag: <FRAME atribute>. Iată principalele proprietăţi:

⇒ src – adresa fişierului HTML sau a imaginii utilizate.

 de exemplu, cadrul afişează un fişier HTML:

<FRAME src="c:/test.html">

 sau cadrul afişează o imagine:


<FRAME src="c:/poze/birou.jpg">

⇒ marginheight – marginile, în pixeli sau procent %, faţă de partea de sus


(top) şi cea de jos (bottom);

⇒ marginwidth – marginile, în pixeli sau procent %, faţă de partea din stânga


(left) şi cea din dreapta (right).

 Sus şi jos marginea este de 100 pixeli, iar în stânga şi dreapta este
de 150 pixeli:

<FRAME marginwidth=150 marginheight=100


src="c:/poze/cladire.jpg">

⇒ frameborder - poate lua două valori: 1 (valoare implicită) sau 0. Dacă


valoarea luată de acest atribut este 0, atunci cadrul nu mai este separat de
celelalte printr-un chenar.

Observaţie ! Dacă vrem să nu se traseze chenarul separator între două cadre,


trebuie ca amândouă să aibă valoarea 0 pentru acest atribut. E logic, nu?

⇒ scrolling – tratează prezenţa barei de scroll (defilare). Atributul poate


lua una dintre cele trei valori:
150 Manual de Informatică pentru clasa a XII-a

1) auto – valoarea implicită. Bara de scroll este prezentă numai dacă


este cazul (ce trebuie afişat în cadru ocupă o suprafaţă mai mare
decât cea a cadrului);
2) yes - bara de scroll este întotdeauna prezentă;

3) no – bara de scroll nu este în nici un caz afişată.

⇒ noresize – prezenţa sa cere browser-ului să nu permită vizitatorului


paginii respective să redimensioneze cadrul. Dacă este prezent pentru un
cadru, atunci nu pot fi redimensionate nici cadrele învecinate.

⇒ name – are rolul de a atribui un nume elementului FRAME.

Probabil că vă veţi întreba: la ce foloseşte numele unui cadru? Ei bine, rolul

? este uriaş. Mai precis, dintr-un cadru, se poate comanda conţinutul oricărui
cadru (inclusiv al cadrului curent).

Exemplul 4.57. Browser-ul afişează două cadre. Primul dintre ele conţine link-urile
pentru capitolele unei cărţi. Al doilea, iniţial, afişează paragrafele primului capitol.
La comanda vizitatorului paginii respective, se pot afişa, în al doilea cadru,
paragrafele oricărui alt capitol.

Figura 4.76. Pagina propusă pentru Exemplul 4.57

Iată fişierul HTML iniţial, cel care creează cadrele şi în care unul dintre ele
este numit “cpt”:

<HTML>
<HEAD>
</HEAD>
<FRAMESET cols="30%*, 70%">
<FRAME src="c:/ancore.html">
<FRAME name="cpt" src="c:/c1.html">
</FRAMESET>
</HTML>

Primul cadru afişează următorul fişier HTML:


Capitolul 4. HTML, CSS – primele noţiuni 151

<HTML>
<HEAD>
</HEAD>
<BODY>
<A href="c:/c1.html" target="cpt"> Capitolul 1 </A> </br>
<A href="c:/c2.html" target="cpt"> Capitolul 2 </A> </br>
<A href="c:/c3.html" target="cpt"> Capitolul 3 </A>
</BODY>
</HTML>

Fişierul de mai sus conţine trei ancore. Pentru fiecare ancoră s-a folosit un atribut
nou, numit target. Acesta are rolul de a preciza “ţinta”, adică numele cadrului
care va afişa fişierul HTML cerut.

Observaţie ! În absenţa atributului target, fişierul va fi afişat în cadrul care


conţine ancora!

Elementul IFRAME - permite crearea unui cadru în corpul (BODY) documentului.


Cu alte cuvinte, cadrele se pot folosi şi în mod clasic. Pentru a-l descrie, se
folosesc etichetele <IFRAME atribute> şi </IFRAME>.

Exemplul 4.58. Mai jos, un cadru conţinut


de un document afişează un fişier HTML:
<HTML>
<HEAD></HEAD>
<BODY>
<P>Acesta este un paragraf</P>
<IFRAME SRC="C:/c1.html">
</IFRAME>
</BODY> Figura 4.77. Exemplu de pagină cu un
</HTML> cadru în interiorul corpului documentului

Atributele elementului <IFRAME> sunt:


⇒ name – numele, am văzut care este rolul lui;
⇒ frameborder – poate lua valoarea 0 sau 1, la fel ca pentru elementul
FRAME;
⇒ src – adresa fişierului HTML sau a imaginii utilizate;
⇒ scrolling – la fel ca orice cadru.

Elementul NOFRAMES - este cuprins între tag-urile <NOFRAMES> şi


</NOFRAMES>. În cazul în care browser-ul vizitatorului x nu poate afişa cadre, se
utilizează pentru a scrie tag-urile HTML alternative. Ce-i drept, acest lucru se
întâmplă din ce în ce mai rar (fabricanţii de soft s-au adaptat cerinţelor). De regulă,
în acest caz, se vor utiliza <BODY> şi câteva ancore (câte una pentru fiecare cadru).
152 Manual de Informatică pentru clasa a XII-a

4.17. Elementul MARQUEE


Acesta creează un bloc în care elementele introduse între etichetele
<MARQUEE> şi </MARQUEE> se mişcă într-o anumită direcţie. Acest efect se
numeşte Scrolling Display şi poate fi util la afişarea anunţurilor (publicitare):

Figura 4.78. Efect obţinut cu ajutorul elementului MARQUEE

Codul pentru a obţine animaţia de mai sus este:


<MARQUEE>Salut! Uite masina mea! <IMG src="Masina.jpg">
</MARQUEE>

Se observă că elementul este la nivel de text, imaginea fiind aliniată cu textul


introdus. Oricum, trebuie folosit cu grijă şi cu gust pentru că poate obosi vizitatorul
cu prea multă mişcare...

Cele mai importante atribute ale acestui element sunt:

⇒ Direction – direcţia de mişcare a blocului ("Left" sau "Right").


Valuarea implicită este dinspre stânga ("Left").
⇒ Behavior – tipul de scroll aplicat. Poate lua valorile:

 Scroll – valoare implicită - conţinutul se mişcă de la o margine la


alta şi apoi reapare;
 Slide – când se atinge marginea opusă (cea indicată de atributul
Direction), mişcarea se opreşte;
 Alternate – conţinutul se mişcă alternativ între cele două margini şi
este întotdeauna vizibil.
⇒ Scrolldelay – timpul de tranziţie al elementelor de la o poziţie la alta (în
milisecunde, valoarea implicită este de "85"). Astfel, stabilim viteza cu care
se derulează “animaţia”: cu cât această valoare este mai mare, cu atât vom
avea o tranziţie mai lentă a conţinutului.
De exemplu: <MARQUEE Scrolldelay="500"> (jumătate de secundă).
Capitolul 4. HTML, CSS – primele noţiuni 153

⇒ Scrollamount – se setează numărul de pixeli cu care se mută conţinutul


blocului, la fiecare pas. O valoare mai mare implică o viteză mărită de
mişcare. Valoarea implicită este "6".
De exemplu: <MARQUEE Scrollamount="10">.

⇒ Loop – numărul de cicluri pe care să le efectueze conţinutul. Implicit,


valoarea este "INFINITE" (la nesfârşit). O problemă ar fi faptul că după
terminarea ultimului ciclu, conţinutul dispare. Se poate rezolva însă cu
atributul Behavior, specificând ca la ultimul ciclu să se oprească atunci
când atinge marginea respectivă (cu "Slide"):
De exemplu:
<MARQUE Loop="3" Behavior="Slide">Salutare!</MARQUEE>.

4.18. Aşezarea implicită în pagină a diverselor


elemente

O întrebare foarte importantă: cum aranjează browser-ul în pagină diversele


elemente (imagini, paragrafe, tabele, etc.)? Vă daţi seama de importanţa ei: orice
creator de pagini web doreşte să amplaseze elementele care alcătuiesc o pagina
într-un anumit fel...

În HTML, există două tipuri de elemente: elemente la nivel de bloc şi


elemente la nivel de text (inline).

A) Elementele la nivel de bloc sunt aşezate pe rând nou. Exemple de


elemente la nivel de bloc: P (paragraf), TABLE (tabel), TR (linie de tabel)
H1..H6, OL, LI, UL (liste), DL, DT, DD (itemi din liste).

B) Elemente la nivel de text (inline). Acestea se scriu pe linia curentă, în


continuare. Exemple de elemente la nivel de text: B (bold), I (italic), IMG
(imagini), DEL, DFN, etc.

Exemplul 4.59. Analizaţi codul sursă de mai jos:


<HTML>
<HEAD>
<STYLE>
IMG {width:3cm;
height:4 cm;}
</STYLE>
</HEAD>
154 Manual de Informatică pentru clasa a XII-a

<BODY>
<P> Acest paragraf este scris pentru a verifica
modul de aliniere pe orizontala in cazul unui
element IMG, care este de tip INLINE
<IMG src="Eric.jpg", alt="Eric">,
deci se insereaza exact ca un cuvant intr-un paragraf</P>
<P> Paragraful este un element de tip BLOC, asa ca se
insereaza pe o linie noua!</P>
</BODY>
</HTML>

Figura 4.79. Pagina web obţinută


Capitolul 4. HTML, CSS – primele noţiuni 155

4.19. Alte modalităţi de aşezare în pagină a


elementelor

În CSS există posibilitatea să se aşeze elementele în poziţiile dorite (alta


decât cea în cazul fluxului normal). Această posibilitate este dorită de mult timp de
către creatorii de pagini WEB. O astfel de aşezare se poate face prin utilizarea
atributului position, care poate lua mai multe valori:

 static – implicit – aşezarea se face în flux normal;

 absolute – aşezare în poziţii absolute – există, totuşi, anumite nuanţe,


motiv pentru care vom da mai multe exemple pentru a vă lămuri.

Exemplul 4.60. Un paragraf şi un tabel sunt aşezate în flux


normal. O celulă a tabelului conţine o imagine:
<P> Un text oarecare
<TABLE border=3>
<TR>
<TD> A11 </TD>
<TD id="Tata">
<IMG src="c:\Poze\cladire.jpg"></TD></TR>
<TR>
<TD> A21 </TD> <TD> A22 </TD></TR> Figura 4.80. Pagina web
</TABLE>

Exemplul 4.61. Adăugăm componentei IMG un stil, prin care-i precizăm poziţia.
Poziţia este dată în pixeli prin atributele top şi left. În acest caz, deplasarea este
dată faţă de colţul din stânga-sus al ferestrei:
<STYLE>
IMG {position:absolute; left:30; top:50;}
</STYLE>
...
<P> Un text oarecare
<TABLE border=3>
<TR>
<TD>A11</TD>
<TD id="Tata">
<IMG src="c:\Poze\cladire.jpg"></TD></TR>
<TR>
<TD>A21</TD> <TD>A22</TD></TR> Figura 4.81. Pagina web
</TABLE>

Pare simplu, nu-i aşa? În realitate, lucrurile sunt puţin mai complicate.
Aceasta se întâmplă atunci când elementul părinte este poziţionat în flux normal.
156 Manual de Informatică pentru clasa a XII-a

Exemplul 4.62. Elementul părinte al lui IMG este


elementul TD (nu TABLE). Poziţionăm absolut şi
elementul TD. Observăm că, în acest caz, elementul
apare în afara tabelului, iar IMG este poziţionat
relativ faţă de TD (vezi Fig. 4.82).

<STYLE>
IMG { position: absolute;
left:30; top:50; }
#Parinte_TD { position:absolute;
top:100; left:100; }
</STYLE>
...
<P> Un text oarecare
<TABLE border="3">
Figura 4.82. Pagina web
<TR>
<TD> A11 </TD>
<TD id="Parinte_TD">
<IMG src="c:\Poze\cladire.jpg"> A21 </TD> </TR>
<TR>
<TD>A21</TD> <TD>A22</TD> </TR>
</TABLE>
...

Ideea de bază este următoarea: dacă un element este poziţionat absolut şi dacă
părintele său, părintele părintelui, .... sunt poziţionate în flux normal, atunci
elementul este poziţionat în raport de colţul din stânga-sus al ferestrei. Dacă
parintele este poziţionat absolut, atunci elementul este poziţionat relativ faţă
de părinte.

Exemplul 4.63. De această dată, poziţionăm absolut


tabelul şi imaginea. Aşa cum era de aşteptat, imaginea
se aliniază în raport de colţul tabelului.
<STYLE>
IMG { position: absolute;
left:30px; top:50px; }
TABLE { position:absolute;
top:100px; left:100px; }
</STYLE>
</HEAD>
<BODY>
<P> Un text oarecare
<TABLE border=3> Figura 4.83. Pagina web
...

Observaţie ! Pentru poziţionarea absolută, orice element poziţionat în flux normal


se consideră că se află la coordonatele (0,0) faţă de părintele său. Cu această
constatare, un element este poziţionat, de fapt, relativ faţă de părinte.
Capitolul 4. HTML, CSS – primele noţiuni 157

 relative – spre deosebire de poziţionarea absolută, în cazul poziţionării


relative, un element este poziţionat în raport de elementul părinte, chiar şi în
cazul în care acesta din urmă este pozionat în flux normal.

Exemplul 4.64. Mai jos, elementul IMG este poziţionat


relativ faţă de elementul părinte (TD):

<HTML>
<HEAD>
<STYLE>
IMG { position: relative;
left:30px; top:50px; }
</STYLE>
</HEAD>
<BODY>
<P> Un text oarecare
<TABLE border="3"> Figura 4.84. Pagina web
<TR>
<TD>A11</TD>
<TD id="Parinte_TD">
<IMG src="c:\Poze\cladire.jpg"> A21 </TD> </TR>
<TR> <TD>A21</TD>
<TD>A22</TD> </TR>
</TABLE>
</BODY>
</HTML>

Observaţie ! Atributele pot lua şi valori negative.

4.20. Atributul z-index

Din studiul mecanismului de poziţionare a elementelor s-a putut distinge


faptul că există posibilitatea ca anumite elemente să fie afişate suprapus. Pe de o
parte, dacă nu dorim ca acest lucru să se întâmple, trebuie să fim atenţi la scrierea
coordonatelor, dar, pe de altă parte, putem face ca această posibilitate să lucreze
în interesul nostru. Mai mult, prin intermediul atributului z-index, putem controla
ordinea de afişare a elementelor suprapuse.

Exemplul 4.65. Un tabel are culoarea de fond galbenă, un altul are culoarea
albastră, iar în rest sunt identice. Primul tabel reţine pentru z-index, 1, iar al
doilea, 2. Cele două tabele sunt afişate parţial suprapus, dar deasupra se găseşte
cel care pentru z-index reţine 2 (vezi Fig. 4.85.a). Dacă se inversează valorile
reţinute de z-index pentru cele două tabele, atunci tabelele sunt afişate în ordine
inversă (vezi Fig. 4.85.b).
158 Manual de Informatică pentru clasa a XII-a

a) b)

Figura 4.85. Ordinea tabelelor în funcţie de atributul z-index

<HTML>
<HEAD>
<STYLE>
#tabel1 { position: absolute; top:100; left:100;
background-color:blue;
z-index:1; }
#tabel2 { position: absolute; top:120; left:120;
background-color:yellow;
z-index:2; }
</STYLE>
</HEAD>
<BODY>
<TABLE id="tabel1" border="3">
<TR>
<TD> A11 </TD>
<TD> <IMG src="c:\Poze\cladire.jpg"> A21 </TD>
</TR>
<TR>
<TD> A21 </TD> <TD> A22 </TD>
</TR>
</TABLE>
<TABLE id="tabel2" border="3">
<TR>
<TD> A11 </TD>
<TD> <IMG src="c:\Poze\cladire.jpg"> A21 </TD>
</TR>
<TR>
<TD> A21 </TD> <TD> A22 </TD>
</TR>
</TABLE>
</BODY>
</HTML>
Capitolul 4. HTML, CSS – primele noţiuni 159

4.21. Atributul display

Am învăţat faptul că în HTML există elemente de tip bloc (block), care se


afişează la început de rând şi singure pe linie şi elemente de tip text (inline) care
se afişează în continuarea rândului curent.

Există posibilitatea de a schimba modul implicit de afişare, prin utilizarea


atributului diplay. Acesta poate lua următoarele valori:

 Block – elementele se afişează la început de rând.

Exemplul 4.66. Un element de tip bold va fi afişat block,


deşi, implicit, se afişează inline:

<HTML>
<HEAD>
<STYLE>
B { display:block; }
</STYLE>
</HEAD> Figura 4.86. Element de tip bold
<BODY> afişat la început de rând
<P> Un <B>text</B> oarecare</P>
</BODY>
</HTML>

 Inline – elementele se afişează în continuarea rândului curent.

Exemplul 4.67. Implicit, paragrafele se afişează la început de rând (block). De


această dată, se afişează inline:

<HTML>
<HEAD>
<STYLE>
P { display:inline; }
</STYLE>
</HEAD> Figura 4.87. Element de tip paragraf afişat
<BODY> în continuarea randului curent
<P> Un text oarecare </P>
<P> Alt text oarecare </P>
</BODY>
</HTML>

 none – elementul (elementele) nu se va afişa.


160 Manual de Informatică pentru clasa a XII-a

4.22. Caractere HTML

În HTML există posibilitatea de introducere a caracterelor prin codul lor.


Astfel, putem folosi şi caractere care nu se obţin direct de la tastatură, cum ar fi:
semne matematice, litere greceşti, litere specifice limbii române, etc.

Exemplul 4.68. Pentru texte în limba română, putem introduce diacritice:

"Mama merge la piaţă"  Mama merge la pia&#355;&#259;


"Ţara mea este România"  &#354;ara mea este Rom&#226;nia
"O şopârlă"  O &#351;op&#226;rl&#259;

Exemplul 4.69. Pentru texte (formule) “matematice”:

"Aria cercului este πR "  Aria cercului este &#960R;<SUP>2</SUP>


2

"sin(ωt) "  sin(&#969;t)

Exemplul 4.70. Pentru semne speciale (se pot lăsa mai multe spaţii între cuvinte):

" Nu mai copiaţi..."  &#169; Nu mai copia&#355;i...


"Mama merge!"  mama&#160;&#160;&#160;merge

Observaţie ! Prin folosirea spaţiului, browser-ul nu va pune cele două cuvinte pe


linii diferite!

Exemplul 4.71. Evitarea confuziei de caractere pe care o poate face browser-ul


(caracterul "<" are un anumit sens în HTML).
Se afişează într-un paragraf, "m<v": <P> m&#60;V </P>.

Mai multe caractere puteţi găsi în Anexa 3.

Aplicaţie. Realizaţi pagina web de mai jos:

Figura 4.88. Pagină cu


caractere româneşti
Capitolul 4. HTML, CSS – primele noţiuni 161

4.23. Aspecte generale ale proiectării


interfeţelor web
Problema la care încercăm să răspundem în acest paragraf este următoarea:
cum este bine să arate o pagină web? Vă daţi seama că, la această întrebare, nu
se poate da un răspuns precis, dar se pot prezenta anumite reguli de care este
bine să ţineţi cont. Cel mai important este conţinutul paginii, care trebuie să fie
actualizat frecvent - el este cel care determină ca respectiva pagină să fie vizitată!

Haideţi să pornim de la un exemplu simplu: ştim noţiunile de bază ale


limbajului HTML şi un fotograf profesionist apelează la noi pentru un site care să-i
descrie simplu şi la obiect activitatea. Deoarece “clientul” nostru nu este şi nici nu
este necesar să fie familiarizat cu elementele tehnice, trebuie să-l întrebăm ce
informaţii doreşte să fie incluse pe site. În mod evident, acesta ne va spune că
doreşte să-şi prezinte lucrările anterioare (portofoliul), datele de contact, eventual o
scurtă descriere a sa şi a echipamentului pe care-l utilizează şi onorariul pentru
diversele servicii pe care le oferă. Reţinem toate informaţiile amintite anterior şi îi
cerem, de asemenea, o serie de fotografii pe care le consideră reprezentative.

Să trecem la treabă! În primul rând, informaţiile trebuie să fie bine


structurate, pentru ca vizitatorul să nu piardă timp la identificarea acestora. Din
prima discuţie cu “clientul”, am obţinut structura site-ului – ne trebuie o pagină
separată pentru fiecare categorie:
1. descrierea fotografului şi a activităţii pe care o profesează;
2. portofoliul care cuprinde o serie de fotografii de la diverse evenimente;
3. datele tehnice privitoare la dispozitivele fotografice, la studio, etc.;
4. preţurile în funcţie de serviciile oferite;
5. datele de contact (telefon fix, mobil, e-mail, adresa studioului, etc.);

Pentru a nu plictisi potenţialii vizitatori, pe pagina principală a site-ului (index-ul)


vom introduce prima categorie de informaţii, care vor oferi o prezentare generală
a activităţii “clientului”. De asemenea, accesul la celelalte pagini trebuie să fie facil,
de unde rezultă necesitatea unui meniu format din hiperlegături către acestea.

Site-ul web trebuie să urmărească un anumit tipar, pentru a oferi unitate şi


continuitate interfeţei. Rezultă că toate paginile trebuie să aibă părţi comune, cum
ar fi un antet, aceeaşi culoare de fond, acelaşi font, etc., iar meniul menţionat
anterior trebuie să fie prezent pe fiecare pagină. Multe ar putea fi spuse aici … de
exemplu, aveţi grijă să:

• evitaţi culorile stridente sau nepotrivite, animaţiile în exces şi mesajele


prin care i se explică vizitatorului că, apelând la serviciile oferite, “a dat
norocul peste el”;
162 Manual de Informatică pentru clasa a XII-a

• verificaţi din când în când dacă link-urile externe (care sunt binevenite)
spre paginile web indicate de acestea mai există sau nu;
• nu utilizaţi diverse efecte vizuale sau sonore, doar pentru a arăta
vizitatorlui ce grozavă este echipa care a creat site-ul – important este ca
ele să aibă sens în contextul paginii.
Ar fi dificil de prezentat modul de implementare complet al unui site web
pentru că necesită o multitudine de linii de cod şi ferestre. Pur didactic, prezentăm
o variantă mult simplificată a site-ului (pagina de contact), în figura de mai jos:

Figura 4.89. Exemplu simplu de site web

Titlul “Daniel Andone – fotograf profesionist” (element H2), poza din colţul din
dreapta-sus, meniul (tabel cu cinci coloane), culoarea de fond şi zona de text (în
figură, un tabel cu patru linii) se repetă pe fiecare pagină a site-ului, pentru a oferi
continuitate navigării. Practic, putem avea patru pagini aproape identice, singura
diferenţă fiind textul din zona de culoare albă.
Observaţie ! Tabelul care conţine informaţiile poate fi înlocuit cu un cadru de tip
IFRAME sau, de ce nu, toată pagina poate fi structurată cu ajutorul frame-urilor.

Bineînteles, acest exemplu este rudimentar şi trebuie luat ca atare. Dvs.


puteţi realiza pagini mult mai complexe, utilizând noţiunile prezentate în cadrul
acestui capitol.
Capitolul 4. HTML, CSS – primele noţiuni 163

Un ultim pas, foarte important, pe care-l aveţi de făcut este testarea cu


atenţie a documentului realizat. Nimic nu este mai deranjant decât o pagină care
nu poate fi deschisă sau o imagine care nu poate fi afişată – denotă lipsă de
profesionalism din partea realizatorului. Bineînţeles, nimeni nu este prefect!

Codul sursă pe care l-aţi implementat trebuie să fie bogat în comentarii cât
mai sugestive, pentru că, de cele mai multe ori, persoana care realizează site-ul
web nu este şi cel care-l “întreţine” în mod curent. Vă daţi seama cât de dificil ar fi
să caute prin sute de linii de cod sau să incerce să înţeleagă mecanismul dezvoltat
de dvs. …

Se pot realiza “minuni” prin utilizarea programelor profesioniste de prelucrare


a imaginilor, cum ar fi Adobe Photoshop sau Corel. De asemenea, o animaţie
haioasă dezvoltată cu programul Adobe (Macromedia) Flash poate să capteze
atenţia vizitatorilor în mod favorabil. Merită măcar o încercare …

Poţi fi un excelent programator web, dar dacă nu ai o anumită înclinaţie


artistică, nu vor ieşi “din mâinile tale” pagini frumoase. Apelează, dacă este cazul,
la persoane care au această înclinaţie artistică.

Pentru a crea o pagină web, avem nevoie de limbajul HTML care ne permite
introducerea elementelor de bază, iar cu ajutorul CSS-ului, acestea pot fi persona-
lizate din punct de vedere al aspectului sau a poziţiei în cadrul documentului.

Mai jos, sunt prezentate principalele elemente HTML:

Nume element(e) Descriere

<HTML> şi </HTML> indică începutul şi sfârşitul documentului web

<HEAD> şi </HEAD> indică începutul şi sfârşitul antetului

<BODY> şi </BODY> indică începutul şi sfârşitul corpului paginii

<STYLE> şi </STYLE> în interiorul lor, se descriu stilurile pentru elemente

<TITLE> şi </TITLE> în interiorul lor, se introduce titlul paginii web

<P> şi </P> indică începutul şi sfârşitul unui paragraf


<BR> forţează trecerea pe linia următoare
164 Manual de Informatică pentru clasa a XII-a

&nbsp evită trecerea unui cuvânt pe linia următoare

<B> şi </B> textul din interiorul lor este scris îngroşat

<I> şi </I> textul din interiorul lor este scris înclinat

<U> şi </U> textul din interiorul lor este scris subliniat

<S> şi </S> textul din interiorul lor este scris tăiat

<TT> şi </TT> textul din interiorul lor este scris monospaţiat

<SUP> şi </SUP> textul din interiorul lor este scris ca exponent

<SUB> şi </SUB> textul din interiorul lor este scris ca indice


<H1> şi <H/1>, …,
definesc titluri de diferite dimensiuni
<H6> şi </H6>
<OL> şi </OL> descriu o listă ordonată

<UL> şi </UL> descriu o listă neordonată

<LI> şi </LI> descriu un element al listei

<DL>, <DT> şi <DD> introduc o listă de definiţii

<IMG src="…"> introduce imaginea indicată prin parametrul src

<TABLE> şi </TABLE> indică începutul şi sfârşitul unui tabel

<TR> şi </TR> indică începutul şi sfârşitul unei linii din tabel

<TD> şi </TD> indică începutul şi sfârşitul unei coloane din tabel

<A href="…"> şi </A> hiperlegătură spre resursa indicată de atributul href

<MAP> şi <AREA> descriu o hartă imagine şi o zonă din ea


<BASE href="…"> defineşte adresa de bază pentru resurse
<META> furnizează diverse informaţii motoarelor de căutare

<FRAMESET> şi </F…> împarte pagina în mai multe cadre

<FRAME> şi </FRAME> precizează conţinutul unui cadru


<IFRAME> şi </IFRAME> creează un cadru în corpul documentului
<NOFRAME> şi </N…> conţinut alternativ al unui cadru
<MARQUEE> şi </M…> defineşte un bloc care defilează conţinutul său

Tabelul 4.1. Principalele elemente HTML


Capitolul 4. HTML, CSS – primele noţiuni 165

Fiecare element poate fi personalizat prin intermediul limbajului CSS,


definind stilul corespunzător între tag-urile <STYLE> şi </STYLE>. Putem defini o
clasă de stiluri (atributul class) sau un stil individual (atributul id).

Pentru un element, putem defini poziţia sa în cadrul paginii web:


- aşezare implicită: la nivel de bloc (block) sau la nivel de text (inline);

- prin CSS, cu ajutorul atributului position, care poate lua valorile:


• static – implicit – aşezarea se face în flux normal;
• absolute – aşezare în poziţii absolute;
• relative – în raport cu elementul părinte;

- definirea ordinii de afişare prin intermediul atributului z-index.

Modul implicit de afişare (block sau inline) se poate modifica prin


utilizarea atributului display, pus la dispoziţie de limbajul CSS.

La proiectarea unei interfeţe web, ţineţi minte că o structură bine definită,


bazată pe simplitate şi care să ofere accesul rapid la informaţie poate fi cheia
succesului. De asemenea, încercaţi să-i daţi o formă cât mai elegantă şi cu
bun gust!

1. Cum se scrie pagina


din figura alăturată?

Figura 4.90.
Pagina propusă
166 Manual de Informatică pentru clasa a XII-a

2. Cum trebuie procedat pentru ca


o pagină să arate ca alăturat?

Figura 4.91. Pagina


propusă ca exerciţiu

3. Cum realizăm tabelul


alăturat?

Figura 4.92. Pagina


propusă

4. Presupunem că doriţi să prezentaţi un calculator.


Pagina va cuprinde atât fotografia calculatorului cât şi un
nume pentru el (vezi Fig. 4.93). Atunci când vizitatorul
execută clic, fie pe imagine, fie pe text, trebuie ca
browser-ul să afişeze o altă pagină cu detalii tehnice şi
explicaţii suplimentare. Testul îl veţi face pe calculatorul
dvs. (dar nimeni nu vă opreşte să-l puneţi şi pe site).

Figura 4.93. Exemplu


de pagină

5. Puneţi pe pagină o astfel de imagine (din Yahoo) şi un


mesaj. Dacă vizitatorul paginii execută clic, fie pe mesaj, fie pe
imagine, va fi apelat programul de e-mail şi va putea să vă
scrie, fără să mai completeze adresa!

Figura 4.94. Exemplu


pentru exerciţiul 5

6. Doriţi ca vizitatorii site-ului dvs. să poată download-a o documentaţie pe care o


aveţi acolo sub forma unui fişier word (extensia .doc). Cum trebuie să procedaţi?

7. Presupunem că trebuie să realizaţi o prezentare a animalelor domestice. Pagina


principală va arăta ca în Fig. 4.95:
Capitolul 4. HTML, CSS – primele noţiuni 167

Figura 4.95. Pagina principală a prezentării

Un alt fişier HTML (să-l numim ”lung.html”) va reţine, unul după altul,
textele despre fiecare animal în parte. Se cere ca, atunci când vizitatorul execută
clic pe ”Continuare”, pentru un anumit animal, să apară direct textul cores-
punzător în fereastra care afişează textele. Mai jos, puteţi observa ce se afişează
atunci când acesta execută clic pe “Continuare” la descrierea câinelui:

Figura 4.96. Descrierea câinelui din pagina “lung.html”

8. Cum trebuie procedat ca o ancoră să arate ca mai jos (culoarea este roşie)?

Figura 4.97.
Ancora propusă

9. Doriţi să creaţi un site cu mai multe imagini grupate pe teme (flori, case, etc).
Pentru aceasta, pagina principală va conţine două cadre, aşa cum se vede în
Fig. 4.98. În primul dintre ele, aveţi ancore către documentele HTML care conţin
imaginile dintr-o anumită categorie. În al doilea cadru, veţi afişa fişierul dorit de
utilizator. Imaginile trebuie să fie aliniate în partea de jos.

Figura 4.98. Site-ul propus pentru problema 9


168 Manual de Informatică pentru clasa a XII-a

10. La fel ca la problema anterioară, numai că imaginile trebuie să arate ca în


figura de mai jos:

Figura 4.99. Exemple de imagini pentru problema 10

11. Lucru în echipă. Prin utilizarea cunoştinţelor dobândite până în acest moment,
realizaţi un site pe o temă la alegere. Formaţi grupe de 2-4 elevi care să-şi împartă
atribuţiile: un elev să se ocupe cu design-ul site-ului şi unul, doi sau trei elevi să
caute documentaţie despre tema propusă (text, imagini sugestive, etc.). Unul dintre
elevi, pe lângă atribuţiile sale, va avea rolul de coordonator al proiectului, iar un
altul, se va ocupa la final de testarea site-ului realizat.

Posibile teme:

 ”Sistemul nostru solar”: descrierea fiecărei planete, elemente de teorie


din astronomie, etc.
 ”Echipa de fotbal favorită”: informaţii despre fiecare jucător, o listă cu
titlurile câştigate, meciuri importante, etc.
 ”Clasa noastră”. Adunaţi câteva informaţii despre fiecare elev şi realizaţi
un site despre clasa voastră. Fiţi inventivi! Se pot realiza clasamente după
o mulţime de criterii sau puteţi descrie anumite evenimente amuzante care
s-au petrecut în trecutul vostru.
 “Ştiinţa înainte de toate!”. Prezentaţi un om de ştiinţă important: biografia
sa, poze, lucrări importante şi citate (de exemplu, puteţi alege dintre:
Albert Einstein, Sir Isaac Newton, Gregor Mendel, Marie Curie, etc.).
 “Istorie”. Realizaţi o pagină web despre ziua în care România a devenit un
stat independent, în urma bătăliei de la Plevna.
 “Geografie”. Prezentaţi în detaliu, sub forma unui site web, grupările
muntoase din ţara noastră, specificând informaţii semnificative despre
fiecare în parte.
 “Biologie”. Creaţi un site care să prezinte într-o formă amuzantă evoluţia
omului pe Pământ!
CAPITOLUL
Limbajul PHP

În acest capitol studiem limbajul PHP. După ce-l vom parcurge, vom şti să
trimitem date de pe calculatorul client către server şi vom şti să le prelucrăm
pe server. Vom cunoaşte cum să personalizăm paginile web, în funcţie de
persoana care le accesează, dar adevărata forţă a limbajului se va
vedea atunci când îl vom folosi la un loc cu limbajul MySQL.

 Introducere
 Cum realizăm un formular ?
 Constante, variabile, operatori
 Care sunt instrucţiunile limbajului PHP ?
 Funcţii PHP
 Funcţii “matematice”
 Cum afişăm datele ?
 Funcţii pentru prelucrarea şirurilor de caractere
 Masive în PHP
 Ce sunt variabilele cookie ? Cum le folosim ?
 Utilizarea în comun a limbajelor PHP şi MySQL
 Aplicaţii

Cuvinte cheie: formulare, input, submit, radio, checkbox,


password, textarea, select, constante, variabile, operatori,
echo, print, instrucţiuni, funcţii, masive, cookie, securitate
170 Manual de Informatică pentru clasa a XII-a

5.1. Introducere

Numele limbajului era iniţial un acronim pentru ”Personal Home Page” şi a fost
inventat în 1994 de Rasmus Lerdof, care dorea să-şi contorizeze vizitatorii paginii
sale de Internet. Astăzi, se cosideră că PHP este un limbaj de scriptare înglobat în
HTML. Documentaţia oficială a limbajului se găseşte pe site-ul www.php.net.

Script-urile scrise în acest limbaj se utilizează pe partea de server.

 Limbajul PHP este asemănător limbajului C.


 Script-urile scrise în acest limbaj rulează şi trebuie să se găsească pe
server. În linii mari, ele au rolul de a prelucra datele pe care le trimite
utilizatorul de pe propriul calculator şi de a transmite către browser
rezultatele prelucrărilor.
 Nu toate site-urile permit utilizarea limbajului PHP. Din acest motiv,
dacă vă interesează să-l utilizaţi, trebuie să studiaţi cu atenţie oferta de
site-uri a firmei la care apelaţi (provider-ul).
În ceea ce ne priveşte, pentru a învăţa limbajul PHP vom utiliza pachetul EasyPHP
(vezi Anexa 1) care ne permite să rulăm PHP pe propriul calculator. Nu uitaţi,
înainte de orice, lansaţi în executare programul EasyPHP din meniul Start/Programs!

 Practic, orice script PHP va fi memorat în subfolder-ul www al folder-ului


EasyPHP1-8 din Program Files şi va fi apelat din browser prin
”http://localhost.numescript”.
 Orice script PHP va avea extensia ”php”.

În situaţia în care rulaţi pe un site real, după ce creaţi şi testaţi script-urile pe


propriul calculator, cu EasyPHP, le puteţi transfera pe server cu ajutorul unui
program FTP.

⇒ Orice script PHP este cuprins între:

<?php
...
?>

Exemplul 5.1. Script-ul de mai jos


afişează un mesaj. Îl vom memora în www
sub numele de "primul.php". Apelul şi
rezultatul se pot observa alăturat.
<?php
echo "eu sunt primul script php";
?> Figura 5.1. Rezultatul
Capitolul 5. Limbajul PHP 171

Observaţie foarte importantă! Atunci când se apelează un script, el este rulat pe


server. Acesta va efectua operaţiile pe care le are programate şi eventual, va scrie
ceva (de exemplu, ca în exemplul următor, cu "echo"). Rezultatul (adică ce este
scris) este returnat către browser, iar acesta îl va trata ca pe un fişier html.

Exemplul 5.2. Rulăm script-ul de mai jos


care conţine câteva elemente de
formatare. Rezultatul îl vedem în figura
alăturată:

<?php
echo "eu sunt <B>primul</B><BR>
script<B>php</B>";
?>
Figura 5.2. Rezultatul rulării

Exemplul 5.3. Acelaşi script poate fi apelat şi ca un link, aşa cum observaţi mai jos
(fişierul html putând fi plasat oriunde):
<HTML>
<HEAD></HEAD>
<BODY>
<P> Un text oarecare!
<A href="http://localhost/primul.php">Apeleaza</A>
</BODY>
</HTML>

Exemplul 5.4. Script-urile PHP pot conţine direct elemente de HTML, pe lângă
secvenţa propriu-zisă, PHP. Scrieţi script-ul următor în www şi apelaţi-l. Veţi vedea
că se afişează conţinutul unei variabile PHP (variabilele PHP vor fi tratate separat).
La apel se afişează "Bine ati venit domnule Ion Popescu!".

<HTML>
<HEAD>
</HEAD>
<BODY>
<P> Bine ati venit domnule
<?php
$nume=" Ion Popescu!";
echo ($nume);
?>
</BODY>
</HTML>
172 Manual de Informatică pentru clasa a XII-a

5.2. Formulare

De la început trebuie spus că formularele sunt elemente ale limbajului HTML.


Un formular este o grupare de componente HTML care permit trimiterea datelor şi a
comenzilor către server. Pe server, comenzile sau datele sunt recepţionate de un
script PHP care răspunde comenzilor şi prelucrează datele.

Un formular se descrie între tag-urile <FORM action script> şi </FORM>.


Prin script înţelegem numele script-ului care se rulează atunci când datele,
comenzile sosesc pe server. Între cele două tag-uri se inserează diferite
componente care permit introducerea datelor sau trimiterea comenzilor.

Elementul INPUT – este un element HTML de o mare complexitate. Poate fi de


diverse tipuri (type): de la un buton de validare, la unul radio, un edit, etc. După
cum sugerează şi numele, rolul elementului INPUT este de a permite utilizatorului
să introducă date sau comenzi în pagina vizualizată de browser. Un element
INPUT se descrie cu tag-ul următor (formă simplificată):

<INPUT name="nume" type="tip"


value="valoare"
align="tip_aliniere">
unde valoare exprimă valoarea afişată de element.

5.2.1. Tipul “submit”

Are aspectul unui buton. La apăsarea lui, datele sunt transmise către server,
de unde, evident, răspunde un script care are rolul de a le prelucra.
Exemplu 5.5. Nu se transmit date, dar la apăsarea butonului de tip submit se
lansează un script care afişează un mesaj:
<HTML>
<HEAD>
</HEAD>
<BODY>
<FORM action="http://localhost/exemplu.php">
<INPUT type="submit" value="Primul exemplu de apel PHP">
</FORM>
</BODY>
</HTML>

Alăturat, observaţi cum este afişată sursa


HTML de către browser:

Figura 5.3. Fişierul HTML


Capitolul 5. Limbajul PHP 173

Iată şi script-ul PHP:


<?php
echo ("Ai apasat, am raspuns"); Figura 5.4. Mesajul afişat
?>

În urma rulării, browser-ul afişează mesajul (vezi Fig. 5.4).

5.2.2. Tipul “text”

Este sub forma unui edit şi permite utilizatorului să introducă date. Acestea
se trimit către browser la apăsarea unui buton de tip submit. Pentru ca datele să
fie recuperate de către script-ul de pe server, trebuie ca tag-ul <form> să conţină
parametrul method ="post".

Atunci când browser-ul execută o cerere către server, trimite şi valorile


reţinute de cele două input-uri de tip text. Variabila $_POST este un vector
1
asociativ care reţine toate valorile astfel transmise. Valoarea transmisă de input-ul
de tip text numit a se recuperează prin $_POST[‘a’], cea transmisă de input-ul
de tip text b se recuperează prin $_POST[‘b’]. Această modalitate de
transmitere şi recepţionare a parametrilor este generală şi trebuie reţinută.
Exemplul 5.6. Vizitatorul trimite două valori numerice
a şi b. Script-ul PHP returnează suma lor:
<HTML>
<HEAD> Figura 5.5. Exemplu
</HEAD> de formular
<BODY>
<FORM action="http://localhost/exemplu.php" method ="post">
<INPUT type="text" name="a"><BR>
<INPUT type="text" name="b"><BR>
<INPUT type="submit" value="Suma?">
</FORM>
</BODY>
</HTML>

Sursa este vizualizată de către browser, aşa


cum puteţi observa în Fig. 5.5. Script-ul PHP
care afişează suma celor două numere este:
<?php
// recuperarea datelor
$a=$_POST['a'];
$b=$_POST['b'];
echo $a+$b; Figura 5.6. Rezultatul retransmis spre browser
?>
 În PHP, variabilele încep cu caracterul ”$”.

Vectorii asociativi sunt trataţi în cadrul acestui capitol.


1
174 Manual de Informatică pentru clasa a XII-a

5.2.3. Tipul “radio”

Tipul radio (butoane radio) se utilizează în cazul în care utilizatorul trebuie să


aleagă o singură opţiune dintre mai multe posibile. Pentru fiecare buton radio se
ataşează câte un element input de tip radio. Pentru a avea un comportament de
grup, în sensul că se poate bifa un singur buton, toate butoanele trebuie să aibă un
singur nume, în exemplul de mai jos, Buton. Opţional, pentru un buton se poate
folosi opţiunea checked şi efectul este acela că de la început butonul este bifat.
La apăsarea butonului submit, butonul bifat va trimite valoarea ataşată lui.

Exemplul 5.7. Utilizatorul trebuie să bifeze un singur buton


radio, iar pe server “se va şti”, în funcţie de valoarea primită,
care buton a fost apăsat:
<HTML> Figura 5.7. Formular
<HEAD> cu butoane radio
</HEAD>
<BODY>
<FORM action="http://localhost/exemplu.php"
method ="post">
<P> Cumpar ziarul ...
<BR><BR>
<INPUT name="Buton" TYPE="radio" value=1 checked> zilnic <BR>
<INPUT name="Buton" TYPE="radio" value=2> saptamanal <BR>
<INPUT name="Buton" TYPE="radio" value=3> lunar<BR><BR>
<INPUT type="submit" value="Trimite">
</FORM>
</BODY>
</HTML>

Script-ul PHP şi rezultatul afişat:


<?php
$b=$_POST['Buton']; Figura 5.8. Afişarea
echo $b; rezultatului
?>

5.2.4. Tipul “checkbox”

Acest tip se utilizează pentru ca în fereastra browser-ului să fie afişate


butoane de marcare. Aceste butoane sunt utilizate pentru a permite utilizatorului să
marcheze una, niciuna sau mai multe opţiuni. De reţinut: în acest caz, se transmit
către server doar valorile butoanelor marcate.

Exemplul 5.8. În continuare, observaţi modul în care facem ca browser-ul să


afişeze butoanele de marcare şi script-ul PHP care depistează butoanele marcate:
Capitolul 5. Limbajul PHP 175

<FORM
action="http://localhost/exemplu.php"
method="post">
<P> Urmaresc postul tv </P>
<INPUT NAME="buton1" TYPE="checkbox"
value=1 checked> Realitatea <BR>
<INPUT NAME="buton2" TYPE="checkbox"
value=2> Antena 3 <BR>
<INPUT NAME="buton3" TYPE="checkbox"
value=3> Protv <BR><BR>
<INPUT type="submit" value="GO">
</FORM>

Figura 5.9. Formularul


<?php
foreach ($_POST AS $i=>$nume)
if ($i=="buton1") echo "Realitatea"."<BR>";
else
if ($i=="buton2") echo "Antena 3" ."<BR>";
else
if ($i=="buton3") echo "Protv";

Figura 5.10. Rezultatul

5.2.5. Tipul “password”

Componentele vizuale de acest tip se utilizează pentru introducerea


parolelor, atât de necesare, de exemplu, pentru a avea acces la un site. Sunt
asemănătoare cu cele de tip text, numai că, pentru fiecare caracter al parolei se
afişează câte un “*”. Desigur, către server, datele sunt transmise corect.

Exemplul 5.9. Se introduce o parolă, iar script-ul


care o primeşte o afişează:

<FORM
action="http://localhost/exemplu.php"
method="post">
<P> Introduceti parola </P> Figura 5.11. Formularul
<INPUT NAME="parola" TYPE="password" <BR>
<INPUT type="submit" value="GO">
</FORM>

<?php
echo $_POST['parola'];
?>
Figura 5.12. Rezultatul
176 Manual de Informatică pentru clasa a XII-a

5.3. Elementul TEXTAREA


Elementul TEXTAREA se utilizează pentru a introduce un text mai lung. El
poate fi folosit în interiorul unui formular şi, la apăsarea butonului submit,
conţinutul său este transmis către server. De remarcat este că pentru un element
TEXTAREA se pot preciza numărul de linii (rows) şi de coloane (cols) pe care
acesta să le afişeze.
Exemplul 5.10.
<FORM action="http://localhost/exemplu.php" method="post">
<P>Adaugati comentariul dv.!</P>
<TEXTAREA name="textul" rows="10"
cols="20></TEXTAREA><BR><BR>
<INPUT type="submit" value="Scrie">
</FORM>
Iată şi script-ul PHP care afişează şirul trimis:
<?php
echo $_POST['textul'];
?>

Figura 5.13. Rezultatul Figura 5.14. Formularul

5.4. Elementul SELECT


Elementul SELECT se utilizează pentru ca browser-ul să
afişeze o listă. Fiecare opţiune din listă este marcata de un
element OPTION. Dacă este introdusă într-un formular, către
server se va transmite opţiunea selectată.
Figura 5.15.

Exemplul 5.11. Mai jos este prezentat formularul care afişează lista din figura de
mai sus şi script-ul PHP care afişează opţinea selectată din formular:
<FORM action="http://localhost/testare.php" method="post">
<SELECT name="lista">
<OPTION value="optiunea 1"> Optiunea 1 </OPTION>
<OPTION value="optiunea 2"> Optiunea 2 </OPTION>
Capitolul 5. Limbajul PHP 177

<OPTION value="optiunea 3"> Optiunea 3 </OPTION>


</SELECT><BR>
<INPUT type="submit" value="GO">
</FORM>
Scriptul PHP este:
<?php
$v=$_POST["lista"];
echo $v;
?>

5.5. Constante. Variabile. Operatori

5.5.1. Constante

În PHP se pot defini constante cu ajutorul funcţiei define. Forma generală


a acesteia este:
define("nume_constanta", valoare).
Exemplul 5.12. În script-ul următor se defineşte constanta e şi se probează dacă
este recunoscută. La apel, se afişează 5.42:
<?php
define( "e", 2.71);
echo (e+e);
?>

5.5.2. Variabile

În PHP numele unei variabile începe cu $. În continuare, trebuie să fie o literă


sau o liniuţă de subliniere. În rest, puteţi folosi şi cifre.
⇒ Nu este necesar ca variabilele să fie declarate de la început. Ele se definesc
atunci când sunt folosite. Mai mult, îşi schimbă tipul în funcţie de valoarea
reţinută.
Exemplul 5.13. Analizaţi script-ul următor: iniţial, variabila $x reţine 1. Apoi, i se
atribuie un şir de caractere. Operaţia este posibilă şi în urma ei se reţine şirul, aşa
cum rezultă din valoarea afişată:
<?php
$x=1;
$y="Un sir";
$x=$y;
echo ($x);
?>
178 Manual de Informatică pentru clasa a XII-a

⇒ În PHP este posibilă şi adresarea indirectă, aşa cum rezultă din exemplele
următoare.

Exemplul 5.14. Se afişează 3. Didactic, putem stabili ceea ce se afişează, astfel:


$$x = $($x) = $y = 3.
<?php
$x="y";
$y=3;
echo ($$x);
?>

Exemplul 5.15. Se afişează "Un sir". Astfel, avem:


$$$z = $$($z) = $$y= $($y) = $x = "Un sir".
<?php
$x="Un sir";
$y="x";
$z="y";
echo ($$$z);
?>

5.5.3. Operatori

Mulţi dintre operatorii limbajului PHP sunt cunoscuţi din C++. Acesta este
motivul pentru care vom prezenta doar anumite particularităţi specifice limbajului.
Pentru început, prezentăm, în ordine descrescătoare, prioritatea operatorilor:

1. !, ++, --, (int), (double), (string);


2. *, %, /;
3. <. <=, >, >=;
4. ==, !=, ===, !=== ;
5. &;
6. ^;
7 &&;
8. ?:;
9. =, +=, -=, /=. *=, %=, &=, |=, ^=;
10. And;
11. Xor;
12. Or;
13 ,.
Capitolul 5. Limbajul PHP 179

⇒ În PHP se pot folosi operatori de conversie explicită, cunoscuţi din C++. Ca


şi în C++, ei se aplică prefixat. Astfel, există: (int) - conversie către o
valoare întreagă, (string) - conversie către şir, iar (double) - conversie
către real.

Exemplul 5.16. Conversia unui număr real către un întreg are ca efect eliminarea
zecimalelor. Script-ul următor afişează valoarea 7:
<?php
$x=1;
$y=7.5;
$x=(int)$y;
echo ($x);
?>

Exemplul 5.17. Conversia unui şir către un întreg reuşeşte chiar dacă şirul conţine
şi caractere nenumerice! Caracterele numerice trebuie să ocupe primele poziţii! În
exemplul următor, în urma conversiei, x va reţine 2 şi y va reţine 3. Se afişează
suma, adică 5.
<?php
$x=" 2 siruri";
$y="3siruri";
$x=(int)$x;
$y=(int)$y;
echo ($x+$y);
?>

Observaţie ! Uneori, conversiile se realizează implicit (fără utilizarea operatorului


de conversie explicită).

Exemplul 5.18. Script-ul următor afişează -1.76:


<?php
$x="-2.76"; // sir
echo (1+$x);
?>
Exemplul 5.19. Se afişează -1:
<?php
$x="-2.76"; // sir
$y="1.76";
echo ($x+$y);
?>
Exemplul 5.20. Se afişează ... tot –1:
<?php
$x="-2.76 tren";
$y="1.76masina";
echo ($x+$y);
?>
180 Manual de Informatică pentru clasa a XII-a

⇒ După efectuarea unei operaţii cu un operator din grupele 3 sau 4, se obţine


o valoare logică: true (1) sau false (0).

⇒ Operatorul === se referă la egalitate ca valoare şi ca tip, spre deosebire de


== care se referă la egalitate doar ca valoare. Exemplele următoare vă vor
convinge.

Exemplul 5.21. Script-ul următor afişează “egali ca valoare”:


<?php
$x="3";
$y=3;
if ($x===$y) echo(" egali ca valoare si tip");
else
if ($x==$y) echo ("egali ca valoare");
else echo "inegali ca valoare";
?>

Înlocuiţi în script-ul anterior primele două atribuiri cu atribuirile de mai jos. Veţi
observa că se afişează numai “egali ca valoare”. Aceasta demonstrează că,
deşi valorile logice au reţin 1 sau 0, ele rămân, de fapt, valori logice!
$x=2>1;
$y=1;

Observaţie ! Se poate deduce cu uşurinţă rolul operatorului !==. Operaţia pe care


o efectuează returnează true, dacă este diferenţă între tip sau valoare şi false,
în caz contrar.

⇒ Este permisă atribuirea multiplă.

Exemplul 5.22. Script-ul următor afişează “un sir”:

<?php
$x=1;
$y=-2;
$z="un sir";
$x=$y=$z;
echo ($x);
?>

⇒ Diferenţa dintre || şi Or, && şi And, ^ şi Xor este doar de prioritate!


Capitolul 5. Limbajul PHP 181

5.6. Instrucţiunile limbajului PHP

Instrucţiunile PHP sunt asemănătoare celor din C/C++. Din acest motiv, ne
vom limita la o scurtă prezentare a lor şi la câteva exemple de utilizare. Pentru
exemplificare, vom folosi următorul document HTML care trimite o valoare x către
server. Pe server se va găsi un script, numit ”index.php”, care răspunde
trimiţând o valoare către browser.

<HTML>
<HEAD>
</HEAD>
<BODY>
<FORM action="http://localhost" method="post">
<INPUT type="text" name="x"> <BR><BR>
<INPUT type="submit" value="GO">
</FORM>
</BODY>
</HTML>

5.6.1. Instrucţiunea expresie

Se foloseşte pentru diverse calcule sau atribuiri.


Exemplul 5.23. Analizaţi instrucţiunea: $x=$y*$y+1;.

5.6.2. Instrucţiunea IF

Această instrucţiune are forma generală:

if (expresie) instructiune1
else instructiune2

Dacă expresie produce la evaluare o valoare diferită de 0 (true), se execută


instructiune1, altfel se execută instructiune2.

Exemplul 5.24. Dacă valoarea este în intervalul [1,2], se transmite către browser
valoarea (x+1)/2, altfel se transmite valoarea (x-1)/2:

<?php
if ($x>=1 && $x<=2) $v=($x+1)/2;
else $v=($x-1)/2;
echo ($v);
?>
182 Manual de Informatică pentru clasa a XII-a

5.6.3. Instrucţiunea compusă

Atunci când dorim ca mai multe instrucţiuni să fie interpretate ca una singură,
instrucţiunile se trec între "{" şi "}". Instrucţiunea switch are forma generală:
switch (expresie)
{
case exp1: secventa instructiuni1; break;
case exp2: secventa instructiuni2; break;
...
case expn: secventa instructiunin; break;
[default: secventa instructiunin+1];
}
unde expresie are semnificaţia: expresie de tip întreg, expi sunt expresii
constante de tip întreg, iar instrucţiunii, o secvenţă oarecare de instrucţiuni.

Principiul de executare este:


• se evaluează expresia;
• dacă aceasta produce o valoare egală cu cea produsă de expi, se
execută, în ordine, instrucţiunii şi se trece la instrucţiunea
următoare, altfel se execută numai secvenţa instrucţiunin+1.

Observaţie ! Alternativa default este facultativă. În absenţă, în cazul în care nu


există coincidenţă de valori, se trece la instrucţiunea următoare.
Exemplul 5.25. Dacă valoarea transmisă pentru x este 1, 2, 3, 4, atunci valoarea
respectivă este retransmisă către utilizator alfabetic, altfel, se va transmite un mesaj
oarecare.
<?php
switch ($x)
{
case (1): echo(“unu”); break;
case (2): echo(“doi”); break;
case (3): echo(“trei”); break;
case (4): echo(“patru”); break;
default : echo (“Nu este 1, 2, 3 sau 4”);
}
?>

5.6.4. Instrucţiunea FOR

Instrucţiunea for are forma generală:


for(expresieiniţializare;expresietest;expresieincrementare) instrucţiune
Capitolul 5. Limbajul PHP 183

După cum se vede, între paranteze se găsesc 3 expresii:


• Expresieinitializare se foloseşte, de regulă, pentru iniţializarea variabilei de
ciclare.
• Expresietest se foloseşte pentru a testa dacă se execută instrucţiunea
subordonată - dacă expresia produce la evaluare o valoare diferită de 0
(true), instrucţiunea subordonată for se execută.
• Expresieincrementare se foloseşte pentru incrementarea variabilei de
ciclare.
Principiul de executare este:

P1. Se evaluează expresieiniţializare.


P2. Se evaluează expresiatest. În cazul în care aceasta produce o valoare
diferită de 0, se execută instrucţiunea subordonată for; apoi se trece la P3,
altfel se trece la instrucţiunea următoare (se termină executarea instrucţiunii for).
P3. Se evaluează expresia de incrementare şi se revine la P2.
Exemplul 5.26. Se calculează suma pătratelor primelor x numere naturale (x este
număr natural):
<?php
$s=0;
for ($i=1;$i<=$x;$i++) $s+=$i*$i;
echo($s);
?>

5.6.5. Instrucţiunea WHILE

Instrucţiunea while are forma generală:


while (expresie) instructiune
Principiul de executare este următorul:

P1. Se evaluează expresia;


P2. Dacă valoarea produsă de aceasta este diferită de 0, se execută instrucţiu-
nea subordonată, apoi se revine la P1, altfel se trece la instrucţiunea următoare.
Exemplul 5.27. Se calculează suma de la exemplul anterior:
<?
$s=0; $i=1;
while ($i<=$x)
{ $s+=$i*$i;
$i++;
}
echo($s);
?>

Observaţie ! Script-ul oferă şi un exemplu de instrucţiune compusă.


184 Manual de Informatică pentru clasa a XII-a

5.6.6. Instrucţiunea DO WHILE

Forma generală a acestei instrucţiuni este următoarea:


do
instructiune
while(expresie);

Principiul de executare este următorul:


P1. Se execută instrucţiunea subordonată;
P2. Se evaluează expresia. În cazul în care valoarea produsă la evaluare este
0 (false), executarea instrucţiunii do se termină, altfel se trece la P1.

Exemplul 5.28. Se calculează suma pătratelor primelor x numere naturale (x este


natural):
<?php
$s=0; $i=1;
do
{
$s+=$i*$i;
$i++;
} while ($i<=$x);
echo($s);
?>

5.7. Funcţii în PHP


În PHP se pot crea funcţii fără prea mari diferenţe faţă de ce ştim din C/C++.

Exemplul 5.29. Mai jos este prezentat un script care utilizează o funcţie pentru a
calcula aria unui triunghi, pe care apoi o afişează:
<?php
function aria_t($b, $h)
{ return $b*$h/2; }

$x=3;
$y=8;
echo(aria_t($x,$y));
?>

⇒ Pentru a întoarce rezultate se utilizează, aşa cum suntem deja obişnuiţi,


return. Forma generală este: return expresie.

⇒ Transmiterea parametrilor se face prin valoare şi prin referinţă.


Capitolul 5. Limbajul PHP 185

A) Dacă un parametru este transmis prin valoare, atunci valoarea sa rămâne


neschimbată după executarea funcţiei. Prin valoare se pot transmite atât valori, cât
şi conţinutul unor variabile.
Exemplul 5.30. Script-ul următor afişează 5, chiar dacă în funcţie s-a încercat
modificarea valorii transmise:
<?php
function f($x)
{ $x++; }
$x=5;
f($x);
echo($x);
?>
Exemplul 5.31. Script-ul următor exemplifică faptul că o funcţie poate fi apelată
atât printr-o valoare care este conţinutul unei variabile, cât şi printr-o valoare
oarecare. Se afişează 3 şi 7, deci 37.
<?php
function f($x)
{ echo($x); }
$x=3;
echo(f($x));
echo (f(7));
?>

B) Dacă un parametru este transmis prin referinţă atunci, în corpul funcţiei, se


poate modifica valoarea sa. Evident, un parametru transmis prin valoare trebuie să
fie o variabilă. Pentru a transmite un parametru prin referinţă, el trebuie precedat
de caracterul &.
Exemplul 5.32. În script-ul următor, se modifică valoarea parametrului transmis
prin referinţă. Se va afişa 6, nu 5, cât era valoarea iniţială a variabilei $x:
<?php
function f(&$x)
{ $x++; }
$x=5;
f($x);
echo($x);
?>

⇒ O variabilă se numeşte globală dacă a fost definită în afara oricărei funcţii.


Implicit, ea nu poate fi adresată din corpul unei funcţii. Totuşi, există o
posibilitate de a face acest lucru: ataşăm cuvântul global înaintea acestei
variabile!
Exemplul 5.33. Funcţia din script-ul următor returnează 3. Aceasta arată că a fost
recunoscută variabila globală $x. În absenţa cuvântului global, această valoare
nu ar fi putut fi returnată:
186 Manual de Informatică pentru clasa a XII-a

<?php
function f()
{ global $x;
return $x;
}
$x=3;
echo(f());
?>

⇒ Variabilele locale sunt variabile create în corpul unei funcţii sau cele create
prin transmiterea parametrilor formali (din antetul funcţiilor). Ele nu sunt
recunoscute în afara funcţiilor. Nimic nou...

⇒ În PHP, funcţiile pot fi şi recursive.

Exemplul 5.34. Script-ul de mai jos calculează n! prin utilizarea unei funcţii
recursive:
<?php
function fact($n)
{ if ($n==0) return 1;
else return $n*fact($n-1);
}
echo(fact(4));
?>
Desigur, atunci când scriem un script mai complicat, cu multe funcţii, este necesar
să dispunem de un mecanism prin care să putem include funcţii pe care le-am
scris mai demult, sau pe care le-am primit de undeva...

⇒ Includerea unor funcţii, dar nu numai, se realizează prin funcţia


require("nume_fisier").
Funcţiile trebuie să se găsească pe site, într-un fişier text. Observaţi faptul
că textul funcţiei (funcţiilor inserate) trebuie să fie încadrat între <? şi ?>.
Exemplul 5.35. Funcţia afis() se găseşte în fişierul functia.ex, aflat pe site.
Script-ul care o utilizează conţine require():
<?php
function afis()
{ echo("Eu sunt functia inserata"); }
?>
<?
require("functia.ex");
afis();
?>

Pe lângă faptul că putem să scriem diverse funcţii, limbajul PHP este


înzestrat cu numeroase alte funcţii. Cele mai importante vor fi tratate pe parcurs.
Capitolul 5. Limbajul PHP 187

5.8. Funcţii “matematice”

Multe dintre funcţiile prezentate le-aţi întâlnit dacă aţi studiat limbajul C/C++.
Tabelul următor le prezintă succint:

Funcţia Ce realizează Exemple


abs(-7)=7;
abs(numar) Returnează modulul
abs(-2.23)=2.23;
numărului.
abs(2.3)=2.3
Sinusul, cosinusul şi
sin(x), cos(x), tangenta unui unghi.
tan(x) Argumentul x este dat
în radiani
Returnează ex .
.
exp(x)

pow(x,y) Returnează xy.

Returnează log10 ( x) ,
log10(x), log(x)
respectiv log 2 ( x) .
Returnează maximul,
max(x1, x2,... xn),
minimul dintr-un şir de
min(x1, x2,... xn)
argumente numerice.
Returnează cel mai mic
ceil(4.3)=5,
ceil(x) întreg mai mare sau
ceil(-4.3)=-4
egal cu x.
Returnează întregul
round(4.3)=4,
round(x) rezultat prin rotunjirea
round(4.7)=5.
lui x.
Returnează cel mai
floor(4.3)=4,
floor(x) mare întreg mai mic sau
floor(-4.3)=-5
egal cu x.
Returnează o valoare
rand(1,10) poate
întreagă aleatoare între
rand(min,max) returna orice valoare
valorile întregi min şi
întreagă din [1,10].
max (inclusiv).
pi() Returnează numărul π.
Returnează rădăcina
sqrt(x) sqrt(4)=2;
pătrată a lui x.

Tabelul 5.1. Funcţii “matematice”


188 Manual de Informatică pentru clasa a XII-a

5.9. Afişarea datelor - echo şi print

Pentru a afişa datele pe browser se folosesc echo şi print. Acestea nu


sunt funcţii în accepţiunea clasică a cuvântului, deşi pot fi utilizate asemenea
funcţiilor. Ele sunt construcţii speciale PHP. Ambele afişează şiruri de caractere.

A) echo – datorită simplităţii, a fost utilizată de multe ori până acum. Pentru că
poate fi utilizată în multe feluri, o vom prezenta prin exemple şi vom renunţa la
prezentarea formei generale.

Exemplul 5.36. Afişăm un şir de caractere folosind parantezele rotunde (apel ca în


cazul funcţiilor):
echo("Un mesaj");

Exemplul 5.37. Afişăm un şir de caractere fără să utilizăm parantezele rotunde.


Pentru că este permisă o astfel de utilizare, spunem că echo nu este funcţie, ci
construcţie specială.
echo "Un mesaj";

Exemplul 5.38. În cazul în care nu se folosesc paranteze, se pot afişa mai multe
şiruri de caractere:
echo "Un mesaj ", "Alt mesaj";

Exemplul 5.39. Putem afişa şi conţinutul unor variabile, aşa cum rezultă din
exemplul următor:
<?php
$x=6;
echo ("Am $x mere"); // sau echo "Am $x mere";
?>

B) print – se utilizează la fel ca echo, dar, dacă utilizăm paranteze, se poate


folosi valoarea întoarsă: true, dacă şirul a fost expediat sau false, în caz contrar.

Exemplul 5.40. Priviţi exemplul de mai jos:


print ("Un exemplu");
<?php
$x=6;
$y=8;
print ("Ana are $x mere si <BR> $y pere");
?>

Observaţie ! ”<BR>” se utilizează pentru salt la linie nouă! Vezi HTML...


Capitolul 5. Limbajul PHP 189

Observaţii foarte importante !


1. În loc de “” se pot folosi şi ‘’. Diferenţa este dată de faptul că, în cazul folosirii
‘’, dacă şirul de caractere conţine numele unei variabile, nu se afişează conţinutul
variabilei, ci se afişează numele variabilei.

Exemplul 5.41. Dacă comanda este echo ‘Am $x mere’ se va afişa


Am $x mere.

2. Nu se pot folosi “” incluse între “” şi nici ‘’ incluse între ‘’.

Exemplul 5.42. Secvenţele de mai jos sunt incorecte:


echo " Am “o multime” de prieteni";
echo ‘ Am 'o multime' de prieteni’;

3. În schimb, putem include între “” caracterele ‘’.

Exemplul 5.43. Instrucţiunea următoare


echo " Am 'o multime' de prieteni";
afişează
Am ‘o multime’ de prieteni.

4. În schimb, putem include între ‘’ caracterele “”.

Exemplul 5.44. Instrucţiunea următoare


echo ‘ Am “o multime” de prieteni’;
afişează
Am “o multime” de prieteni.

5.10. Funcţii pentru prelucrarea şirurilor de caractere

În PHP există un set puternic de funcţii, asemănătoare celor din C++, care
lucrează cu şiruri de caractere. De asemenea, există şi un operator de
concatenare a şirurilor.

⇒ Şirurile se memorează ca o succesiune de caractere ASCII. Putem adresa


fiecare caracter al şirului, aşa cum suntem obişnuiţi, prin indicele său. Primul
caracter are indicele 0.

Exemplul 5.45. În secvenţa următoare, se afişează caracterul “U”:


$sir="Un exemplu";
echo ($sir[0]);
190 Manual de Informatică pentru clasa a XII-a

⇒ Operatorul de concatenare a şirurilor este punctul.

Exemplul 5.46. Se afişează "Ana are 9 mere!". Observaţi faptul că valoarea


numerică a fost convertită implicit către şir.
$x=9;
$sir="Ana ". "are ". $x. " mere!";
echo $sir;

⇒ Funcţia strlen(sir) returnează lungimea şirului (numărul de caractere


ale şirului).

Exemplul 5.47. În secvenţa de mai jos se afişează 10 (se numără şi blank-ul):


$sir="Un exemplu";
echo strlen($sir);

⇒ funcţia strpos(sir1, sir2, [poz_start]) caută dacă sir2 este


subşir al lui sir1. În caz afirmativ, returnează poziţia de început a acestuia,
altfel returnează false. Al treilea parametru specifică funcţiei indicele
caracterului de unde să înceapă căutarea. Dacă nu este completat, căutarea
începe din poziţia 0.

Exemplul 5.48. La executarea secvenţei următoare, se afişează 5:


$sir="Un exemplu";
echo (strpos($sir, "em"));

 Funcţia se utilizează şi pentru a testa dacă un şir include sau nu un anumit


subşir. Dacă subşirul este găsit, se returnează poziţia de început a acestuia
în subşir, dacă nu, se returnează false. După cum ştim, valoarea lui false
este, de fapt, 0. Ce ne facem în cazul în care subşirul se găseşte şi începe
în poziţia 0? Cum facem distincţia între acest caz şi cel în care subşirul nu
este găsit? Priviţi secvenţa din exemplul de mai jos, care rezolvă corect
problema şi subliniază importanţa operatorului “===”.

Exemplul 5.49. Secvenţa este următoarea:


<?php
$sir="Un exemplu";
$gasit=strpos($sir, "U");
if ($gasit===false) echo ("Nu este");
else echo ("Este");
?>

Valoarea întoarsă de funcţie este reţinută de variabila $gasit. Pentru a face


distincţie între false şi 0, se foloseşte operatorul “===”, care testează
coincidenţa atât ca valoare, cât şi ca tip. De altfel, acesta este şi rostul unui astfel
de operator. Acest procedeu se poate folosi şi pentru alte funcţii.
Capitolul 5. Limbajul PHP 191

⇒ Funcţia strstr(sir1,sir2) returnează sir1 din poziţia în care a fost


găsit sir2, dacă sir2 este subşir pentru sir1 sau false, în caz contrar.

Exemplul 5.50. În secvenţa următoare se afişează “exemplu”:


$sir="Un exemplu";
$gasit=strstr($sir, "ex");
if ($gasit===false) echo ("Nu este in sir");
else echo ($gasit);

⇒ Funcţia strcmp(sir1,sir2) compară lexicografic (alfabetic) sir1 cu


sir2. Valoarea returnată este:
• <0, dacă sir1 < sir2;
• >0, dacă sir1 > sir2;
• 0, dacă sir1 = sir2.

Exemplul 5.51. Priviţi comparaţiile de mai jos:


 strcmp ("mama", "tata"); returnează un rezultat <0.
 strcmp ("ab", "a"); returnează un rezultat >0.
 strcmp ("abc", "abc"); returnează 0.

Observaţie ! Comparaţia face distincţie între literele mari şi cele mici!


⇒ Funcţia substr(sir,ind,[lung]) returnează subşirul şirului sir, care
începe în poziţia ind şi are lungimea lung. Dacă parametrul lung este
absent, se returnează şirul care începe în poziţia ind şi ţine până la
sfârşitul şirului sir.

Exemplul 5.52. După executarea secvenţei, se afişează “exemplu”:


$sir="Un exemplu";
echo (substr($sir,3));

Exemplul 5.53. După executarea secvenţei, se afişează “ex”:


$sir="Un exemplu";
echo (substr($sir,3,2));
⇒ Funcţia substr_replace(sir1, sir2, ind, [lung]) returnează şirul
rezultat prin înlocuirea în sir1, a subşirului care începe în poziţia ind şi are
lungimea lung cu sir2. Dacă parametrul lung este absent, sir2
înlocuieşte subşirul care începe cu ind şi ţine până la sfârşitul şirului sir2.

Exemplul 5.54. Secvenţa următoare afişează “Un templu”:


$sir="Un exemplu";
echo (substr_replace($sir,"t",3,2));
⇒ Funcţia strtoupper(sir) returnează şirul convertit în litere mari, iar funcţia
strtolower(sir) returnează şirul convertit în litere mici.
192 Manual de Informatică pentru clasa a XII-a

5.11. Masive în PHP

În PHP există o “libertate” extraordinară de lucru cu masive. Începem prin a


spune că masivele nu se declară.

Exemplul 5.55. În script-ul următor, se creează şi se afişează un vector cu 5


componente:
<?php
for ($i=0;$i<5;$i++) $x[$i]=$i;
for ($i=0;$i<5;$i++) echo( "$x[$i] <BR>" );
?>

Exemplul 5.56. Se creează şi se afişează o matrice cu 5 linii şi 5 coloane.


Elementele din linia i şi coloana j reţin valorile i+j.
<?php
for ($i=0;$i<5;$i++)
for ($j=0;$j<5;$j++) $mat[$i][$j]=$i+$j;
for ($i=0;$i<5;$i++)
{ for ($j=0;$j<5;$j++) echo($mat[$i][$j]." ");
echo("<BR>");
}
?>

⇒ În PHP, indicii pot fi şiruri de caractere.

Exemplul 5.57. Probaţi script-ul următor, unde un vector de indici nume de


persoane, reţine numerele lor de telefon. Acesta este un tablou asociativ:
<?php
$x["Ioana"]="0724xxx";
$x["Valentina"]="031xxx";
$x["Paul"]="0211xxx";
$x["Cristian"]="0232xxx";
print $x["Ioana"]."<BR>";
print $x["Valentina"]."<BR>";
print $x["Paul"]."<BR>";
print $x["Cristian"]."<BR>";
?>

Faptul că există posibilitatea utilizării unor astfel de indici creează, pe lângă


avantaje, probleme. Imaginaţi-vă că vreţi să parcurgeţi şi să listaţi un astfel de
vector. Care este numărul componentelor? Să zicem că pe acesta îl reţinem într-o
variabilă, dar ce valori ia variabila de ciclare?

⇒ Funcţia count(nume_vector) returnează numărul de componente ale


vectorului.
Capitolul 5. Limbajul PHP 193

Exemplul 5.58. Pentru vectorul din script-ul anterior, cu ajutorul expresiei


echo(count($x));, se afişează 4.

⇒ Instrucţiunea de mai jos are rolul de a ne permite o parcurgere uşoară a unui


vector cu numele vector, cu variabila de ciclare indice, în care citirea se
face în variabila variabila:
foreach(vector as indice=>variabila).

Exemplul 5.59. Se creează un vector şi se parcurge cu foreach(...), afişând


rezultatele parcurgerii:
<?php
$x["Ioana"]="0724xxx";
$x["Valentina"]="031xxx";
$x["Paul"]="0211xxx";
$x["Cristian"]="0232xxx";
foreach($x as $i=>$nume)
echo($i." ".$nume."<BR>" );
?> Figura 5.16.
Rezultatul script-ului
Iată ce se afişează (Fig. 5.16)!

Există şi alte funcţii care permit accesarea cu uşurinţă a elementelor


vectorului. Ideea de la care se pleacă este următoarea: există un pointer care
întotdeauna este asupra unui element al vectorului.

⇒ Funcţia current(vector); returnează valoarea reţinută de elementul din


vector asupra căruia se găseşte pointer-ul.

⇒ Funcţia key(vector); returnează indicele elementului din vector asupra


căruia se găseşte pointer-ul.

⇒ Funcţia next(vector); deplasează pointer-ul pe elementul următor din


vector şi returnează valoarea reţinută de acesta.

⇒ Funcţia prev(vector); deplasează pointer-ul pe elementul anterior al


vectorului şi returnează valoarea reţinută de acesta.

Exemplul 5.60. Analizaţi script-ul de mai jos:


<?php
$x["Ioana"]="0724xxx";
$x["Valentina"]="031xxx";
$x["Paul"]="0211xxx";
$x["Cristian"]="0232xxx";
echo(current($x)." ".key($x)."<BR>");
echo(next($x)." ".key($x)."<BR>"); Figura 5.17.
echo(prev($x)." ".key($x)."<BR>"); Rezultatul script-ului
echo(count($x)."<BR>");
?>
194 Manual de Informatică pentru clasa a XII-a

Dacă, în general, sortarea unui vector (tablou) se poate efectua cu ajutorul


unui algoritm oarecare de sortare, în cazul unui tablou asociativ, cum lesne vă
puteţi da seama, problema este mai complicată. Din acest motiv, PHP-ul pune la
dispoziţia programatorilor funcţii specifice.

Exemplul 5.61. Pentru a testa modul în care acestea efectuează sortarea, vom
folosi script-ul următor, în care linia “metoda de sortare“ se va înlocui cu
funcţia respectivă:
<?php
$x["Ioana"]="0724xxx";
$x["Valentina"]="031xxx";
$x["Paul"]="0211xxx";
$x["Cristian"]="0232xxx";\
foreach($x as $i=>$nume) echo($i." ".$nume."<BR>");
//metoda de sortare
?>
⇒ Funcţia Asort(vector) sortează crescător vectorul
după valoarea reţinută de fiecare element. Rezultatul
este prezentat în figura alăturată.

Figura 5.18.

⇒ Funcţia Arsort(vector) sortează descrescător


vectorul după valoarea reţinută de fiecare element.
Rezultatul este prezentat alăturat.

Figura 5.19.

⇒ Funcţia Ksort(vector) sortează crescător vectorul


după indici (vezi figura alăturată).

Figura 5.20.

⇒ Funcţia Krsort(vector) sortează descrescător


vectorul după indici. Rezultatul este cel alăturat.

Figura 5.21.

⇒ Funcţiile sort() şi rsort() sortează crescător, respectiv


descrescător, un masiv de indici 0, 1, ..., n. În cazul în care
avem un masiv asociativ, vechile valori ale indicilor se pierd
(vezi figura alăturată).
Figura 5.22.
Capitolul 5. Limbajul PHP 195

5.12. Variabile cookie

Atunci când utilizarea Internet-ului a luat amploare, s-a pus următoarea


problemă: cum trebuie procedat pentru ca server-ul să utilizeaze anumite opţiuni
ale utilizatorului, astfel încât, atunci când acesta intră pe site, să nu mai piardă
timpul selectându-le din nou? Mai mult, dacă se dispune de astfel de informaţii,
pagina afişată pentru un anumit utilizator ar putea fi personalizată. Problema a fost
rezolvată de cei de la firma Netscape în anul 1994.

Mecanismul care stă la baza acestei probleme se bazează pe memorarea,


pe calculatorul vizitatorului unui anumit site, a unor informaţii sub forma unor mici
fişiere text. Operaţia poate fi comandată de pe server şi tot de pe server se poate
comanda citirea, actualizarea sau ştergerea acestor mici fişiere, numite uzual, prin
abuz de limbaj, variabile cookie.

În PHP se poate lucra foarte uşor cu variabilele cookie.

⇒ Pentru a crea o variabilă cookie se utilizează funcţia


setcookie (nume_variabila, valoare, data_expirare)

Exemplul 5.62. În script-ul de mai jos, se creează o variabilă cookie numită


copac. Variabila reţine valoarea verde şi expiră într-o oră.
<?php
// creeaza o variabila cookie
setcookie("copac", "verde", time()+3600);
?>

Observaţii !

1. Nu pot exista simultan mai mult de 20 de variabile cookie. Dacă se creează una
în plus, prima creată este ştearsă automat.
2. Pentru a şterge o variabilă cookie se creează o alta cu acelaşi nume, dar cu
data de expirare înaintea datei curente (de exemplu, time()-1).

⇒ Pentru a citi o variabilă cookie se utilizează conţinutul unui masiv asociativ,


numit $HTTP_COOKIE_VARS. Fiecare componentă a sa, de indice numele
variabilei cookie, reţine valoarea variabilei cookie.
Exemplul 5.63. În script-ul de mai jos se afişează valoarea variabilei cookie creată
de script-ul anterior:
<?php
// afiseaza verde
echo $HTTP_COOKIE_VARS["copac"];
?>

Analizaţi şi exemplele următoare …


196 Manual de Informatică pentru clasa a XII-a

Exemplul 5.64. În script-ul de mai jos se creează 20 de variabile cookie numite


V1, V2, ..., V20 care reţin respectiv 1, 2, ..., 20:
<?php
for ($i=1;$i<=20;$i++)
setcookie("V".$i, $i, time()+10000);
echo "OK complet"
?>

Exemplul 5.65. În script-ul de mai jos se afişează conţinutul variabilelor cookie


existente pe calculatorul vizitatorului:
<?php
foreach($HTTP_COOKIE_VARS as $i=>$nume)
echo $i." ".$nume."<BR>";
?>

Exemplul 5.66. Script-urile care urmează exemplifică modul în care se pot reţine
anumite informaţii pe care utilizatorul le-a tastat o dată. Apelat pentru prima dată,
atunci când nu există variabila cookie nume, se cere numele vizitatorului. Acesta
va introduce numele şi va apăsa butonul insereaza (vezi Fig. 5.23). Dacă
respectivul vizitator, reintră pe acel site, reapelând script-ul, acesta va identifica
variabila cookie nume, va prelua numele memorat şi, în loc ca vizitatorului să i se
ceară din nou numele, se va afişa mesajul (vezi Fig. 5.24).

Figura 5.24.
Figura 5.23.

<?php
$gasit=0;
// se cauta daca exista variabila cookie nume
foreach($HTTP_COOKIE_VARS as $i=>$v)
if($i=="nume")
$gasit=1;
//daca exista se afiseaza un mesaj
if ($gasit==1)
echo " Bine ati venit pe site-ul nostru domnule:
".$HTTP_COOKIE_VARS["nume"];
// daca nu exista, se afiseaza cele necesare pentru
// identificare si se creeaza variabila nume
else
echo "<FORM action='cc.php' method ='post'>"."Nume<BR>".
"<input name='Nume' type='text'>;". "<BR>".
"<INPUT type='submit', value='insereaza'>";
?>
Capitolul 5. Limbajul PHP 197

5.13. Utilizarea în comun a limbajelor PHP şi MySQL

5.13.1. Crearea unei baze de date

În acest paragraf prezentăm modul în care se utilizează împreună PHP şi


MySQL. Vom presupune că server-ul care găzduieşte site-ul dispune de soft-ul
necesar. Desigur, prezentarea aplicaţiilor se va face în continuare pe propriul
calculator, prin utilizarea pachetului EasyPHP. Orice script PHP va fi scris în folder-ul
www, inclus în folder-ul EasyPHP1-8 (versiunea pe care o aveam în momentul
scrierii cărţii pe calculatorul nostru).

⇒ Orice script PHP care lucrează cu MySQL trebuie să se conecteze la acesta.


Pentru conectare, se utilizează funcţia mysql_connect() sub forma:
resursa mysql_connect(“nume_gazda”,”nume_utilizator”,
“parola”)

În cazul nostru, numele gazdei este localhost, iar numele utilizatorului şi


parola sunt cele utilizate în Partea 1, Capitolul 2, atunci când am învăţat să utilizăm
MySQL de la consolă. În cazul în care conectarea a reuşit se returnează resursa,
altfel, se returnează FALSE.

⇒ Pentru a da o comandă MySQL dintr-un script PHP se utilizează funcţia


mysql_query(), care primeşte instrucţiunea sub forma unui şir de
caractere. Şi aici, în caz că operaţia a reuşit, se returnează o valoare diferită
de 0, altfel se returnează 0.
resursa mysql_query(instructiune_mysql)

Exemplul 5.67. Se cere să se scrie un script, cre_baza.php, care creează baza


de date, numită baza. Practic, script-ul va realiza conexiunea la MySQL, după care
va da comanda de creare a bazei de date. În ambele operaţii, în caz de nereuşită,
se va da un mesaj de eroare lămuritor.
<?php
// conectarea la MySQL
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL "; exit; }
// crearea bazei de date numita baza
$rezultat=mysql_query("CREATE DATABASE baza");
if (!$rezultat)
echo "nu s-a reusit crearea bazei de date";
?>

Pentru a rula script-ul, se dă următoarea comandă browser-ului:


http://localhost/cre_baza.php
198 Manual de Informatică pentru clasa a XII-a

Dacă dorim ca mesajele de eroare să ne ajute mai mult în depanare, vom


utiliza două funcţii MySQL.

⇒ Funcţia string mysqlerrno() returnează codul numeric al ultimei erori.


Lista parametrilor este vidă.
⇒ Funcţia string mysqlerror() returnează mesajul asociat ultimei erori.
Şi în cazul ei, lista parametrilor este vidă.

Exemplul 5.68. Înlocuiţi ultimul echo din scriptul anterior cu:


echo mysql_errno().":".mysql_error();

În cazul în care veţi rula din nou script-ul, va apărea o eroare care se
datorează faptului că se încearcă crearea unei baze de date care există deja. Iată
cum este afişată eroarea în acest caz:
1007: Can’t create database ‘baza’; database exists

Observaţie ! În perioada de început, este recomandabil să utilizaţi în paralel şi


fereastra MS-DOS pentru a lucra cu MySQL, ca în Capitolul 2. De fiecare dată veţi
testa dacă operaţia a reuşit. De exemplu, după ce aţi creat baza de date, numită
baza, daţi comanda USE baza şi dacă nu apare eroare, înseamnă că baza de
date a fost creată.

5.13.2. Accesul la o bază de date şi crearea unui tabel


în baza de date

⇒ Pentru a avea acces la o bază de date, se utilizează funcţia de mai jos, care
returnează, aşa cum suntem obişnuiţi, o valoare diferită de 0 în caz de
reuşită şi 0, în caz contrar.
bool mysql_select_db(nume_baza)
După realizarea accesului, putem crea tabelul prin utilizarea instrucţiunii
mysql_query().

Exemplul 5.69. Se cere să se scrie un script, cre_tabel.php, prin care să se


creeze un tabel, numit vizitatori, care reţine, pentru fiecare persoană trecută
în tabel, numele, vârsta şi adresa de e-mail.

<?php
// conectarea la MySQL
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL "; exit;}
// conectarea la baza de date
$baza=mysql_select_db("baza");
Capitolul 5. Limbajul PHP 199

if (!$baza)
{ echo mysql_errno().":".mysql_error(); exit;}
// crearea tabelului
$interogare="CREATE TABLE vizitatori (nume CHAR(30), varsta
INT, email CHAR(20) PRIMARY KEY)";
$rezultat=mysql_query($interogare);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
?>

Testaţi script-ul apelând: http://localhost/cre_tabel.php.

În toate operaţiile pe care le vom face de acum înainte cu această bază de


date vom avea nevoie, în mod evident, de conectarea la MySQL şi accesul la baza
de date. Pentru ca să nu repetăm această secvenţă, se scrie script-ul de mai jos,
numit conectare.php():
<?php
// conectarea la MySQL
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql)
{echo "Nu s-a realizat conectarea la MySQL "; exit;}
// conectarea la baza de date
$baza=mysql_select_db("baza");
if (!$baza)
{echo mysql_errno().":".mysql_error(); exit;}
?>

⇒ Pentru ca un script să includă un altul şi să-l execute se foloseşte funcţia


MySQL de mai jos, care are ca parametru numele script-ului care urmează
să fie inclus:
require_once(nume_script);

Exemple de utilizare ale acestui script veţi găsi în paragrafele următoare.

5.13.3. Inserarea liniilor în tabel

Am creat o bază de date, numită baza, cu un tabel, numit vizitatori.


Rămâne să introducem date în acest tabel. Vom presupune că fiecare utilizator al
bazei de date se autoînregistrează, scriind datele în nişte edit-uri afişate de pagină.
Problema se rezolvă în două părţi.

A) Se creează o pagină, s-o numim i_date.php, care conţine edit-urile prin care
se introduc datele şi butonul la apăsarea căruia datele sunt transmise către server.
Modul de creare a unei astfel de pagini a fost descris, prin urmare prezentăm
numai codul ei şi tabelul pe care-l afişează. La apăsarea butonului inserează se
apelează script-ul insereaza.php aflat pe server (în cazul nostru, în folder-ul
www). Pagina va fi apelată prin comanda următoare:
200 Manual de Informatică pentru clasa a XII-a

http://localhost/cre_tabel.php.

Codul sursă pentru pagina i_date.php este:

<HTML>
<HEAD> </HEAD>
<BODY>
<FORM action="insereaza.php"
method ="post">
Nume<BR>
<INPUT name="nume" type="text">; <BR>
Varsta <BR>
<INPUT name="varsta" type="text">; <BR>
Adresa e-mail <BR> Figura 5.25.
<INPUT name="email" type="text">; <BR> Pagina i_date.php
<INPUT type="submit", value="insereaza">
</FORM>
</BODY>
</HTML>

B) După ce vizitatorul paginii respective îşi completează datele şi apasă butonul


insereaza, acestea sunt transmise către server şi sunt preluate de către script-ul
insereaza.php. Acesta preia datele şi le introduce în tabelul vizitatori.
<?php
require_once("conectare.php");
$nume= $_POST['nume'];
$varsta= $_POST['varsta'];
$email= $_POST['email'];
$cerere="INSERT INTO vizitatori (nume,varsta,email)
VALUES('$nume',$varsta,'$email')";
$rezultat=mysql_query($cerere);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
?>

Observaţii !

1. Pentru câmpurile nume şi email datele sunt de tip şir de caractere. Ele sunt
memorate de variabilele $nume şi $email. Pentru a le introduce ca şiruri, vom
trece variabilele între apostrofuri: ‘$nume’, ‘$email’.

2. După introducerea unui rând, testaţi dacă acesta a fost sau nu introdus în
fereastra MS-DOS: SELECT * FROM vizitatori.

Este foarte important ca datele introduse să fie validate. Astfel, numele


trebuie să fie nevid, varsta trebuie să fie o valoare numerică mai mare sau egală
ca 10 şi mai mică sau egală cu 90 şi adresa de e-mail trebuie să conţină caracterul
‘@’. Vom rescrie script-ul, de această dată cu validări.
Capitolul 5. Limbajul PHP 201

Observaţie ! Atunci când se depistează o eroare, se afişează un mesaj lămuritor şi


se reafişează formularul de introducere a datelor!
<?php
require_once("conectare.php");
$nume= $_POST['nume'];
if (strcmp($nume,"")==0)
{echo "Nu ati scris numele";
require_once("i_date.php");
exit;
}
$varsta= $_POST['varsta'];
if (!is_numeric($varsta) || $varsta<10 ||$varsta>90)
{echo "Varsta incorecta";
require_once("i_date.php");
exit;
}
$email= $_POST['email'];
if (!strpos($email,"@"))
{
echo "Adresa de e-mail gresita";
require_once("i_date.php");
exit;
}
$cerere="INSERT INTO vizitatori (nume,varsta,email)
VALUES('$nume',$varsta,'$email')";
$rezultat=mysql_query($cerere);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
?>

5.13.4. Afişarea unui tabel

În acest paragraf vom arăta modul în care se listează rezultatul unei


interogări. După cum am văzut, o interogare se realizează cu mysql_query().
Ea returnează o valoare care, în cazul în care interogarea a reuşit, este diferită de
0. În cazul în care rezultatul unei interogări este alcătuit din mai multe rânduri, ca
de exemplu în cazul listării unui tabel, nu se afişează direct rezultatul, aşa cum
suntem obişnuiţi. În astfel de cazuri, pornind de la valoarea returnată de
mysql_query(), se afişează tabelul rând cu rând.

⇒ Funcţia mysql_fetch_array() returnează un rând al unei interogări (în


cazul de faţă, al unui tabel) sub forma unui tablou asociativ. După returnarea
rândului, automat se trece la rândul următor.
array mysql_fetch_array(resursa)
Pornind de la tabloul asociativ returnat, se poate accesa orice câmp al
interogării.
202 Manual de Informatică pentru clasa a XII-a

Exemplul 5.70. Analizaţi script-ul


următor, unde se afişează datele
introduse în tabel. Rezultatul îl puteţi
observa în figura alăturată.
<?php
require_once("conectare.php"); Figura 5.26.
$cerere="SELECT * FROM vizitatori"; Rezultatul obţinut
$rezultat=mysql_query($cerere);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
// pentru fiecare rand al tabelului
while($rand=mysql_fetch_array($rezultat))
echo $rand["nume"]." ".$rand["varsta"]." ".
$rand["email"]."<BR>";
?>

Desigur, datorită formei inestetice,


această afişare a tabelului nu ne
convine. Din acest motiv, vom afişa
tabelul, aşa cum îl observaţi alăturat.
Pentru aceasta, vom rescrie script-ul
afisare_tabel:

<?php Figura 5.27.


require_once("conectare.php"); Rezultat “estetic”
$cerere="SELECT * FROM vizitatori";
// in urma interogarii, se returneaza tabelul
$rezultat=mysql_query($cerere);
if (!$rezultat)
{ echo mysql_errno().":".mysql_error(); exit; }
// afisam datele sub forma unui tabel
echo "<TABLE BORDER=5>";
// afisam capul de tabel
Echo "<TR><TD align='center'>
<STRONG>Nume<TD><STRONG>Varsta<TD><STRONG>Adresa e-mail";
// Pentru fiecare rand al tabelului
while($rand=mysql_fetch_array($rezultat))
{ echo "<TR>";
echo "<TD>".$rand["nume"].
"<TD align='right'>".$rand["varsta"]."<TD>".
"<A href=mailto:".$rand["email"].">".$rand["email"]."</A>";
echo "</TR>";
}
echo "</TABLE>";
?>

Apelaţi script-ul prin: http://localhost/afisare_tabel.php.


Capitolul 5. Limbajul PHP 203

5.14. Aplicaţii

5.14.1. Inscrierea pe un site

În unele site-uri se cere ca, în prealabil, vizitatorii respectivului site să se


înscrie în baza de date a acestuia. De regulă, utilizatorului i se cere ID-ul
(nickname-ul) şi parola. Acestea sunt memorate într-un tabel şi de câte ori utilizatorul
doreşte să acceseze din nou site-ul, ele sunt cerute pentru identificare. Accesul la
site se realizează numai atunci când ID-ul şi parola se regăsesc în baza de date.

A) Pentru început, este necesar ca să se creeze o bază de date, de exemplu,


inscrisi, care conţine un singur tabel, parole. Script-ul următor, btab.php,
realizează cele de mai sus:
<?php
// conectarea la MySQL
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL "; exit; }
// crearea bazei de date numita baza
$rezultat=mysql_query("CREATE DATABASE inscrisi");
if (!$rezultat)
{ echo "nu s-a reusit crearea bazei de date";
exit;
}
$baza=mysql_select_db("inscrisi");
$interogare="CREATE TABLE parole ( nume CHAR(30) PRIMARY
KEY, parola CHAR(10))";
$rezultat=mysql_query($interogare);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
?>

În cele ce urmează, vom presupune că am rulat script-ul btab.php, deci


baza de date şi tabelul sunt create.

B) Dacă un vizitator accesează site-ul, este afişată pagina alăturată, în care i se


cere, fie să se identifice, în cazul în care este înscris deja, fie să se înscrie, în caz
contrar.

Figura 5.28.
Pagina principală
204 Manual de Informatică pentru clasa a XII-a

Pentru a realiza pagina respectivă, se foloseşte un simplu fişier HTML (sau


PHP), vedeţi mai jos (index.php). În fapt, acesta conţine două ancore, către cele
două script-uri PHP: identificare.php sau inscriere.php. Vizitatorul poate
opta pentru oricare dintre ele.
<HTML>
<BODY>
<H2> Bine ati venit pe site-ul...</H2>
<A href="http://localhost/identificare.php"> Identificare
</A><BR><BR>
<A href="http://localhost/inscriere.php"> Inscriere </A>
</BODY>
</HTML>

C) Dacă utilizatorul optează pentru înscriere, atunci


este rulat script-ul următor (inscriere.php), care
afişează fereastra alăturată. Vizitatorului i se cere să
introducă numele (ID-ul) şi parola. Atunci când se
introduce parola, se afişează * pentru fiecare caracter
introdus. Pentru a evita introducerea greşită a parolei,
aceasta trebuie să fie introdusă de două ori.

După introducerea datelor, vizitatorul va apăsa butonul


“inscrie-te”. Efectul va fi acela de trimitere a datelor
către server şi de apel al script-ului inscrie.php.
Figura 5.29.
<HTML> Pagina “inscriere.php”
<BODY>
<FORM action="inscrie.php" method ="post">
Nume<BR>
<input name="nume" type="text">; <BR>
Parola <BR>
<input name="parola1" type="password">; <BR>
Reintroduceti parola <BR>
<input name="parola2" type="password">; <BR>
<INPUT type="submit", value="inscrie-te!">
</FORM>
</BODY>
</HTML>

C1) Script-ul inscrie.php validează datele şi, în caz că acestea sunt valide, le
înscrie în tabelul parole:
- se testează dacă numele este nevid;
- dacă cele două parole coincid;
- dacă nu mai există un vizitator cu aceeaşi parolă (parola este cheie primară).

În cazul în care una dintre aceste condiţii nu este îndeplinită, se afişează un mesaj
de eroare corespunzător şi se reafişează formularul de introducere a datelor.
Capitolul 5. Limbajul PHP 205

<?php
// conectare la mysql
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL "; exit; }
// declarare baza folosita
$baza=mysql_select_db("inscrisi");
//Citirea numelui - trebuie sa fie nevid
$nume= $_POST['nume'];
if (strcmp($nume,"")==0)
{echo "Nu ati scris numele";
require_once("inscriere.php");
exit;
}
// citirea parolelor - trebuie sa fie identice
$parola1= $_POST['parola1'];
$parola2= $_POST['parola2'];
if (strcmp($parola1,$parola2)!=0)
{echo "parola incorecta";
require_once("inscriere.php");
exit;}
// se incearca inscrierea in tabel
$cerere="INSERT INTO parole (nume,parola)
VALUES('$nume','$parola1')";
$rezultat=mysql_query($cerere);
if (!$rezultat)
{ echo "Nume existent in baza de date";
require_once("inscriere.php");
}
else echo "OK! Ati fost introdus in baza noastra de date";
?>

D) În cazul în care vizitatorul este deja înscris, va


apela script-ul identificare.php prin intermediul
ancorei respective. Acesta va cere numele şi parola,
iar la apăsarea butonului “Conecteaza-ma” va
trimite datele către server. Acestea sunt preluate de
script-ul “verif.php”.
<HTML>
<BODY>
<FORM action="verif.php" method ="post"> Figura 5.30. Pagina
Nume<BR> “identificare.php”
<input name="nume" type="text">; <BR>
Parola <BR>
<input name="parola" type="password">; <BR>
<INPUT type="submit", value="Conecteaza-ma">
</FORM>
</BODY>
</HTML>
206 Manual de Informatică pentru clasa a XII-a

D1) Se testează dacă în tabelul parole există înregistrarea cu ID-ul şi parola


introdusă de utilizator. În caz că există, se rulează, de exemplu, un script php, în
acest caz, rezultat.php, altfel se cere ca datele să fie reintroduse:

<?php
// conectare la mysql
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL "; exit; }
// declarare baza folosita
$baza=mysql_select_db("inscrisi");

// citirea numelui si parolei


$nume= $_POST['nume'];
$parola= $_POST['parola'];

// selectez, daca exista in tabel, randul corespunzator


$cerere="SELECT nume FROM parole
WHERE nume='$nume' AND parola='$parola'";
$rezultat=mysql_query($cerere);
$rand=mysql_fetch_array($rezultat);
//echo $rand['nume'];
if ($rand["nume"]!=$nume)
{echo "Numele si/sau parola sunt eronate";
require_once("identificare.php");
}
else require_once("rezultat.php"); ;
?>

Fişierul rezultat.php este:

<HTML>
<BODY>
<H1> pagina ce ar trebui afisata
</BODY>
</HTML>

5.14.2. Determinarea adresei IP şi a browser-ului utilizatorului

Uneori se doreşte obţinerea unor informaţii despre vizitatorii unui site. Astfel,
se poate afla adresa IP a vizitatorului, browser-ul utilizat de acesta sau sistemul de
operare pe care acesta îl utilizează. Toate acestea pot fi stocate în baze de date.
Informaţiile astfel dobândite sunt extrem de importante pentru aplicaţii precum:

- Aplicaţii prin care vizitatorii votează răspunsul la o anumită întrebare. Pentru


a evita ca un vizitator să voteze de mai multe ori într-o zi, într-un tabel se va
memora adresa IP a acestuia. De la o anumită adresă IP se poate vota o
singură dată sau o singură dată pe zi, caz în care se va reţine şi ziua votării.
Capitolul 5. Limbajul PHP 207

- Aplicaţii prin care se contorizează vizitatorii unui site. Dacă o persoană


vizitează site-ul într-o zi de mai multe ori, dar cu aceeaşi adresă IP, aceasta
este numărată ca vizitator o singură dată.
- Determinarea browser-ului are şi ea mai multe utilizări. Se ştie că, din
păcate, diferite browser-e afişează uneori diferit acelaşi fişier download-at de
pe server. Pentru a nu mai avea astfel de probleme, dacă se cunoaşte
browser-ul utilizatorului, atunci server-ul expediază către calculatorul
vizitatorului fişierul corespunzător.
- Informaţii precum cele de mai sus pot fi folosite de site-urile care
monitorizează vizitele la diferite alte site-uri şi întocmesc clasamentul
acestora în funcţie de numărul de vizitatori.

În acest paragraf vom învăţa să determinăm adresa IP şi browser-ul vizitatorului.

$_SERVER este o variabilă predefinită de tip masiv asociativ. Cu ajutorul ei,


script-ul PHP poate accesa o mulţime de informaţii. Pentru a afla adresa IP a
vizitatorului se utilizează $_SERVER["REMOTE_ADDR"] şi pentru a afla informaţii
despre browser se utilizează $_SERVER["HTTP_USER_AGENT"]. În acest din urmă
caz, dacă şirul obţinut conţine subşirul MSIE 6.0, atunci browser-ul utilizator este
Microsoft Internet Explorer versiunea 6.0, dacă conţine subşirul Netscape,
atunci browser-ul este de tip Netscape, etc.

Exemplul 5.71. Mai multe informaţii puteţi obţine analizând script-ul următor care
afişează browser-ul utilizatorului şi adresa IP a acestuia (vezi figura de mai jos):

Figura 5.31. Rezultatele script-ului propus ca exemplu

<?php
$brw = $_SERVER["HTTP_USER_AGENT"];
echo " Informatia generala: ".$brw. "<BR>";

// determinare browser
if(strstr($brw,"MSIE 5.0"))
$brw = "Microsoft Internet Explorer v5.0";
else
if(strstr($brw,"MSIE 5.5"))
$brw = "Microsoft Internet Explorer v5.5";
else
if(strstr($brw,"MSIE 6.0"))
$brw = "Microsoft Internet Explorer v6.0";
else
if ( strstr($brw, "Netscape"))
$brws = "Netscape";
208 Manual de Informatică pentru clasa a XII-a

else
if ( strstr($brw, "Firefox"))
$brws = "Firefox";
else
if ( strstr($brw, "Mozilla"))
$brws = "Mozilla";
else
if ( strstr($brw, "Opera"))
$brws = "Opera";
else
$brw = "Browser necunoscut";
echo " Browser ".$brw. "<BR>";
// adresa IP
$ip = $_SERVER["REMOTE_ADDR"];
echo " Adresa IP ".$ip;
?>

1. Creaţi un contor pentru un site care să numere vizitatorii site-ului respectiv. Un


vizitator cu o anumită adresă IP se numără o singură dată într-o zi, indiferent de
numărul de vizite ale site-ului pe care acesta le efectuează.

2. Creaţi un site care afişează o anumită întrebare, la care vizitatorii sunt invitaţi să
răspundă alegând o opţiune dintre mai multe, afişate cu ajutorul unor butoane
radio. Un vizitator cu o anumită adresă IP poate vota o singură dată într-o zi. În
situaţia în care acesta încearcă să voteze de mai multe ori, se va afişa un mesaj
prin care acesta este anunţat că a votat deja.

Observaţie ! În ambele cazuri veţi crea o bază de date cu un singur tabel, care
reţine adresa IP a vizitatorului şi (eventual) data efectuării vizitei respective.

5.14.3. Cum se creează un forum ?

De câte ori n-am văzut sau am scris în diverse forum-uri... Unele sunt pe
marginea unor articole din ziare, altele au scopuri precise, cu discuţii pe anumite
teme (limbaje de programare, politică, literatură, etc.).

În cele ce urmează ne propunem să creăm un forum mult simplificat, în care


cei care doresc scriu mesaje, iar toţi ceilalţi le citesc. De ce avem nevoie pentru a
realiza un astfel de forum?

A) În primul rând, este necesară o bază de date, s-o numim forum şi un tabel, să-l
numim mesaje. Un rând al tabelului va conţine un mesaj. În acest sens, va exista
un număr de ordine pentru mesajul respectiv (nr), id-ul celui care a scris mesajul
(id), titlul mesajului (titlu) şi textul propriu-zis al acestuia (textul). Script-ul următor,
să-l numim f1.php, creează baza de date şi tabelul. Iniţial, tabelul este vid.
Capitolul 5. Limbajul PHP 209

<?php
// conectarea la MySQL
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql)
{ echo "Nu s-a realizat conectarea la MySQL "; exit; }
// crearea bazei de date numita baza
$rezultat=mysql_query("CREATE DATABASE forum");
if (!$rezultat)
{ echo "nu s-a reusit crearea bazei de date";
exit;
}
$baza=mysql_select_db("forum");
$interogare="CREATE TABLE mesaje(nr INT UNIQUE KEY
AUTO_INCREMENT, id CHAR(20), titlu CHAR(100),
textul LONGTEXT)";
$rezultat=mysql_query($interogare);
if (!$rezultat)
echo mysql_errno().":".mysql_error();
?>

B) Acum este necesar un script prin


care utilizatorul scrie un mesaj. Practic,
acesta trebuie să introducă mesajul,
adică informaţiile cerute de tabel şi la
apăsarea butonului “Adauga mesajul”
să fie trimis către server.

<HTML>
<HEAD> </HEAD>
<BODY>
<FORM action="insereaza.php"
method ="post"> ID <BR>
<INPUT name="id"
type="text">;
<BR> Titlu <BR>
<INPUT name="titlu"
type="text">;
<BR><BR> Mesajul dv <BR>
<TEXTAREA name="mesajul" Figura 5.32. Pagina care
rows="10" cols="30"></TEXTAREA> conţine formularul
<BR>
<INPUT type="submit", value="Adauga mesajul">
</FORM>
</BODY>
</HTML>

C) Pe server, informaţiile transmise de către cel care a scris mesajul sunt preluate
de către script-ul insereaza.php. Practic, se verifică dacă fiecare câmp în parte
este nevid, după care mesajul este memorat în tabel.
210 Manual de Informatică pentru clasa a XII-a

<?php
// conectarea la MySQL
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql) echo "Nu s-a realizat conectarea la MySQL ";
// conectarea la baza de date
$baza=mysql_select_db("Forum");
if (!$baza) echo mysql_errno().":".mysql_error();
$id= $_POST['id'];
if (strcmp($id,"")==0)
{ echo "Nu ati introdus ID-ul";
require_once("f2.php"); exit; }
$titlu= $_POST['titlu'];
if (strcmp($titlu,"")==0)
{ echo "Nu ati scris titlul";
require_once("f2.php"); exit; }
$mesajul= $_POST['mesajul'];
if (strcmp($mesajul,"")==0)
{ echo "Nu ati scris mesajul";
require_once("f2.php"); exit; }
$cerere="INSERT INTO mesaje (id,titlu,textul)
VALUES('$id','$titlu','$mesajul')";
$rezultat=mysql_query($cerere);
if (!$rezultat) echo mysql_errno().":".mysql_error();
?>

D) O persoană care doreşte să vizualizeze mesajele scrise de alţii, va apela


script-ul următor, f3.php. Practic, acesta afişează tabelul mesajelor. După cum
observaţi, pentru un mesaj, nu este afişat textul propriu-zis:

Figura 5.33. Pagina care


conţine tabelul mesajelor

Pentru a-l vizualiza pe acesta, va trebui să se execute clic pe titlul mesajului. De aici
rezultă că titlul va trebui afişat ca un link. Aici intervine ceva interesant. Atunci când
se execută clic, se va apela un alt script, f4.php, care va afişa mesajul cerut.
Problema este că va trebui să fie cunoscut numărul curent al mesajului respectiv.
Prin urmare, este necesar un link care să transmită şi un parametru. Este necesar
un apel de forma: f4.php?nr_mesaj. De exemplu, dacă numărul mesajului este
3, vom scrie: f4.php?3. În rest, script-ul f3 afişează datele într-un tabel, aşa cum
suntem deja obişnuiţi.
<?php
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql)
{echo "Nu s-a realizat conectarea la MySQL "; exit;}
//conectarea la baza de date
$baza=mysql_select_db("forum");
Capitolul 5. Limbajul PHP 211

if (!$baza)
{echo mysql_errno().":".mysql_error(); exit;}
$cerere="SELECT * FROM mesaje";
// in urma interogarii, se returneaza tabelul
$rezultat=mysql_query($cerere);
if (!$rezultat)
{ echo mysql_errno().":".mysql_error(); exit;}
echo "<TABLE BORDER=5>";
// afisam capul de tabel
echo "<TR> <TD align='left'><STRONG>nr.curent
<TD align='center'><STRONG>ID<TD><STRONG>Titlu mesaj";
while($rand=mysql_fetch_array($rezultat))
{ echo "<TR>";
echo "<TD align='right'>".$rand["nr"].
"<TD>".$rand["id"].<TD>"."<A
href=http://localhost/f4.php?".$rand["nr"].
">".$rand["titlu"]."</A>";
echo "</TR>";
}
echo "</TABLE>";
?>

E) Script-ul de mai jos, f4.php, apelat de f3.php, primeşte ca parametru de


intrare numărul mesajului. Practic, apelează MySQL-ul, deschide baza de date şi
afişează corpul mesajului (textul propriu-zis al acestuia), indentificându-l cu ajutorul
unei interogări.
<?php
$nr= $_SERVER["QUERY_STRING"];
$msql=mysql_connect("localhost","root","parolamea");
if(!$msql)
{echo "Nu s-a realizat conectarea la MySQL"; exit;}
// conectarea la baza de date
$baza=mysql_select_db("forum");
if (!$baza) {echo mysql_errno().":".mysql_error(); exit;}
$cerere="SELECT textul FROM mesaje WHERE nr=$nr";
// in urma interogarii, se returneaza tabelul
$rezultat=mysql_query($cerere);
$rand=mysql_fetch_array($rezultat); echo $rand["textul"];
?>

1. Adăugaţi script-ului f3.php o secvenţă în urma căreia, la apăsarea unui buton,


să se poată introduce un mesaj (practic, să fie apelat script-ul f2.php).
2. Reproiectaţi aplicaţia astfel încât să existe posibilitatea unui răspuns la un
mesaj.
212 Manual de Informatică pentru clasa a XII-a

5.15. Proiectarea paginilor web


În acest moment, puteţi spune că aveţi cunoştinţe solide astfel încât să puteţi
dezvolta o aplicaţie hipermedia. Definirea modelului conceptual vă ajută la etapa
de proiectare a unei baze de date, normalizarea acesteia asigură robusteţe şi
siguranţă, iar prin intermediul limbajului MySQL o puteţi implementa. Limbajele
HTML şi CSS oferă nenumărate posibilităţi de realizare a interfeţei cu utilizatorul
final, iar PHP-ul, accesul la baza de date stocată pe server.
Observaţie ! Recitiţi Capitolul 1 pentru a vă reaminti noţiunile fundamentale care
privesc proiectarea bazelor de date!
O planificare riguroasă a proiectului este imperativă şi de cele mai multe ori,
ducerea la bun sfârşit a acestuia necesită o întreagă echipă care să lucreze
coordonat. Astfel, în cazul în care nu realizaţi proiectul singur, trebuie să formaţi o
echipă care să-şi distribuie sarcinile cât mai eficient, în funcţie de aptitudini. Puteţi
revedea subcapitolul 1.4. din Partea I, care descrie managementul de proiect.
Nimeni nu “pleacă la drum” fără un plan bine pus la punct. De aceea, înainte
de toate, trebuie să fixaţi clar toate etapele pe care trebuie să le parcurgeţi.
1. Trebuie să ştiţi cui i se adresează site-ul pe care doriţi să-l dezvoltaţi şi
bineînţeles, discutaţi cu beneficiarul acestuia pentru a obţine toate
informaţiile de care aveţi nevoie. În funcţie de datele pe care acesta
doreşte să le cunoască despre vizitatorii site-ului sau pe cele care vrea să
le reţină în urma interacţiunii cu aceştia, puteţi realiza modelul conceptual
al bazei de date.
2. Analizaţi cu atenţie modelul conceptual, iar dacă este cazul, utilizaţi
tehnica de normalizare a datelor pentru a preveni eventualele anomalii.
3. Utilizând modelul relaţional al bazelor de date, implementaţi modelul con-
ceptual, iar cu ajutorul limbajului MySQL, creaţi baza de date!
4. Interfaţa grafică cu utilizatorul trebuie să fie bine structurată, simplu de
utilizat, iar datele de intrare şi cele de ieşire trebuie alese corespunzător, în
funcţie de particularităţile proiectului (revedeţi paragraful 4.23).
Nu uitaţi ! Realizarea interfeţei grafice reprezintă o etapă esenţială pentru
că paginile web sunt unicul loc unde utilizatorul interacţionează în mod
direct cu aplicaţia dvs. Upload-aţi pe server fişierele html astfel formate şi
testaţi-le cu atenţie!
5. Realizaţi formularele care asigură colectarea şi trimiterea datelor către
server. Multe aplicaţii hipermedia conţin formulare care au câmpuri
opţionale, permiţând colectarea unor informaţii suplimentare despre
utilizatori.
6. Creaţi script-urile PHP care să prelucreze datele introduse de utilizator şi
care să răspundă comenzilor recepţionate.
7. La final, testaţi aplicaţia pentru a elimina anumite erori care pot apărea!
Capitolul 5. Limbajul PHP 213

 De multe ori, codurile sursă pot avea sute de linii de cod, la care trebuie să
adăugaţi comentarii sugestive pentru a putea vizualiza rapid secţiuni din
cadrul acestora.
 Corectitudinea datelor introduse de către utilizatori trebuie să fie asigurată
prin “mesajele ajutătoare” sau de eroare care trebuie să se regăsească în
cadrul paginilor web – se evită astfel introducerea unor informaţii eronate în
baza de date.
 Cu ajutorul variabilelor cookie, puteţi oferi posibilitatea personalizării site-ului,
în funcţie de preferinţele utilizatorului (de exemplu: diverse teme – care au la
bază câte un stil – vezi CSS; afişarea informaţiilor de interes – listă cu
diverse categorii, etc.).
 Nicio aplicaţie nu poate fi considerată în totalitate terminată, ea fiind
deschisă la eventuale îmbunătăţiri. De asemenea, pentru a fi asigurat
succesul site-ului web, actualizaţi frecvent informaţiile pentru a ţine la curent
vizitatorii fideli!
Important ! Pentru ca posesorul site-ului să poată vizualiza informaţiile reţinute în
baza de date, realizaţi o interfaţă (o pagină web) specială, stabilind de comun
acord care date trebuie să fie afişate în respectivele rapoarte, grafice, etc.

1. Care dintre afirmaţiile de mai jos sunt adevărate şi care sunt false?
a) Un script PHP este executat de către browser.
b) PHP-ul se instalează pe server.
c) Un fişier HTML poate conţine un script PHP.
d) Formularele se descriu în HTML.
2. “Variantă simplificată de test online”. Reluaţi problema 1. Veţi crea o pagină
HTML care afişează problema şi oferă vizitatorului ca, acolo unde consideră că
răspunsul este adevărat, să bifeze un buton de marcare. Datele se trimit către server.
Pe server, răspunde un script PHP care, acolo unde vizitatorul a răspuns corect,
afişează OK, iar unde nu a răspuns corect, afişează răspunsul corect şi o explicaţie.
3. Dintre afirmaţiile de mai jos, una singură este falsă. Care este?
a) Funcţiile PHP admit parametri transferaţi prin referinţă.
b) Funcţiile apelate de un script PHP trebuie să fie conţinute de acesta.
c) Funcţiile PHP admit parametri transferaţi prin valoare.
d) În PHP nu este necesar să declarăm tipul unei variabile.
4. Cum se testează online problema 3 (vedeţi problema 2)?
214 Manual de Informatică pentru clasa a XII-a

5. ”Validarea datelor”. Scrieţi un fişier HTML care conţine un formular prin


intermediul căruia se pot trimite către server numele vizitatorului şi vârsta sa. Pe
server, se va găsi un script care testează dacă numele este alfabetic şi dacă vârsta
este între 5 şi 90 de ani. Dacă aceste condiţii sunt îndeplinite, browser-ul va afişa
OK, altfel se vor afişa mesaje de eroare corespunzătoare.
6. ”Semnalarea erorilor găsite la validare”. Se cere să se scrie un formular prin
care vizitatorul trimite către server un număr întreg din intervalul [1,10] şi un
script PHP care verifică valoarea introdusă. În cazul în care valoarea introdusă este
corectă, se va afişa OK, altfel se va da un mesaj de eroare, după care se va afişa
din nou formularul (vezi figurile de mai jos).

a) Formular iniţial b) Mesaj de eroare

Figura 5.34. Figuri propuse pentru problema 6

7. ”Verificare parolă”. Se cere să se scrie un formular prin care i se cere


vizitatorului să introducă o parolă. Pe server răspunde un script PHP care verifică
parola. În caz de coincidenţă, se va afişa o pagină HTML, la alegerea dvs., iar altfel
se va afişa un mesaj de eroare.
8. ”Imagini la alegere”. Să se creeze un formular care conţine o listă. Vizitatorul
selectează, după nume, o anumită fotografie şi trimite selecţia sa către server.
Acolo, un script PHP afişează imaginea, dar şi lista, pentru ca vizitatorul să poată
selecta o altă imagine.
9. ”Afişarea unui tabel atunci când nu se cunosc de la început datele”. Să se
creeze un formular care trimite 4 valori către server. Acolo se va găsi un script care
afişează cele 4 valori sub forma unui tabel. Vedeţi mai jos.

a) Formular iniţial b) Tabelul obţinut

Figura 5.34. Pagini propuse pentru problema 9

(pentru verificare, rezolvările se găsesc la pag. 383)


Capitolul 5. Limbajul PHP 215

Formaţi echipe de 2 - 4 elevi, alegeţi-vă o temă de proiect, fie din temele


propuse în această secţiune, fie una propusă chiar de voi.
Atenţie! Repartizaţi sarcinile în mod echitabil în cadrul echipei de proiect.
Puteţi chiar organiza împreună cu cadrul didactic, un concurs la nivelul clasei
sau al şcolii, la care să invitaţi şi alţi profesori din şcoală.
Nu uitaţi să documentaţi fiecare presupunere pe care aţi făcut-o în realizarea
proiectului!

1. “Şeful clasei”. Este de preferat ca orice clasă să aibă ales un elev care să se
ocupe de problemele “administrative”. Dacă aveţi sau nu unul, este momentul unui
nou scrutin! Nominalizaţi-vă un număr de 4-5 elevi care să candideze pentru acest
titlu şi realizaţi o aplicaţie hipermedia care să permită sistemul “votului electronic”.
Bineînţeles, problema poate fi extinsă: fiecare candidat să aibă o pagină
separată, unde să poată să-şi facă o “campanie electorală“ cât mai interesantă,
rezultatele parţiale sau finale să poată fi vizualizate on-line, etc.
Mult succes!

2. “Forum”. Fie că este vorba de maşini sau calculatoare, probleme personale sau
profesionale, tuturor ne place să “discutăm” pe Internet! Păreri sunt multe şi de
multe ori ne place să ne amuzăm sau să deschidem un nou “topic” pe forum, în
speranţa că măcar virtual să ne facem “auziţi”. Realizaţi un astfel de site web!

3. “Vânzare/Cumpărare”. Toată lumea a auzit de succesul site-ului E-bay,


recunsocut la nivel mondial în lumea comerţului electronic. Chiar dacă nu atât de
complex, realizaţi şi voi un site care să permită:
• posibilitatea creării unui cont care să identifice unic fiecare vizitator;
• introducerea anunţurilor de tip vânzare/cumpărare;
• vizualizarea produselor existente în funcţie de categorie, preţ, etc.;
• afişarea unor rapoarte care să evidenţieze cele mai vândute produse,
preferinţele obiectelor cumpărate în funcţie de vârstă, etc.;
• trimiterea unor mesaje între utilizatori – simularea unei căsuţe poştale.
PARTEA A III-A CAPITOLUL
Iniţiere în utilizarea limbajului Java

În acest capitol vom învăţa să scriem programe în limbajul Java. Mai jos
sunt prezentate principalele noţiuni pe care le veţi studia:

 Cum instalăm Java ?


 Primul program
 Conceptul de Maşină Virtuală Java
 Care sunt tipurile de aplicaţii Java ?
 Cum introducem comentariile ?
 Afişarea şirurilor de caractere
 Tipuri de date
 Operatori
 Instrucţiuni
 Masive
 Citirea datelor de la tastatură
 Date membru
 Metode
 Exemple de utilizare a metodelor
 Supraîncărcarea metodelor

Cuvinte cheie: instalare, maşină virtuală, stand-alone, applet,


servlet, date, operatori, instrucţiuni, masive,
date membru, metode, supraîncărcare
Capitolul 6. Iniţiere în utilizarea limbajului Java 217

După studiul acestui capitol, vom putea scrie programe la nivelul celor scrise
1
în anii trecuţi în Pascal sau C/C++ . Limbajul Java este exclusiv orientat către
programarea pe obiecte. Pentru a fi uşor de înţeles, în această primă parte, vom
recurge la un mic artificiu: programul va fi în întregime conţinut într-o clasă, iar
variabilele (datele membru) şi funcţiile (metodele) vor fi statice .
2

6.1. Cum instalăm Java ?

Pentru a lucra în Java, utilizăm software-ul pus la dispoziţie de firma Sun,


creatoarea limbajului. În cele ce urmează, considerăm că lucrăm sub sistemul de
operare Windows 2000 şi calculatorul are acces la Internet.

A. Începem prin a download-a softul. Adresa este: http:\\java.sun.com.


Evident, vom alege o versiune recentă pentru sistemul Windows.
B. Pentru că software-ul pus la dispoziţie de firma Sun lucrează prin
comenzi date de la tastatură (ca în MS-DOS) va trebui să folosim, ca şi
în cazul pachetului EasyPHP, programul ”CMD.exe”. Pentru a utiliza cu
uşurinţă acest program, vom crea pe Desktop un shortcut către el
(vedeţi alăturat).
C. Va trebui ca fereastra CMD
să fie deschisă în subfolder-ul
bin al folder-ului care conţine
softul download-at şi instalat.
Executaţi clic cu butonul
drept al mouse-ului şi
selectaţi Properties.
La apariţia cutiei alăturate,
introduceţi calea folder-ului
amintit în edit-ul ”Start in”.

Figura 6.1. Cutia de dialog


“CMD.exe Properties”

D. Întrucât, în perioada de iniţiere, programele noastre se vor găsi în


folder-ul bin, pentru a lucra mai uşor, este recomandabil să creăm pe
Desktop şi un shortcut către acest folder.

Totuşi, programele pe care le vom putea realiza după studiul acestui capitol nu vor utiliza
1

fişiere. Acestea vor fi tratate în capitolul următor.


În acest capitol, din considerente pedagogice, noţiunile de clasă, dată membru statică şi
2

metodă statică nu vor fi explicate, ci doar aplicate în mod mecanic. În capitolul următor, se
va reveni asupra acestor noţiuni.
218 Manual de Informatică pentru clasa a XII-a

E. Deşi de la instalare, mediul Java ar trebui, implicit, să lucreze în folder-ul bin,


este bine ca dvs. să-l setaţi corespunzător. În acest scop, vom folosi variabila de
sistem CLASSPATH (calea către clase) care este iniţializată cu respectiva cale.
Pentru aceasta, vom respecta următorii paşi:
1. Din meniul Start, apelaţi Settings, Control Panel şi System..
2. Va apărea o cutie de dialog în care selectaţi Advanced şi Environment
Variables...:

Figura 6.2. Cutia de dialog “System Properties”

3. În cutia de dialog de mai jos, apăsaţi New:

Figura 6.3. Cutia de dialog “Environment Variables”

4. În cutia de dialog din figura alăturată, introduceţi numele variabilei de


sistem (CLASSPATH), apoi calea către folder-ul bin. Atenţie! Calea
trebuie să corespundă locului unde aveţi instalat mediul Java pe
calculatorul dvs. Apoi, apăsaţi OK!

Figura 6.4. Cutia de dialog “New User Variable”


Capitolul 6. Iniţiere în utilizarea limbajului Java 219

6.2. Primul program

De acum putem scrie primul program. Trebuie să ştim că mediul Java, pus
la dispoziţie de firma Sun, nu ne oferă un editor de text. Din acest motiv, textul
programului va fi introdus cu ajutorul NOTEPAD-ului, dar va trebui să fim atenţi ca
extensia fişierului text astfel obţinut să fie .java.

Nu uitaţi ! Pentru început, fişierul text care conţine programul trebuie să se


găsească în folder-ul bin.

Pentru a introduce şi rula un program, vom respecta paşii următori:


A. Vom deschide shortcut-ul către bin din meniul flotant, vom alege New şi Text
Document, apoi schimbăm numele fişierului în prima.java. Fişierul cu acest
nume va fi deschis din meniul flotant asociat, cu Open with... şi Notepad.
Apoi, se introduce programul de mai jos, care afişează mesajul Acesta este
primul program Java şi salvăm programul:

class prima {
public static void main(String[] args) {
System.out.println("Acesta este primul program Java");}
}

 Este obligatoriu ca numele clasei să coincidă cu numele fişierului. În


exemplu, clasa se numeşte prima, iar fişierul este prima.java.
 Este obligatoriu ca extensia fişierului text să fie .java !

B. Din fereastra CMD, apelăm compilatorul Java prin comanda:


javac prima.java

În urma acestei comenzi, se va crea fişierul prima.class. Acest fişier conţine


programul compilat. Verificaţi existenţa lui în bin!

C. Pentru a executa programul astfel compilat, vom da comanda:


java prima
Iată cum arată acum fereastra CMD:

Figura 6.5.
Fereastra CMD după
rularea programului
220 Manual de Informatică pentru clasa a XII-a

Perfect ! Dacă aţi reuşit să rulaţi acest prim program, aţi făcut un pas important.
Înseamnă că aţi instalat corect mediul şi de acum puteţi lucra liniştit. Sunt mulţi cei
care se împotmolesc în acest punct şi din acest motiv, renunţă…

Să aruncăm o privire asupra programului:

 Orice program este inclus într-o clasă. Noţiunea de clasă aparţine


programării orientate pe obiecte şi va fi explicată pe larg. În exemplu, clasa
se numeşte ”prima”.
 Aşa cum s-a precizat, numele clasei trebuie să coincidă cu numele fişierului
text sursă (cel creat cu NOTEPAD), numai că acesta din urmă trebuie să aibă
extensia ”.java”.
 Orice program are o metodă (funcţie main()) şi executarea sa începe cu
instrucţiunile acestei metode.
 În exemplu, programul afişează un şir de caractere. Instrucţiunea (apelul de
metodă) care afişează acest şir de caractere este
system.out.println().
După afişare, cursorul sare pe rândul următor.
 În Java, în locul termenului deja consacrat “funcţie”, vom folosi pe acela de
metodă.
 Este obligatoriu ca metoda main() să conţină anumiţi parametri de intrare:
String[] args. Asupra semnificaţiei acestor parametri revenim în capitolul
următor.
 Elementele public şi static sunt modificatori. Prezenţa lor în antetul
metodei main() este obligatorie. Şi asupra lor vom reveni.
 void este tipul metodei main(). Semnificaţia este cea din C++, adică
metoda nu returnează nici o valoare.
 În Java, se face distincţie între literele mari şi cele mici. De exemplu, Mama
şi mama sunt identificatori diferiţi.

6.3. Conceptul de Maşină Virtuală Java (JVM)

Una dintre cerinţele care au stat la baza creării limbajului Java a fost aceea
de a obţine un limbaj portabil. Aceasta înseamnă că un program scris pe un anumit
calculator, pe care rulează un anumit sistem de operare, să poată rula fără
modificări şi pe un alt calculator, pe care rulează alt sistem de operare. De
exemplu, să se poată scrie un program care să fie rulat pe Windows şi pe Linux.
Pentru a rezolva această problemă, cei de la Sun au recurs la următorul procedeu:
Capitolul 6. Iniţiere în utilizarea limbajului Java 221

 Fiecare utilizator al unui sistem de operare poate download-a mediul specific


acelui sistem de operare. De aceast lucru v-aţi convins atunci când aţi
download-at mediul pentru Windows.
 Mediul specific pentru un anumit sistem de operare conţine un compilator
special creat pentru el, care preia programul din fişierul sursă şi “îl traduce”
într-un cod anume, numit byte-code. Compilatorul este programul javac,
iar fişierul compilat are extensia .class.
 Programele în byte-code sunt rulate pe aşa numita Maşină Virtuală Java
(JVM). Maşina virtuală Java este un suport software care trebuie să fie
instalat pe calculatoarele care rulează astfel de fişiere. Când aţi instalat
Java, implicit aţi instalat şi maşina virtuală Java. De altfel, maşina virtuală
Java poate fi instalată şi în absenţa mediului de dezvoltare Java.
 Un fişier în byte-code (extensia .class) poate fi rulat pe orice calculator,
indiferent de sistemul de operare pe care-l are, dacă are instalată maşina
virtuală Java. Practic, se ia prima instrucţiune din fişierul byte-code, este
tradusă în instrucţiuni ale calculatorului pe care rulează aplicaţia şi acestea
din urmă sunt executate; se ia o a doua instrucţiune din byte-code care se
traduce şi se rulează, ş.a.m.d.
 Se poate observa că Java are şi un compilator care traduce sursa în
byte-code (javac.exe) dar şi un interpreter care traduce şi execută
fiecare instrucţiune din byte-code în instrucţiuni ale calculatorului pe care se
execută aplicaţia.
Observaţie ! Datorită faptului că Java este înzestrat cu interpreter (ia o
instrucţiune, o traduce şi o execută, apoi altă instrucţiune, o traduce şi o execută,
...), programele se execută mai lent. Acest fapt este compensat de procesoarele
din ce în ce mai performante, dar şi de performanţele interpreter-ului.

6.4. Tipuri de aplicaţii Java

În Java există trei tipuri de aplicaţii:

1. Aplicaţii de sine stătătoare (stand-alone). Acestea sunt precum aplicaţiile


studiate în Pascal sau C++: se rulează pe un anumit calculator.
2. Aplicaţii care se rulează pe partea de client (applet-uri). Un applet este
alcătuit dintr-unul sau mai multe fişiere cu extensia .class şi este utilizat în cadrul
paginilor web. Practic, el este ataşat textului HTML, la fel cum se ataşează o
imagine, iar fişierele care-l alcătuiesc se transferă pe site. El este adus pe
calculatorul clientului atunci când se apelează pagina respectivă şi este executat
prin intermediul browser-ului.
3. Aplicaţii care se execută pe partea de server (servlet-uri).
222 Manual de Informatică pentru clasa a XII-a

6.5. Comentarii

În Java, se pot introduce comentarii oriunde dorim, la fel ca şi în cazul


limbajului C++. Ele sunt de două feluri:
1. Comentariile la nivel de linie: // tot ce urmează după ele, pe linia celor
două caractere, este considerat comentariu.
2. Comentarii pe mai multe linii se găsesc între /* şi */.

Exemplul 6.1. Cod sursă care conţine comentarii:


class prima { // un comentariu
public static void main(String[] args) {
/* Acesta
este alt comentariu */
System.out.println("Acesta este primul program Java");
}
}

6.6. Afişarea şirurilor de caractere

Pentru afişarea datelor vom utiliza două metode:


1. System.out.print(sir_de_caractere);
2. System.out.println(sir_de_caractere);

Ambele metode afişează şirul de caractere căutat. Diferenţa dintre ele este
dată de faptul că după afişare: în primul caz, cursorul rămâne pe rândul curent
(după ultimul caracter scris), iar în cazul al doilea, după ce s-a scris şirul de
caractere, cursorul trece pe linia următoare.

6.7. Tipuri de date

În teoria clasică a limbajelor de programare, prin tip de date se înţelege:


 o mulţime de valori;
 o mulţime de operaţii definite pe mulţimea valorilor.

Limbajul Java extinde noţiunea de tip de date, la aceea de tip. Aici se


lucrează cu clase, care descriu într-o unică structură atât date cât şi metode
(funcţii). Obiectele sunt instanţieri ale claselor, deci fiecare obiect conţine atât date
Capitolul 6. Iniţiere în utilizarea limbajului Java 223
cât şi metode. Asupra acestor probleme vom reveni, dar reţineţi faptul că, în Java,
prin tip vom înţelege o clasă, iar un obiect are un anumit tip dacă rezultă ca
instanţiere a unei clase.
Totuşi, limbajul Java utilizează şi tipuri în sens clasic, vezi prima definiţie.
Pentru a nu se crea confuzii, aceste tipuri se numesc tipuri primitive. Astfel, avem
tipuri de date primitive şi tipuri referinţă.

6.7.1. Tipurile de date primitive

a) Tipuri întregi

Octeţi
Tip Numere întregi din intervalul
ocupaţi
byte 1 [-128,127]
short 2 [-32768,32768]
int 4 [-2147483648, +2147483647]
long 8 [-9223372036854775808,9223372036854775807]

Tabelul 6.1. Tipuri de date întregi

Exemplul 6.2. Declarăm şi afişăm mai multe variabile de tip întreg:


short t=32767;
byte z=-128, x=15;
int a=100000;

b) Tipuri reale

Tip Octeţi ocupaţi Modulul valorilor între


float 4 [3.4×10-38, 3.4×1038]
double 8 [1.7×10-308,1.7×10308]

Tabelul 6.2. Tipuri de date reale

Pentru iniţializarea tipurilor reale se folosesc literali.

Observaţie ! Pentru tipul real float, literalii trebuie urmaţi în mod obligatoriu de
litera f. Excepţie fac literalii care reprezintă valori întregi.

Exemplul 6.3. Priviţi iniţializările de mai jos:


1. float a=3,b=2.5f,c=-7,d=3E2f,g=-2.4E-2f; Valorile cu care am
iniţializat variabilele sunt: 3, 2, 2.5, -7, 3×102, -2.4×10-2.
Aceleaşi valori se folosesc pentru a iniţializa variabile de tip double:
2. double a=3,b=2.5,c=-7,d=3E2,g=-2.4E-2;
224 Manual de Informatică pentru clasa a XII-a

c) Tipul char
O variabilă de tipul char reţine un caracter. În Pascal, C/C++, caracterele
sunt reţinute prin utilizarea codului ASCII. În Java, codul utilizat pentru
memorarea caracterelor este Unicode şi, în acest cod, un caracter ocupă 2 octeţi.

Exemplul 6.4. Mai jos, puteţi observa declaraţia a trei variabile de tip char:
char a='m', b='\u006d', c=109;
System.out.println(a); System.out.println(b);
System.out.println(c);

Toate variabilele reţin caracterul m. Prima dată, caracterul este declarat în


mod clasic, iar a doua oară, este declarat prin codul său în hexa şi a treia oară este
declarat în zecimal. Cele afirmate sunt probate prin afişare, pentru că se afişează
de trei ori m.
Caracterele se pot declara sub formă de coduri escape:

Caracter Semnificaţie
\\ backslash
\n newline
\' apostrof
\” ghilimele
\r carriage return
\t tab
\f salt la pagină nouă

Tabelul 6.3. Tipuri de caractere sub formă escape

Exemplul 6.5. Priviţi declaraţiile de mai jos:


1. char a='\''; am declarat caracterul apostrof. Dacă am încerca să
declarăm acest caracter prin char a='''; primim eroare de sintaxă.
2. char b='\n'; am declarat caracterul newline. Dacă se afişează acest
caracter, cursorul sare pe linia următoare.
3. char c='\\'; am declarat caracterul backslash. Dacă am încerca să
declarăm acest caracter prin char a='\'; primim eroare de sintaxă.

d) Tipul boolean
O variabilă de acest tip poate reţine la un moment dat, una din cele două
valori: false (fals) sau true (adevărat).
Exemplul 6.6. Se declară, se iniţializează şi se afişează conţinutul unei variabile
de tip boolean:
boolean c=true; System.out.println(c);
Observaţie ! Metodele System.out.print() şi System.out.println()
permit afişarea tuturor tipurilor primitive.
Capitolul 6. Iniţiere în utilizarea limbajului Java 225

6.7.2. Tipul referinţă

O variabilă de tip referinţă reţine o referinţă (adresă) către un obiect. Cu


ajutorul referinţei, putem accesa datele membru şi metodele obiectului. Numele
tipului unei astfel de variabile coincide cu numele clasei. Cum obiectele sunt
instanţieri ale claselor şi cum putem proiecta o infinitate de clase, înseamnă că
există o infinitate de tipuri referinţă. Prin abuz de limbaj, vom spune despre o
variabilă care poate reţine o referinţă către un anumit obiect că este de tip
referinţă. Orice variabilă de tip referinţă poate reţine valoarea null. Ea are
semnificaţia de “nici o referinţă”.

6.7.3. Observaţii importante

Cu ajutorul celor două metode:


System.out.print() şi System.out.println(),
putem afişa conţinuturile variabilelor de un tip primitiv. Mai avem de precizat două
lucruri esenţiale:
a. Dacă în corpul unei metode, în exemplu main(), se găseşte o variabilă
neiniţializată şi se încearcă afişarea conţinutului pe care îl are, tentativa este
sancţionată prin eroare de sintaxă. Vedeţi mai jos:
int i; System.out.println(i);
b. Avem posibilitatea de a afişa mai multe variabile pe aceeaşi linie. Aceasta se
obţine prin convertirea conţinutului variabilelor în şiruri de caractere şi
concatenarea şirurilor cu ajutorul operatorului +. Vedeţi exemplul de mai jos
care afişează pe o linie a=2 b=4.5:
int a=2; float b=4.5f;
System.out.println("a="+a+" b="+b);

6.8. Operatori
În acest paragraf vor fi prezentaţi operatorii utilizaţi în Java.

6.8.1. Operatori aritmetici


Există următorii operatori aritmetici:
• - minus (unar, adică acţionează asupra unui singur operand);
• + plus (unar);
• + (binar), pentru adunare;
226 Manual de Informatică pentru clasa a XII-a

• - (binar), pentru scădere;


• * (binar), are semnificaţia de înmulţire;
• / (binar), pentru împărţire;
• % (binar) restul împărţirii întregi.

Observaţii !
 Operatorul '/' (împărţire) acţionează în mod diferit în funcţie de operanzi:
a) dacă ambii sunt de tip întreg, rezultatul este întreg şi are semnificaţia de
împărţire întreagă. Cu toate acestea, rezultatul este corect (din punct de
vedere matematic) numai dacă valorile care se împart sunt pozitive.
b) dacă cel puţin un operand este de unul din tipurile reale rezultatul este
real (se efectuează împărţirea obişnuită).
 Operatorul '%' acţionează numai asupra operanzilor de tip întreg. Rezultatul
obţinut este corect din punct de vedere matematic numai dacă ambii
operanzi sunt numere naturale.
 În cazul în care se împart două valori întregi se procedează astfel:
 se face împărţirea întreagă a celor două valori care sunt
considerate în modul;
 semnul câtului se stabileşte după regula semnelor (+ cu + rezultă
+, + cu -, rezultă -), etc.
 în cazul operatorului '%', se face împărţirea ca anterior (se obţine
C), iar restul se obţine după formula R=D-Î×C.
 se pot utiliza oricâte perechi de paranteze rotunde, pentru a
impune ca anumite operaţii să se facă prioritar.

Exemplul 6.7. Fie declaraţia: int a=10;. Atunci expresia 4*a/3 este de tip int
şi la evaluare se obţine 13. S-a înmulţit 4 cu conţinutul variabilei a (10) şi s-a
obţinut 40. Apoi, 40/3=13 (a fost efectuată împărţirea întreagă). În aceleaşi
condiţii, expresia 4*(a/3) are ca rezultat numărul 12. La început s-a efectuat
a/3 şi s-a obţinut 3, apoi 4*3=12. Iată un exemplu în care se observă faptul că
una este o expresie la matematică, şi alta în Java.
Exemplul 6.8. Fie declaraţia: float a=10;. Expresia 4*(a/3) are rezultatul
13.3333, la fel ca expresia 4*a/3. De această dată, s-a efectuat împărţirea a
două numere reale.
Exemplul 6.9. Fie declaraţia: int a= -10;. Atunci expresia a%3 are ca rezultat
numărul -1.
Exemplul 6.10. Fie declaraţia: int a=-10;. Atunci expresia a*-3 are ca rezultat
numărul 30.
Capitolul 6. Iniţiere în utilizarea limbajului Java 227

Exemplul 6.11. Fie declaraţiile: int a=10; char b=2; float c=5;. Atunci
expresia: a+b+c are rezultatul 17.0.

În exemple, apare o problemă foarte importantă: care este tipul rezultatului,


în cazul în care o expresie aritmetică are operanzi de mai multe tipuri? Problema
de mai sus se numeşte problema conversiilor aritmetice implicite (după cum
vom vedea, conversiile se pot face şi explicit).

Regula generală este: se converteşte unul din operanzi către tipul


celuilalt (mai cuprinzător). De exemplu, dacă unul din operanzi este de tip int,
iar celălalt de tip float, rezultatul va fi de tip float.

Observaţie ! Fără o conversie prealabilă, operatorii aritmetici nu acţionează


asupra variabilelor de tip char. De exemplu, secvenţa char x=’1’; x=x+1; este
eronată din punct de vedere sintactic.

6.8.2. Operatori relaţionali

În Java există următorii operatori relaţionali:


• < (mai mic);
• <= (mai mic sau egal);
• > (mai mare);
• >= (mai mare sau egal).

Întrucât în Java există valorile logice true şi false, rezultatul unei operaţii
logice este una dintre aceste valori.
Exemplul 6.12. Analizaţi expresiile de mai jos:
3>5 - expresia ia valoarea false;
3<5 - expresia ia valoarea true;
3+7>=11-1 - expresia ia valoarea true (este posibil să scriem astfel de expresii,
întrucât operatorii relaţionali au o prioritate mai mică decât operatorul aditiv).

6.8.3. Operatori de egalitate

Operatorii de egalitate sunt:


• == pentru egalitate;
• != pentru inegalitate.

Ca şi operatorii relaţionali, expresiile de acest tip returnează 0 sau 1, în


funcţie de modul în care este respectată sau nu egalitatea (inegalitatea).

Exemplul 6.13. Expresiile: 3==3 are ca rezultat true; 3!=3 are ca rezultat false.
228 Manual de Informatică pentru clasa a XII-a

6.8.4. Operatorii de incrementare şi decrementare

Aceşti operatori sunt unari şi au rolul de a incrementa (adună 1) sau de a


decrementa (scad 1) conţinutul unei variabile. Operatorii sunt:
• ++ pentru incrementare;
• -- pentru decrementare.
Operatorii pot fi prefixaţi (aplicaţi în faţa operandului) sau postfixaţi (aplicaţi
după operand). Exemplu: fie a o variabilă de tip int.
Operatorul de incrementare prefixat aplicat variabilei a este ++a.
Operatorul de incrementare postfixat aplicat variabilei a este a++.
Operatorul de decrementare prefixat aplicat variabilei a este –-a.
Operatorul de decrementare postfixat aplicat variabilei a este a--.
Care este diferenţa între efectul unui operator aplicat prefixat sau postfixat?
Să ne gândim la faptul că pot fi expresii care conţin şi alţi operatori în afara celor
de incrementare (decrementare).

⇒ Dacă operatorul este prefixat, variabila este incrementată (decrementată)


înainte ca valoarea reţinută de ea să intre în calcul.

⇒ Dacă operatorul este postfixat, variabila este incrementată (decrementată)


după ce valoarea reţinută de ea intră în calcul.

Exemplul 6.14. Fie a o variabilă de tip int care reţine valoarea 1. În urma evaluării
expresiei 1+a++ se obţine valoarea 2, dar după evaluare, a va reţine valoarea 2
(variabila a fost incrementată după ce valoarea reţinută de ea a intrat în calcul).

Exemplul 6.15. La fel ca în cazul anterior, expresia 1-++a produce valoarea -1


(variabila a fost întâi incrementată, s-a obţinut 2, apoi s-a efectuat 1-2).

6.8.5. Operatori logici

Există trei tipuri de operatori logici care acţionează asupra datelor de tip
boolean:
• ! negare logică;
• && şi logic;
• || sau logic.

Aceşti operatori se aplică oricărei variabile şi constante de tip logic.


Operatorul negare logică acţionează astfel: dacă operandul este o valoare
true, rezultatul este false, altfel rezultatul este true.
Operatorul şi logic (binar) acţionează astfel: dacă ambii operanzi sunt true
rezultatul este true, altfel el este false.
Capitolul 6. Iniţiere în utilizarea limbajului Java 229

Operatorul sau logic (binar) acţionează astfel: dacă cel puţin unul din
operanzi este true, rezultatul este true, altfel rezultatul este false.

Exemplul 6.16. În condiţiile: boolean a=true, b=false;


!a returnează false;
a||b returnează true;
a&&b returnează false;
Operatorii logici binari garantează modul în care se tratează operanzii - întâi
cel din stânga, apoi (dacă este cazul) cei din dreapta. Astfel, dacă operandul din
stânga este true, operatorul sau logic nu mai acţionează asupra operandului din
dreapta (este clar că rezultatul este true). Tot aşa, dacă operandul din stânga
este false, operatorul şi logic nu mai evaluează operandul din dreapta (oricum
rezultatul este false). Observaţia este foarte importantă pentru cazul în care al
doilea argument este funcţie (metodă) de tip boolean.

6.8.6. Operatori logici pe biţi

Limbajul Java este dotat cu un set de operatori care permit accesul la bit.
Aceştia sunt:
• <<, >>, >>> operatori de deplasare;
• & şi pe biţi;
• | sau pe biţi;
• ^ sau exclusiv pe biţi;
• ~ negare pe biţi (operator unar).

Aceşti operatori acţionează numai asupra operanzilor de tip întreg.

Operatorul << este binar. El are rolul de a deplasa către stânga conţinutul tuturor
biţilor operandului din stânga sa, cu un număr de poziţii egal cu valoarea reţinută
de al doilea operand. Poziţiile rămase libere (în dreapta) vor reţine valoarea 0.
Dacă al doilea operand reţine valoarea m, o astfel de deplasare este echivalentă cu
înmulţirea cu 2m (evident, dacă m este mai mic decât numărul de biţi rezervat
primului operand).
Operatorul >> este binar. El are rolul de a deplasa către dreapta conţinutul tuturor
biţilor operandului din stânga cu un număr de poziţii egal cu valoarea reţinută de al
doilea operand. Atenţie: în poziţiile din stânga, rămase libere după deplasare, se
copiază conţinutul bitului de semn (acesta reţine 1 în cazul numerelor negative şi
0, în cazul numerelor pozitive). Dacă operandul din stânga este un întreg pozitiv,
poziţiile rămase libere (în stânga) vor reţine valoarea 0. În cazul întregilor pozitivi,
dacă al doilea operand reţine valoarea m, o astfel de deplasare este echivalentă cu
împărţirea întreagă cu 2m.
Operatorul >>> acţionează la fel ca şi operatorul >>, dar diferenţa este dată de
faptul că poziţiile rămase libere din dreapta vor reţine 0.
230 Manual de Informatică pentru clasa a XII-a

Atenţie ! Operatorii de deplasare sunt utilizaţi doar pentru evaluarea expresiilor,


operanzii, chiar dacă sunt variabile, rămân nemodificaţi! Desigur, valorile astfel
obţinute pot fi atribuite. Aceasta înseamnă de fapt acces la bit.
În cazul operatorilor binari &, ^, |, rezultatul se obţine aplicând pentru fiecare
pereche de biţi aflaţi pe aceeaşi poziţie regulile din tabelul următor:

OP1 OP2 OP1&OP2 OP1^OP2 OP1|OP2


0 0 0 0 0
1 0 0 1 1
0 1 0 1 1
1 1 1 0 1
Tabelul 6.4. Rezultatele operatorilor binari

Operatorul ~ (negare pe biţi) are rolul de a inversa conţinutul biţilor (dacă un


bit conţine 0 va conţine 1 şi invers).
Exemplul 6.17. Dacă a este de tip int şi reţine 3, iar b este de acelaşi tip şi reţine
1, atunci:
a&b returnează 1;
a|b returnează 3;
a^b returnează 2;
a<<2 returnează 6;
a>>1 returnează 1;
~a returnează -4.

6.8.7. Operatori de atribuire

În Java atribuirea este operator, dar după cum vom vedea, este şi
instrucţiune. În plus, avem mai mulţi operatori de atribuire. Operatorul '=' se
foloseşte într-o expresie de forma:
v=expresie
Aici, v este o variabilă.

Principiul de executare este următorul:


• se evaluează expresia;
• variabilei v i se atribuie valoarea obţinută (dacă este cazul se
efectuează conversia respectivă).

Se pot efectua şi atribuiri multiple de forma:


v=v1=v2=...=vn=expresie,
unde v, v1, v2, ..., vn sunt variabile.
Capitolul 6. Iniţiere în utilizarea limbajului Java 231

În acest caz, principiul de executare este următorul:

• se evaluează expresia;
• valoarea obţinută este atribuită variabilei vn (eventual convertită, dacă
este cazul);
• conţinutul variabilei vn este atribuit variabilei vn-1 (eventual se
efectuează conversia necesară);
• ...
• conţinutul variabilei v1 este atribuit variabilei v (eventual se efectuează
conversia necesară).
Acest operator se asociază de la dreapta la stânga. Ce am prezentat anterior
evidenţiază acest lucru.
Pentru atribuiri se mai pot utiliza şi operatorii: *=, /=, %=, +=, -=, <<=,
>>=, &>, ^=, |=.

O atribuire de forma: v op=expresie, are acelaşi rezultat ca


v=v op expresie
(diferenţa este că în primul caz se generează un cod maşină eficient).

Observaţie! Am văzut că atribuirea este un operator care figurează într-o expresie.


Ca orice expresie, aceasta are o valoare rezultată în urma evaluării. În cazul
atribuirilor, valoarea rezultată este valoarea atribuită variabilei care este prima din
stânga, (într-un şir de atribuiri, eventual după conversie).
Exemplul 6.18. Fie declaraţiile: int a=5, b=3; float c;. În urma atribuirii
c=a/b, c va conţine valoarea reală 1.0. Este normal să fie aşa întrucât expresia
a/b este de tip int (se efectuează împărţirea întreagă şi se obţine 1), apoi
această valoare este atribuită variabilei c (după ce este convertită).

Exemplul 6.19. Fie declaraţiile: int a,b; float c; şi expresia c=a=b=1.


După evaluare, a reţine 1, b reţine 1, c reţine 1.0, iar valoarea rezultată în urma
evaluării este 1.0 (reală).

Exemplul 6.20. Fie declaraţia: int a=3; şi expresia a*=2. În urma evaluării, a
reţine valoarea 6, iar expresia va produce valoarea de tip int 6.

Observaţie foarte importantă ! Sunt permise doar atribuiri în care tipul variabilei
căreia i se atribuie conţinutul unei variabile de alt tip, conţine, printre valorile
permise, cele ale tipului variabilei care este atribuită.

Exemplul 6.21. Fie declaraţiile: long a=2; int b=3;


a=b; // corect
b=a; // incorect
232 Manual de Informatică pentru clasa a XII-a

Exemplul 6.22. Fie declaraţiile: char a=2; int b=3;


b=a; //corect
a=b; //incorect

Exemplul 6.23. Fie declaraţiile: float a=2; int b=3;


a=b; //corect
b=a; //incorect

Exemplul 6.24. Fie declaraţiile: float a=2; double b=3;


b=a; //corect
a=b; //incorect

Observaţie ! După cum observaţi, aici apare o diferenţă faţă de C/C++. Java, ca
şi Pascal-ul, încearcă să te ferească de erori ascunse, rezultate în urma
conversiilor implicite.

6.8.8. Operatorul condiţional

Se foloseşte în expresii de genul:


exp1?exp2:exp3

Cerinţa este ca exp1 să fie de tipul boolean. Principiul de executare este următorul:
• se evaluează exp1;
• dacă aceasta produce true, se evaluează exp2 şi exp3 este ignorată
(nu se evaluează);
• altfel, se evaluează exp3 şi exp2 este ignorată.

În ansamblu, expresia este de tipul lui exp2 sau exp3 şi produce valoarea
exp2 sau exp3 (în funcţie de cea care se evaluează).

Exemplul 6.25. Variabila c ia valoarea 5 (valoarea maximă).


int a=1, b=5, c;
c=a>b?a:b;

Exemplul 6.26. Se afişează valoarea 5.


int a=1, b=5, c;
System.out.println(a>b?a:b);

Exemplul 6.27. Variabila h ia valoarea 9. Aici se observă că nu este obligatoriu ca


exp2 şi exp3 să aibă acelaşi tip:
int a=1, b=5; float d=9,h;
h=a>b?a:d;
Capitolul 6. Iniţiere în utilizarea limbajului Java 233

6.8.9. Operatorul de conversie explicită

De multe ori, vrem ca unul sau mai mulţi operanzi să intre în calcul convertiţi
aşa cum dorim (nu implicit). Pentru aceasta, înaintea operandului se trece între
paranteze tipul său.

Exemplul 6.28. Variabila a ia valoarea 9. Iată că, deşi implicit conversia nu poate fi
realizată, în acest mod s-a efectuat fără probleme.
int a=1; double d=9.6;
a=(int)d;

Exemplul 6.29. Se afişează 0.5. Iată că, deşi operanzii sunt întregi şi rezultatul ar
trebui să fie 0, prin utilizarea operatorului de conversie explicită se obţine rezultatul
corect.
int a=3, b=6;
System.out.println((float) a/b);

6.8.10. Prioritatea (precedenţa) operatorilor

Operatorii au o anumită prioritate (precedenţă). Mai jos, sunt prezentaţi


operatorii în ordinea descrescătoare a priorităţii:

1) (), . , []
2) ++, --, +(unar),–(unar),!, new, operatorul de conversie explicită
3) *, /, %
4) +, - (priviţi ca operatori binari)
5) <<, >>, >>>
6) <, <=, >, >=
7) ==, !=
8) &
9) ^
10) |
11) &&
12) ||
13) ?:
14) =, +=, etc (operatori de atribuire)
234 Manual de Informatică pentru clasa a XII-a

6.9. Instrucţiuni

6.9.1. Instrucţiunea vidă

Instrucţiunea nu face nimic, dar are sens în programul Java, după cum va
rezulta din studiul altor instrucţiuni. Instrucţiunea vidă se marchează prin ;.

6.9.2. Instrucţiunea compusă

Se utilizează atunci când se doreşte ca mai multe instrucţiuni să fie


considerate ca o singură instrucţiune.

Exemplul 6.30. Mai jos, puteţi observa o instrucţiune compusă care subordonează
mai multe instrucţiuni vide.
{
;
;
;
}

6.9.3. Instrucţiunile de incrementare şi de decrementare

Se utilizează pentru a incrementa sau decrementa o anumită variabilă.

Exemplul 6.31. Diverse incrementări/decrementări: a++; ++a; a--; --a;.

Observaţie ! Există o diferenţă între operatorii de incrementare (decrementare) şi


instrucţiunea de incrementare (decrementare). Instrucţiunea de incrementare
(decrementare) conţine numai un operator de incrementare (decrementare), dar de
exemplu, b=++a+1 este o instrucţiune (atribuire, vezi mai jos) care conţine şi un
operator de incrementare.

6.9.4. Instrucţiunea de atribuire

Conţine o expresie prin care unei variabile i se atribuie o altă expresie (aflată
în dreapta operatorului de atribuire).
Exemplul 6.32. Analizaţi atribuirile următoare:
a) int a, b=6;
a=b+5; // după atribuire a reţine 11.
Capitolul 6. Iniţiere în utilizarea limbajului Java 235

b) int a, b=6;
a=++b+5; // după atribuire a reţine 12.
c) int a=1, b=6;
a+=b; // după atribuire a reţine 7.
d) a=b=c=1; // a, b, c sunt de tip int.

Exemplul 6.33. Iată o atribuire multiplă. Iniţial, c ia valoarea 1, apoi b=c, atunci
b=1, apoi a=b, deci a=1. După atribuire a, b, şi c reţin 1.

Observaţii !
 Nu sunt permise atribuiri de genul: ++a=b+5;.
 Există o diferenţă între operatorul de atribuire şi instrucţiunea de atribuire.
De exemplu, a=b=c=1 este o instrucţiune de atribuire, dar conţine 3
operatori (de atribuire). Practic, o instrucţiune de atribuire conţine cel puţin
un operator de atribuire.

6.9.5. Instrucţiunea IF

Această instrucţiune are două forme:

Forma 1.
if (expresie de tip boolean) instrucţiune1 else instrucţiune2

Principiul de executare este următorul:

⇒ se evaluează expresia;
⇒ dacă valoarea produsă de aceasta este true, se execută
instrucţiune1;
⇒ dacă valoarea produsă este false se execută instrucţiune2.

Forma 2.
if (expresie de tip boolean) instrucţiune

Principiul de executare este următorul:

⇒ se evaluează expresia;
⇒ dacă valoarea produsă de aceasta este true, se execută
instrucţiunea subordonată, altfel se trece la cea următoare.

Exemplul 6.34. Se afişează cea mai mare valoare dintre valorile reţinute de
variabilele a şi b:
if (a>b) System.out.println(a);
else System.out.println(b);
236 Manual de Informatică pentru clasa a XII-a

Exemplul 6.35. Se rezolvă ecuaţia ax+b=0, unde pentru valorile lui a şi b sunt
reţinute variabilele cu acelaşi nume.
if (a!=0)
{ x=-b/a;
System.out.println(x); }
else
if (b==0) System.out.println("infinitate de solutii");
else System.out.println("nu are solutie");

6.9.6. Instrucţiunea WHILE

Forma generală a acestei instrucţiuni este:


while (expresie de tip boolean) instrucţiune

Principiul de executare este următorul:

⇒ Se evaluează expresia;
⇒ Dacă valoarea produsă de aceasta este true, se execută instrucţiunea
subordonată, apoi se revine la evaluarea expresiei, altfel se trece la
instrucţiunea următoare.

Exemplul 6.36. Pentru n>0, număr natural, să se calculeze suma cifrelor sale
(pentru n=213, se va afişa 6):
int n=213,s=0;
while (n!=0)
{ s+=n%10;
n/=10;
}
System.out.println(s);

6.9.7. Instrucţiunea DO WHILE

Forma generală a acestei instrucţiuni este următoarea:


do
instrucţiune
while(expresie);

Principiul de executare este următorul:

⇒ Se execută instrucţiunea subordonată;


⇒ Se evaluează expresia. În cazul în care valoarea produsă la evaluare
este false, executarea instrucţiunii do while se termină, altfel se
trece la pasul anterior.
Capitolul 6. Iniţiere în utilizarea limbajului Java 237

Observaţie ! Secvenţa se execută cel puţin o dată, după care se pune problema
dacă să se repete sau nu (prin evaluarea expresiei logice).

Exemplul 6.37. Se dă un număr natural n, mai mare sau egal cu 1. Să se


calculeze suma primelor n numere naturale nenule.
int n=10,s=0,i=1;
do
{ s=s+i;
i=i+1;
} while (i<=n);
System.out.println(s);

6.9.8. Instrucţiunea FOR

Instrucţiunea FOR are forma generală:


for(expresieiniţializare;expresietest;expresieincrementare)
instrucţiune

După cum se vede, între paranteze se găsesc 3 expresii:


• Expresieinitializare se foloseşte de regulă pentru iniţializarea variabilei de
ciclare. Este de remarcat faptul că în cadrul acestei expresii (cu rol special)
este posibil chiar să declarăm variabila de ciclare (cu valoare iniţială).
• Expresietest este de tip boolean şi se foloseşte pentru a testa dacă se
execută instrucţiunea subordonată - dacă expresia produce la evaluare
true, instrucţiunea subordonată for se execută.
• Expresieincrementare se foloseşte pentru incrementarea variabilei de ciclare.

Principiul de executare este:


P1. Se evaluează expresieiniţializare (un caz special este când aceasta
conţine şi declaraţia variabilei de ciclare);
P2. Se evaluează expresietest. În cazul în care aceasta produce true, se
execută instrucţiunea subordonată for; apoi se trece la P3, altfel se trece la
instrucţiunea următoare (se termină executarea instrucţiunii for).
P3. Se evaluează expresia de incrementare şi se revine la P2.
Observaţie ! Toate expresiile pot fi vide. În concluzie, expresiile de mai sus au
rolul precizat în mod normal - dar nu obligatoriu şi nici restrictiv. De exemplu, dacă
expresietest este vidă, se execută un ciclu infinit for(;;) instrucţiune.

Exemplul 6.38. Se afişează numerele, 10, 9, ..., 1, fiecare pe câte un rând.


Observaţi faptul că variabila i a fost declarată în cadrul ciclului for.
for (int i=10;i>=1;i--) System.out.println(i);
238 Manual de Informatică pentru clasa a XII-a

Exemplul 6.39. Se afişează alfabetul, de la ‘a’ la ‘z’ şi pentru fiecare caracter se


afişează şi codul său:
for (char c='a';c<='z';c++)
System.out.println(c+" "+(int)c);

6.9.9. Instrucţiunea BREAK

Are rolul de a forţa ieşirea dintr-un ciclu. În cazul în care există cicluri
imbricate (un ciclu în interiorul altui ciclu), forţează doar ieşirea din primul ciclu
(vezi secvenţa următoare, unde for-ul după j se execută doar pentru j=1). Se
foloseşte pentru instrucţiunile for, while, do while şi în particular, pentru
switch (cazul va fi studiat separat).

Exemplul 6.40. Analizaţi secvenţa de mai jos: Se afişează:


for (int i=1;i<=4;i++) 1 1
for (int j=1;j<=4;j++) 2 1
if (j==2) break; 3 1
else System.out.println(i+" "+j); 4 1

6.9.10. Instrucţiunea CONTINUE

Instrucţiunea este folosită în cazul ciclurilor (for, while, do while) şi are


rolul de a determina ca, după executarea ei, să se sară direct la testul condiţiei de
continuare. Astfel, se ignoră instrucţiunile care îi urmează în secvenţa care se
repetă.

Exemplul 6.41. Secvenţa următoare afişează: 1, 3, 4. Dacă i ia valoarea 2,


atunci se execută continue şi se sare peste apelul metodei de afişare.
for (int i=1;i<=4;i++)
{ if (i==2) continue;
System.out.println (i);}

6.9.11. Instrucţiunea SWITCH

Instrucţiunea are forma particulară:


switch (expresie)
{ case exp1: secvenţă instrucţiuni1; break;
case exp2: secvenţă instrucţiuni2; break;
.................................
case expn: secvenţă instrucţiunin; break;
[default: secvenţă instrucţiunin+1];
}
Capitolul 6. Iniţiere în utilizarea limbajului Java 239

unde:
• expresie are semnificaţia: expresie de tip întreg (sau char);
• expi : sunt expresii constante de tip întreg (sau char);
• instrucţiunii reprezintă o secvenţă oarecare de instrucţiuni.

Principiul de executare este:


⇒ se evaluează expresia;
⇒ dacă aceasta produce o valoare egală cu cea produsă de expi, se
execută în ordine instrucţiunii şi se trece la instrucţiunea următoare,
altfel se execută numai secvenţa instrucţiunin+1.

Observaţie ! Alternativa default este facultativă. În absenţă, în cazul în care nu


există coincidenţă de valori, se trece la instrucţiunea următoare.

Exemplul 6.42. Secvenţa care urmează probează instrucţiunea switch. Se va


afişa 1:
int i =1;
switch(i)
{ case 1: System.out.println(1);break;
case 2: System.out.println(2);break;
default: System.out.println("altceva");
}

Observaţie ! Am prezentat o formă simplificată a instrucţiunii switch, mai precis,


cea corespunzătoare programării structurate. În absenţa instrucţiunii break, în
cazul în care există egalitate între expresie şi expi se execută secvenţa
corespunzătoare şi, pe rând, toate secvenţele care urmează, ş.a.m.d.

Exemplul 6.43. Secvenţa care urmează afişează: 2, altceva:


int i =2;
switch(i)
{ case 1: System.out.println(1);
case 2: System.out.println(2);
default: System.out.println("altceva");
}

Observaţie ! În forma generală, instrucţiunea switch are rolul de a stabili mai


multe puncte de intrare într-o secvenţă de instrucţiuni, în funcţie de valoarea pe
care o reţine expresie.

6.9.12. Instrucţiunea apel metodă (funcţie)

Aceasta va fi tratată la momentul potrivit. Pentru moment, putem da ca


exemplu doar System.out.print() sau System.out.println().
240 Manual de Informatică pentru clasa a XII-a

6.9.13. Instrucţiunea de declarare a variabilelor

Până în prezent, am întâlnit-o de multe ori. Ea poate fi plasată oriunde în


corpul unei metode (funcţii).

Exemplul 6.44. Instrucţiunea int x=2,y.

6.10. Masive

În Java există un mecanism excepţional de lucru cu masive (vectori,


matrice, etc). Din motive didactice, pentru început, vom prezenta declararea
masivelor în doi paşi:

Pasul 1. Se declară o variabilă care poate reţine o referinţă (adresă) către vector,
matrice, etc.
Exemplul 6.45. Analizaţi declaraţiile de mai jos:
a) int[] V; am declarat o variabilă referinţă către un vector cu componente de
tip int. O declaraţie echivalentă poate fi făcută prin: int V[];.
b) int[][] Mat; am declarat o variabilă referinţă către o matrice cu
componente de tip int.
c) float[] V, V1; am declarat două variabile referinţă către vectori, numite
V, respectiv V1. Ambii vectori au componente de tip float.
d) float Mat[][],Mat1[][]; am declarat două variabile de tip referinţă
către matrice. Cele două variabile se numesc Mat şi Mat1.

Pasul 2. Alocăm spaţiu în memorie pentru masiv (vector, matrice). Adresa


vectorului va fi reţinută în variabila V.

Exemplul 6.46. Urmăriţi exemplele de mai jos:


a) V=new int[4];. Am alocat spaţiu în memorie pentru un vector cu 4
componente de tip int (practic am creat vectorul). Referinţa către el va fi reţinută
în V şi pornind de la această variabilă putem accesa V.
b) Mat=new int [4][3];. Am alocat spaţiu în memorie pentru o matrice cu 4
linii şi 3 coloane cu componente de tip int.

⇒ Prima componentă a unui vector are indicele 0, a doua indicele 1 ş.a.m.d.


Tot aşa, liniile unei matrice se numerotează începând cu 0, coloanele unei
matrice se numerotează începând cu 0.
Capitolul 6. Iniţiere în utilizarea limbajului Java 241

⇒ O componentă a unui vector se adresează pornind de la referinţă şi scriind


indicele între paranteze drepte (exemplu V[3]). O componentă a unei
matrice se adresează pornind de la referinţă si scriind între paranteze
pătrate fiecare din cei doi indici (exemplu Mat[2][1]).

Exemplul 6.47. În secvenţa următoare se creează un vector, se iniţializează


fiecare componentă a lui şi se afişează:
int[] V; // sau int V[];
V=new int[4]; int i;
for (i=0;i<4;i++) V[i]=i+1;
for (i=0;i<4;i++) System.out.println(V[i]);

Schema alăturată reflectă


modul în care arată vectorul, V 1 2 3 4
după ce i-am iniţializat 0 1 2 3
componentele.
referinţa
Figura 6.6. Vectorul după
ce a fost iniţializat

 Vectorii se pot declara şi aşa cum se vede mai jos, gata iniţializaţi. În urma
unei astfel de declaraţii se poate lucra direct cu ei, exact ca anterior.
int[] V={1,2,3,4}; int i;
for (i=0;i<4;i++) V[i]=i+1;
for (i=0;i<4;i++) System.out.println(V[i]);

Exemplul 6.48. În secvenţa următoare se creează o matrice, se iniţializează


fiecare componentă a ei şi se afişează:
int[][] Mat;
int i,j;
Mat=new int [4][3];
for (i=0;i<4;i++)
for (j=0;j<3;j++) Mat[i][j]=i+j;
for (i=0;i<4;i++)
{ for (j=0;j<3;j++) System.out.print(Mat[i][j]+" ");
System.out.println();
}

 Ca şi vectorii, matricele se pot declara şi aşa cum se vede mai jos, gata
iniţializate. În urma unei astfel de declaraţii se poate lucra direct cu ele, exact
ca anterior.

int[][] Mat={{1,2,3,4},{3,4,5,6}};
int i,j;
for (i=0;i<2;i++)
{ for (j=0;j<3;j++) System.out.print(Mat[i][j]+" ");
System.out.println();
}
242 Manual de Informatică pentru clasa a XII-a

 Declararea unui masiv se poate face şi într-un singur pas, ca mai jos:
float[] V=new float[4];

⇒ De vreme ce numele masivului (V, Mat, în exemplele date) reţine o referinţă


către masiv, înseamnă că unei astfel de variabile i se poate atribui o referinţă
către alt masiv, ceea ce este echivalent cu faptul că atribuirea “funcţionează”
în cazul masivelor ca în cazul variabilelor de unul din tipurile de date primitive.
Totuşi, există o diferenţă esenţială: se atribuie doar referinţa, nu conţinutul
masivului, care rămâne nemodificat. Masivul care nu mai este referit va fi
şters, automat (fără ca, în acest scop, să fie scrisă o secvenţă specială).

Exemplul 6.49. Avem doi vectori, V şi V1. Cei doi vectori sunt creaţi şi iniţializaţi.
După aceasta, se interschimbă referinţele către cei doi vectori şi, în vederea
probării operaţiilor efectuate, se afişează.
float[] V=new float[4], V1=new float[3], Man;
int i;
for (i=0;i<4;i++) V[i]=i+1;
for (i=0;i<3;i++) V1[i]=9;
Man=V1;
V1=V;
V=Man;
for (i=0;i<4;i++) System.out.println(V1[i]);
for (i=0;i<3;i++) System.out.println(V[i]);

Grafic, interschimbarea de mai sus se poate prezenta astfel:


 după crearea şi iniţializarea celor doi vectori:

V 1 2 3 4
0 1 2 3

V1 9 9 9
0 1 2
Figura 6.7. Pasul întâi

 după efectuarea instrucţiunii Man=V1;, vom avea:

V 1 2 3 4
0 1 2 3

V1 9 9 9
0 1 2

Man

Figura 6.8. Pasul al doilea


Capitolul 6. Iniţiere în utilizarea limbajului Java 243

 după efectuarea instrucţiunii V1=V; , vom avea:

V 1 2 3 4
0 1 2 3

V1 9 9 9
0 1 2

Man

Figura 6.9. Pasul al treilea

 după efectuarea instrucţiunii V=Man; , vom avea:

V 1 2 3 4
0 1 2 3

V1 9 9 9
0 1 2
Figura 6.10. Ultimul pas

⇒ O altă utilizare de excepţie a acestui mecanism este aceea prin care se


declară un masiv exact cu numărul de componente dorit şi nu un număr de
componente mare, care se presupune că indiferent de intrare, nu poate fi
depăşit (ca în Pascal, C/C++). Aceasta conduce la economie de memorie.
int n;
// se citeste n;
V=new int [n];
⇒ Deşi din punct de vedere teoretic nu se poate explica în acest moment,
numărul de componente ale unui vector (masiv unidimensional) este returnat
de data membru (vom învăţa despre date membru) length, apelată ca mai
jos. În urma executării acestei secvenţe se afişează 10.
int[] vector=new int[10];
System.out.println(vector.length);
⇒ O matrice poate fi privită (şi, de fapt asta şi este) ca un vector de vectori. Fie
declaraţia int Mat[][]=new int [4][5]. Putem spune că avem un
vector cu 4 componente. Fiecare componentă este la rândul ei, un vector cu
5 componente. Atunci, length, aplicată matricei, reţine 4, şi aplicată, de
exemplu, componentei de indice 2 returnează 5. La executarea secvenţei de
mai jos se afişează 4 şi 5.
int Mat[][]=new int [4][5];
System.out.println(Mat.length);
System.out.println(Mat[2].length);
244 Manual de Informatică pentru clasa a XII-a

⇒ În cazul matricelor (sau, în general, masivelor de dimensiune mai mare sau


egală cu 2) există posibilitatea ca liniile să aibă lungime diferită. Cu alte
cuvinte, o componentă a vectorului de vectori (matricea) poate avea un
număr de componente, altă componentă, alt număr de componente. În
secvenţa următoare am declarat o matrice cu 2 linii. Prima linie are 3
componente, a doua linie are două componente. În final, se afişează
conţinutul unui element al matricei.
int Mat[][]=new int [2][];
Mat[0]=new int[3];
Mat[1]=new int[2];
Mat[0][0]=1; Mat[0][1]=2; Mat[1][0]=3;
System.out.println(Mat[0][1]);

 Vă daţi seama câtă economie de memorie se face?

Aplicaţie ! Secvenţa următoare creează, iniţializează şi afişează o


matrice triunghiulară. Alăturat puteţi observa rezultatul rulării. Este
ceva faptul că pentru a reţine o matrice triunghiulară se reţine exact
atât cât este necesar!
int[] vector=new int[10]; Figura 6.11.
int Mat[][]=new int [4][]; Rezultatul rulării
int i, j, k=1;
for (i=0;i<4;i++)
{ Mat[i]=new int[i+1]; // declararea este instructiune
for (j=0;j<=i;j++) Mat[i][j]=k++;
}
for (i=0;i<4;i++)
{ for (j=0;j<Mat[i].length;j++) System.out.print(Mat[i][j]);
System.out.println();
}

6.11. Citirea datelor de la tastatură


Limbajul Java conţine o mulţime de facilităţi, dar pentru începători există o
reală dificultate în a citi date de la tastatură. Ca să le înţelegem cu adevărat, sunt
necesare cunoştinţe avansate de Java. Şi nu putem aştepta până atunci, pentru
că este relativ dificil să prezinţi materia, mai ales la nivel de liceu, fără a putea citi
ceva de la tastatură. Pentru a rezolva această problemă, s-a recurs, ca de altfel şi
în alte cursuri de Java, la prezentarea unei clase prin care să putem realiza citirea
de la tastaură a şirurilor de caractere.
Vom prezenta această clasă referindu-ne doar la utilizarea ei. Ulterior, vom
prezenta modul în care a fost realizată. Clasa pe care o vom folosi se numeşte
cin şi este următoarea:
Capitolul 6. Iniţiere în utilizarea limbajului Java 245

import java.io.*;
public class cin {
static String linie ()
{ String sir = ""; char ch;
try
{ while ((ch = (char)System.in.read()) != 13)
sir = sir+ch;
}
catch (IOException e) {} try { System.in.read(); }
catch (IOException e) {}
return sir;
}
}
Textul de mai sus îl vom introduce în fişierul cin.java. Apoi, îl compilăm cu
javac cin.java. În urma compilării rezultă fişierul cin.class. Acest fişier va fi
utilizat de orice program care foloseşte o metodă din clasa cin. Dacă fişierele
cin.java şi cin.class se vor găsi în folder-ul bin, atunci, fără nici o problemă,
utilizăm aceste metode ca şi cum ar fi ale limbajului Java (practic, orice program
care apelează clasele respective le găseste în bin).
⇒ Metoda linie() are rolul de a citi un şir de caractere introdus de la tastatură.
Rezultatul este de tip referinţă la String, adică referinţă către şirul de
caractere citit. Şirul este citit cacter cu cacter. Atunci când utilizatorul apasă
enter, se generează, de fapt, 2 caractere. Primul dintre ele este depistat de
metodă. Pentru a elimina caracterul rezidual, se mai citeste un caracter.
Exemplul 6.50. Programul următor citeşte şi afişează o linie introdusă de la
tastatură:
class test {
public static void main(String[] args) {
String l=cin.linie();
System.out.println(l);
}
}
⇒ Dacă dorim să citim numai un caracter, vom utiliza metoda charAt(nr),
care returnează caracterul aflat pe poziţia nr a şirului de caractere. Atenţie:
primul caracter al şirului are indicele 0.
Exemplul 6.51. în programul următor se citeşte şi se afişează un caracter.
Observaţi modul de utilizare al metodei charAt().
class test {
public static void main(String[] args) {
String l=cin.linie();
char c=l.charAt(0);
System.out.println(c);
}
}
246 Manual de Informatică pentru clasa a XII-a

⇒ Dacă dorim să citim numere, este sarcina noastră să convertim rezultatul


către tipul dorit. Vom utiliza metode ale unor clase, numite înfăşurătoare,
clase care vor fi prezentate la momentul potrivit.

⇒ Metoda Integer.parseInt(sir) returnează şirul convertit către int.

Exemplul 6.52. Se citesc două numere naturale a şi b şi se afişează suma lor:


class test {
public static void main(String[] args) {
System.out.print("a=");
int a=Integer.parseInt(cin.linie());
System.out.print("b=");
int b=Integer.parseInt(cin.linie());
System.out.println(a+b);
}
}
⇒ Metoda Long.parseLong(sir) returnează şirul convertit către long.
⇒ Metoda Float.parseFloat(sir) returnează şirul convertit către float.

⇒ Metoda Double.parseDouble(sir) returnează şirul convertit către


float.

Observaţie ! Nu trebuie să vă îngrijoraţi că nu aţi înţeles toate noţiunile prezentate.


Pentru moment, luaţi-le ca atare. Toate vor fi studiate în amănunt. Să ne mulţumim
cu faptul că putem citi şi afişa un şir de caractere.

Întrucât cunoaştem deja operatorii şi instrucţiunile şi putem citi date cu


ajutorul clasei cin, de acum putem să scriem mici programe. Toate instrucţiunile
se vor găsi în main().

1. Se citesc două numere reale. Se cere să se afişeze numărul cel mai mare
dintre ele (calculul maximului).
class test {
public static void main(String[] args) {
System.out.print("a=");
double a=Double.parseDouble(cin.linie());
System.out.print("b=");
double b=Double.parseDouble(cin.linie());
if (a>b) System.out.println(a);
else System.out.println(b);
}
}
Capitolul 6. Iniţiere în utilizarea limbajului Java 247

2. Se citeşte n, număr natural mai mare decât 0. Să se calculeze 1+2+...n.


class prima {
public static void main(String[] args) {
System.out.print("n=");
int i,s=0,n=Integer.parseInt(cin.Token());
for (i=1;i<=n;i++) s+=i;
System.out.println("Suma este " +s);
}
}

 Observaţi modul în care se afişează, mai întâi, şirul “n=”, si apoi se


aşteaptă introducerea lui n.

 Prin expresia: "Suma este " +s se converteşte mai întâi tipul int către
String (obiect care reţine un şir de caractere), apoi cele două se
concatenează. În final, se afişează şirul astfel obţinut.

 Aceasta înseamnă că pentru a converti o valoare numerică, a, către şir, se


poate face şirul sumă între şirul vid şi a: “”+a. De reţinut!

3. Se citeşte n şi un vector cu n componente numere reale. Să se afişeze


conţinutul componentelor vectorului sortate crescător. Se va utiliza metoda bulelor.
class test {
public static void main(String[] args) {
System.out.print("n=");
int n=Integer.parseInt(cin.linie()),i;
double man; boolean gasit;
double V[]=new double[n];
for (i=0;i<n;i++)
{ System.out.print("V["+i+"]=");
V[i]=Double.parseDouble(cin.linie());}
do
{ gasit=false;
for (i=0;i<n-1;i++)
if (V[i]>V[i+1])
{ man=V[i]; V[i]=V[i+1]; V[i+1]=man;
gasit=true;}
} while (gasit==true);
for (i=0;i<n;i++) System.out.println(V[i]);
}
}

4. Mai jos puteţi observa o secvenţă simplă prin care se pot inversa liniile i şi j
ale unei matrice cu n linii şi m coloane (i,j<n).
int Man[]; Man=A[i]; A[i]=A[j]; A[j]=Man;
248 Manual de Informatică pentru clasa a XII-a

6.12. Date membru


În Java, există posibiltatea de a declara variabile vizibile la nivel de clasă,
aşa cum se vede în programul de mai jos, unde se citesc conţinuturile numerice a
două astfel de variabile şi se afişează suma lor. Ele sunt, de fapt, variabile globale
la nivel de clasă. Ca să respectăm terminologia consacrată, le vom numi date
membru (ale clasei care conţine main()). Pentru moment, pentru a putea lucra ca
acest mod este obligatoriu ca datele membru să fie precedate de modificatorul
static. Justificările celor prezentate acum vor fi date ulterior.
class test {
static int a,b;
public static void main(String[] args) {
a=Integer.parseInt(cin.linie());
b=Integer.parseInt(cin.linie());
System.out.println(a+b);}
}
Orice dată membru (variabilă) a clasei este iniţializată automat, la pornirea
programului. Astfel, datele numerice sunt iniţializate cu 0, datele de tip boolean cu
false, datele de tip caracter cu caracterul de cod 0, datele de tip referinţă cu
null (nu conţin nici o adresă).

6.13. Metode
În esenţă, o metodă este alcătuită din:
• Antet - acesta conţine mai multe informaţii importante necesare
compilatorului, numele metodei, lista parametrilor formali, tipul metodei
şi, eventual, modificatori.
• Corpul metodei - acesta cuprinde instrucţiunile metodei.
Exemplul 6.53. În Fig. 6.12, puteţi observa metoda suma() ce are rolul de a
calcula suma a două numere naturale. În schema ataşată, puteţi identifica
elementele constitutive ale ei:
 Numele metodei – se utilizează pentru a o identifica atunci când metoda
este apelată.
 Lista parametrilor formali – parametrii formali sunt valorile pe care
metoda le primeşte la apel. În exemplu, lista este formată din doi
parametri formali, x şi y, ambii de tipul int.
 Tipul metodei – sau altfel spus, precizează natura rezultatului. În
exemplu, metoda returnează o valoare întreagă (de tip int), dar pot fi
metode de alt tip, cum ar fi float double, etc. Există şi metode care
nu returnează nimic, caz în care tipul metodei este void.
Capitolul 6. Iniţiere în utilizarea limbajului Java 249

Modificator Tipul Numele Lista


metodei metodei parametrilor
formali

static int suma(int x, int y)


{ return x+y;
Corpul }
metodei
Figura 6.12. Exemplu de metodă
 Corpul metodei – este sub forma unei instrucţiuni compuse. În
exemplu, acesta conţine o singură instrucţiune, return, prin care se
calculează şi se returnează suma parametrilor formali.
 Modificator – static.
Mai jos, puteţi observa modul în care se apelează metoda suma():
public class test {
static int suma(int x, int y) {return x+y;}
public static void main(String[] args) {
System.out.println(suma(2,3));
int x=2, y=5;
System.out.println(suma(x,y)); System.out.println(suma(3,y));}
}

⇒ Metodele care sunt de orice alt tip în afara tipului void, trebuie să returneze
o valoare din tipul respectiv. Returnarea valorii se face prin utilizarea
instrucţiunii return. În exemplu, metoda suma() prin return x+y;
returnează suma celor doi parametrii primiţi.
Mai jos puteţi observa modul în care se apelează o metodă de tip void:
public class test {
static void met()
{ System.out.println("Eu sunt o metoda de tip void"); }
public static void main(String[] args) { met(); }
}
⇒ Parametrii care figurază în apelul unei metode se numesc parametri efectivi.
De exemplu, în apelul suma(2,3), parametrii efectivi sunt valorile 2 şi 3. În
apelul suma(x,y) parametrii efectivi sunt conţinuturile variabilelor x şi y.
⇒ Metodele se pot apela una pe alta, indiferent de poziţia pe care o ocupă
definiţia lor în cadrul clasei.
Exemplul 6.54. În exemplul de mai jos, metoda met1() apelează metoda met(),
deşi aceasta din urmă este definită, în cadrul clasei, după ea.
class test {
static void met1()
{ System.out.println("Met1"); met(); }
250 Manual de Informatică pentru clasa a XII-a

static void met() {System.out.println("Met");}


public static void main(String[] args)
{met1();}
}

⇒ În Java, parametrii se transmit numai prin valoare. Aceasta înseamnă că


parametrul efectiv, chiar dacă este variabilă, râmâne nemodificat.
Exemplul 6.55. Priviţi exemplul următor:
public class test {
static void exemplu(double x)
{ x=3.7; }
public static void main(String[] args) {
double x=5; exemplu(x); System.out.println(x);
}
}
În main() avem o variabilă x, de tip double, iniţializată cu 5. Apelăm
metoda de tip void exemplu(). În metodă, lui x i se atribuie altă valoare (3.7).
După executarea metodei, se revine în main() şi se afişează x. Valoarea afişată
este cea iniţială, 5. Conţinutul variabilei x din main() a rămas nemodificat.

⇒ Am arătat faptul că numele unui masiv este o referinţă către masiv ce se


găseşte în memorie. În acest caz, transmiterea unei referinţe către un masiv
ca parametru al unei metode are ca efect posibilitatea modificării
conţinuturilor componentelor masivului.

Observaţie ! Întrucât masivele conţin şi data membru length, dacă o metodă


primeşte ca parametru o referinţă către masiv, atunci nu mai este necesar ca, în alte
limbaje de programare, să transmitem şi numărul de componente ale masivului.

Exemplul 6.56. Metoda exemplu() calculează suma numerelor reţinute de un


vector şi face ca fiecare componentă a vectorului să reţină valoarea 1. În
programul principal se iniţializează vectorul, apoi se probează efectul metodei.
public class test {
static int exemplu(int[] t )
{ int s=0,i;
for (i=0;i<t.length;i++) s+=t[i];
for (i=0;i<t.length;i++) t[i]=1;
return s;
}
public static void main(String[] args) {
int[] v=new int [5]; int i;
for (i=0;i<5;i++) v[i]=Integer.parseInt(cin.linie());
System.out.println(exemplu(v));
for (i=0;i<v.length;i++) System.out.print(v[i]+" ");
}
}
Capitolul 6. Iniţiere în utilizarea limbajului Java 251

6.14. Exemple de utilizare a metodelor

1. Se citesc două numere întregi m şi n. Se cere să se tipărească cel mai mare


divizor comun şi cel mai mic multiplu comun al lor.
Rezolvare. Presupunem cunoscut algoritmul care determină cel mai mare divizor
comun pentru două numere. Cel mai mic multiplu comun al două numere se poate
determina împărţind produsul lor la cel mai mare divizor comun al lor. Prin urmare,
scriem o metodă cmmdc cu doi parametri formali m şi n, care întoarce o valoare
întreagă - cel mai mare divizor comun al lor.
public class test {
static int cmmdc(int m, int n)
{ while (m!=n)
if (m>n) m-=n;
else n-=m;
return m; }
public static void main(String[] args) {
int m=Integer.parseInt(cin.linie());
int n=Integer.parseInt(cin.linie());
int cm=cmmdc(m,n);
System.out.println(cm);}
}

2. Superpalindrom. Un număr natural este palindrom dacă citit de la stânga la


dreapta şi de la dreapta la stânga rămâne nemodificat. De exemplu, numărul
12321 este palindrom. Un număr natural este superpalindrom dacă este palindrom
atât el cât şi pătratul său. Scrieţi un program care listează toate numerele cu
această proprietate aflate între doi intregi m şi n.
Rezolvare. Modul în care testăm dacă un număr este palindrom este acum lămurit.
Mai mult, avem şi metoda. Nu trebuie decât să o folosim:
public class test {
static boolean palin(int i)
{ int isalv=i,iinv=0;
while (i!=0)
{ iinv=iinv*10+i%10; i=i/10; }
return isalv==iinv;
}
public static void main(String[] args) {
int m=Integer.parseInt(cin.linie());
int n=Integer.parseInt(cin.linie());
for(int i=m;i<n;i++)
if (palin(i))
if (palin(i*i)) System.out.println(i+" "+i*i);
}
}

⇒ În Java metodele pot fi recursive, deci o metodă se poate autoapela.


252 Manual de Informatică pentru clasa a XII-a

3. Să se calculeze recursiv n!. Pentru a scrie o metodă recursivă care efectuează


acelaşi calcul, vom porni de la o definiţie recursivă a lui n!. Aceasta este:
public class test {
static int fact(int n)
{ if (n==0) return 1;
else return n*fact(n-1); }
public static void main(String[] args) {
System.out.println(fact(3)); }
}

6.15. Supraîncărcarea metodelor


În Java, metodele pot fi supraîncărcate. Aceasta înseamnă că putem avea
două sau mai multe metode cu acelaşi nume, dar care diferă prin tipul şi/sau
numărul parametrilor.

Exemplul 6.57. Priviţi programul de mai jos, care conţine două metode cu acelaşi
nume, cu acelaşi număr de parametri (1), dar de tip diferit (int, respectiv float):
public class test {
static void eu_sunt(int n)
{ System.out.println("Parametru de tip int "+ n); }
static void eu_sunt(double n)
{ System.out.println("Parametru de tip double "+n ); }
public static void main(String[] args) {
eu_sunt(3);
eu_sunt(-2.7); }
}

Faptul că metodele pot fi supraîncărcate are consecinţe uriaşe în


programare. Dacă în cazul programării clasice (neorientate pe obiecte) se poate
programa şi în absenţa acestei facilităţi, în cazul programării orientate pe obiecte,
facilitatea devine esenţială, aşa cum va rezulta din capitolele următoare.

 Un exemplu este chiar metoda println(), atât de utilizată până în acest


moment. Ea afişează orice i-am transmite ca parametru: o valoare de tip
int, o valoare de tip float, un caracter sau un şir de caractere. De fapt,
există mai multe metode println() care diferă doar prin tipul parametrului.

Sugestie ! Pentru a vă obişnui cu programarea în Java, puteţi rezolva orice


problemă din manualele pentru clasele a X-a şi a XI-a care nu necesită utilizarea
fişierelor.
CAPITOLUL
Programare orientată pe obiecte

În acest capitol vom studia în detaliu programarea orientată


pe obiecte, utilizând limbajul de programare Java. Mai jos sunt
prezentate principalele noţiuni pe care le veţi învăţa:

 Care sunt principiile programării orientate pe obiecte ?


 Ce este un constructor ?
 Date membru statice şi metode statice
 Cuvântul cheie This
 Referinţe către obiecte
 Masive de obiecte
 Aplicaţii. Lucrul cu numere raţionale
 Studiul unor clase din limbajul Java
 Extinderea claselor (moştenirea)
 Ce este polimorfismul ?
 Clase abstracte
 Interfeţe
 Specificatori de acces (modificatori de acces)
 Excepţii (tratarea erorilor)

Cuvinte cheie: încapsulare, moştenire, polimorfism, constructor,


static, nestatic, legare, this, referinţă, masiv, math, string, clasă
înfăşurătoare, abstract, interfaţă, specificator de acces, excepţie
254 Manual de Informatică pentru clasa a XII-a

7.1. Principiile programării orientate pe obiecte

Atunci când ne referim la programarea orientată pe obiecte, se mai pot folosi


şi denumirile: programare obiectuală, programare orientată spre obiect sau pe
scurt, ”OOP - Object Oriented Programming”.

În linii mari, se poate spune că OOP reuneşte trei principii fundamentale:


încapsulare, moştenire şi polimorfism.
1. Prin încapsulare înţelegem mecanismul prin care datele (variabilele) şi funcţiile
(numite în acest caz şi metode) sunt plasate împreună, într-o unică structură,
numită clasă. Clasa generalizează noţiunea de tip de dată. Fiind dat un tip de
dată, putem avea variabile care sunt de acel tip, adică acele variabile pot reţine
numai date care respectă cerinţele tipului.

Exemplul 7.1. Dacă trebuie să reţinem un număr real, putem alege tipul double şi
să definim o variabilă de acest tip.

Fiind dată o clasă, putem obţine obiecte rezultate prin instanţierea acelei
clase. Pe lângă datele proprii, un obiect conţine şi metode, adică funcţii care permit
lucrul cu datele reţinute de obiectul respectiv, dar şi cu date din afara obiectului.

Exemplul 7.2. La matematică v-aţi întâlnit cu numere complexe! Ele sunt de


forma: z=x+iy, unde x,y∈ℜ. Prin urmare, pentru fiecare număr complex ar trebui
să reţinem două valori reale, pentru x şi pentru y. Decidem că în acest caz, pentru
a le reţine, avem nevoie de două variabile de tip double.
Priviţi programul de mai jos care conţine două clase: Complex şi test:
class Complex {
// date membru
double x,y;
// metoda
void afis()
{ System.out.println(x+" "+y); }
}
public class test {
public static void main(String[] args) {
// declar un numar complex
Complex z1;
z1= new Complex (); // Complex z1=new Complex();
// Datelor membru li se atribuie valori
z1.x=3;
z1.y=-4.7;
// Afisez datele membru
z1.afis();
}
}
Capitolul 7. Programare orientată pe obiecte 255

Să analizăm programul:

clasa Complex:

1. Clasa conţine două date membru, x şi y, ambele de tip double.


2. Clasa conţine o metodă care are rolul de a afişa într-un mod convenabil
datele membru ale clasei.
clasa test - metoda main():
1. Complex z1;- variabila z1 este de tip Complex. Prin urmare, ea poate reţine
o referinţă (adresă) către un obiect de tip Complex.
2. z1=new Complex(); - se creează un obiect de tip Complex şi referinţa către
el este reţinută de z1.
3. z1.x=3; z1.y=-4.7; - datelor membru x şi y ale obiectului a cărui
referinţă este reţinută de z1 li se atribuie respectiv, valorile 3 şi 4.7.
4. z1.afis(); - se afişează numărul complex reţinut de obiectul referit de z1.

Foarte important !

A) La baza programării pe obiecte stă noţiunea de clasă. Clasa încorporează atât


date membru, cât şi metode. A defini o clasă înseamnă a crea un tip (în sensul
extins). Un obiect rezultă ca instanţiere a unei clase. Obiectul va avea ca tip
numele clasei respective. Pentru a putea accesa datele membru şi metodele clasei
respective se utilizează variabile de tip referinţă către obiectele clasei respective.
B) Odată definită clasa, putem crea obiecte de tipul clasei respective. Într-o formă
simplificată (mai precis, în absenţa unui constructor), crearea unui obiect de tipul
unei clase se face prin construcţia de mai jos, unde v este o variabilă referinţă
către obiectele clasei respective.
Nume_clasa v=new Nume_Clasa()
C) Un constructor al unei clase este o metodă specială a clasei respective care
are rolul de a aloca în memorie spaţiul necesar obiectului dar şi de a iniţializa
datele membru ale acestuia. Orice clasă are un constructor implicit (adică o
metodă pe care nu a scris-o cel care a creat clasa).
D) Operatorul new are dublu rol:
- apelează constructorul clasei respective;
- returnează referinţa (adresa) la care a fost creat obiectul respectiv.

Exemplul 7.3. Complex z=new Complex(); - z reţine o referinţă către


obiectul creat prin new:

z
Figura 7.1. x y
256 Manual de Informatică pentru clasa a XII-a

E) Accesul la variabilele interne ale obiectului se realizează prin numele


obiectului, urmat de operatorul ‘.’ şi numele variabilei.

Exemplul 7.4. În exemplu, Z va reţine numărul x+2i, iar aceste valori vor fi afişate:
z1.x=1;
z1.y=2;
System.out.println(z1.x);
System.out.println(z2.y);

F) O clasă poate conţine una sau mai multe metode. Apelul unei metode de
acest tip se face prin numele variabilei care reţine referinţa către obiect, urmat de
‘.’ şi de numele metodei.
Exemplul 7.5. z1.afis().
G) Datele membru ale unei clase sunt iniţializate implicit cu valoarea 0, dacă sunt
de un tip numeric, sau cu caracterul de cod 0, dacă sunt de tip char, sau cu null
dacă sunt de tip referinţă.
2. Prin moştenire se înţelege acea proprietate a claselor prin care o clasă poate
prelua datele şi metodele unei (unor) clase anterior realizate. În Java, acest
mecanism mai este cunoscut sub numele de "extinderea claselor". Evident, clasei
nou construite i se pot adăuga noi date şi metode! Prin acest procedeu, se preia
soft deja implementat şi acesta se dezvoltă. Avantajul uriaş al acestui mecanism
este că persoana care preia un anumit soft trebuie să cunoască doar documentaţia
de utilizare a acestuia. Extinderea claselor face obiectul unui paragraf separat.
3. Polimorfismul este legat de moştenire. În linii mari, prin polimorfism înţelegem
posibilitatea ca atât clasa care este moştenită, cât şi moştenitoarea, să poată
utiliza metode cu acelaşi nume, dar diferite. Fie mai multe clase C0, C1, ..., Cn, unde
C1 moşteneşte pe C0, C2 pe C1, ..., Cn pe Cn-1. Toate aceste clase redefinesc o
metodă: f. Există posibilitatea ca, în timpul executării programului, să se ruleze
o metodă f sau alta, tot f, în funcţie de tipul datelor care intervin. Procedeul este
cu mult mai complex şi va face obiectul unui paragraf separat.

7.2. Constructori
Aşa cum am arătat, orice clasă are un constructor implicit. Rolul lui este de a
aloca spaţiu în memorie pentru obiect. Constructorul este apelat de operatorul
new. Acesta din urmă are şi rolul de a returna referinţa către obiect, referinţă care
este memorată de o variabilă de tip referinţă către obiect.

Exemplul 7.6. Unei clase i se pot crea proprii constructori, aşa cum rezultă din
exemplul următor, unde clasei prezentate în paragraful precedent i s-au adăugat
doi constructori:
Capitolul 7. Programare orientată pe obiecte 257

class Complex {
// date membru
double x,y;
// Constructor 1
Complex (double x1)
{ x=x1;
}
// Constructor 2
Complex (double x1, double y1)
{ x=x1;
y=y1;
}
// metoda
void afis()
{ System.out.println(x+" "+y);
}
}
public class test {
public static void main(String[] args) {
Complex z1 = new Complex (2,3), z2 = new Complex (1);
z1.afis();
z2.afis();
}
}

Primul constructor are un singur parametru şi se foloseşte pentru declaraţii


de numere complexe care au partea imaginară 0. Al doilea constructor se
utilizează pentru a declara numere complexe cu parte reală şi parte imaginară. În
ambele cazuri nu mai este nevoie ca datele membru să fie iniţializate.

De reţinut !

A) Un constructor nu are tip.

B) Un constructor are întotdeauna numele clasei căreia îi aparţine.

C) Dacă unei clase i se ataşează un constructor, altul decât cel implicit, atunci nu
se mai poate instanţia un obiect prin utilizarea constructorului implicit. De exemplu,
pentru clasa definită în acest paragraf o instrucţiune de genul Complex z=new
Complex() dă eroare de sintaxă.

D) Unei clase i se pot ataşa mai mulţi constructori, după cum aţi văzut şi în
exemplu. Ei trebuie să difere prin numărul parametrilor şi /sau tipul parametrilor, cu
alte cuvinte, ca şi metodele, aceştia sunt supraîncărcaţi.
258 Manual de Informatică pentru clasa a XII-a

7.3. Date membru statice şi metode statice

Atât datele membru cât şi metodele unei clase pot fi statice. Aceasta
înseamnă că datele şi metodele declarate statice pot fi apelate, aşa cum suntem
deja obişnuiţi, pornind de la un obiect al clasei respective, dar şi pornind de la
numele clasei, aşa cum observaţi în exemplul următor.

Exemplul 7.7. Clasa Matematica conţine o dată membru iniţializată (Pi). De


asemenea, ea mai conţine două metode: Patrat() şi Cub() prin care se
calculează x2 şi x3. Se calculează şi afişează aria unui cerc în două feluri:
 apelând data membru şi metoda pornind de la numele clasei (Matematica);
 apelând data membru şi metoda pornind de la numele unui obiect al clasei
Matematica.
class Matematica {
static double Pi=3.1415;
static double Patrat (double x)
{ return x*x; }
static double Cub (double x)
{ return x*x*x; }
}
public class Clasa1 {
public static void main(String[] args) {
int Raza=3;
double Aria=Matematica.Pi*Matematica.Patrat(Raza);
System.out.println(Aria);
//altfel
Matematica ob=new Matematica();
Aria=ob.Pi*ob.Patrat(Raza);
System.out.println(Aria);
}
}

Foarte important !
A) Datele membru statice şi metodele statice nu sunt memorate de fiecare obiect
al clasei respective. Ele sunt memorate o singură dată, în cadrul clasei respective.
B) Sunt clase care au date membru şi/sau metode statice şi nestatice.

Observaţie ! O clasă indispensabilă, este clasa Math, care este prezentată în


această carte. Ea conţine o mulţime de metode “matematice” care se utilizează
mult în orice limbaj de programare. Clasa Matematica, din exemplu, este
construită pe aceleaşi principii ca şi clasa Math.
Capitolul 7. Programare orientată pe obiecte 259

7.4. Cuvântul cheie “this”


În interiorul claselor se poate utiliza cuvântul cheie this. Semnificaţia sa
este: referinţă către obiectul curent. Iată una dintre aplicaţiile sale:

Dacă o metodă (sau un constructor) are o variabilă cu un anumit nume, de


exemplu x, şi dacă, clasa are o dată membru cu acelaşi nume, pentru exemplul
nostru tot x, atunci pentru a nu se crea confuzie, data membru va fi adresată prin
this.x, iar variabila din metodă (sau constructor) prin x.

Exemplul 7.8. Pentru clasa Complex cei doi constructori ar putea fi scrişi şi aşa:
Complex (double x)
{ this.x=x; }
Complex (double x, double y)
{ this.x=x; this.y=y;}

7.5. Referinţe către obiecte


Metodele pot avea parametri de tip referinţă la obiecte şi pot returna referinţe
către obiecte. Evident, referinţele sunt transmise prin valoare. Dar, pornind de la
ele, se poate accesa obiectul ca şi când ar fi transmis prin referinţă.
Exemplul 7.9. Adăugăm clasei Complex metoda Complex adun(Complex
z);. Metoda returnează o referinţă către un obiect de tip Complex care reţine
numărul complex rezultat ca sumă între numărul reţinut de obiectul curent şi
numărul complex transmis ca parametru:

class Complex {
double x,y;

Complex (double x)
{ this.x=x; }

Complex (double x, double y)


{ this.x=x; this.y=y; }

void afis()
{ System.out.println(x+" "+y); }

Complex adun(Complex z)
{ return new Complex (x+z.x,y+z.y); }
}
260 Manual de Informatică pentru clasa a XII-a

public class test {


public static void main(String[] args) {
Complex z1 = new Complex (2,3);
Complex z2 =new Complex(3,4);
Complex z=z1.adun(z2);
z.afis();
}
}
Programul afişează suma numerelor complexe reţinute z1 şi z2, adică
numărul complex z=5+7i, afişat ca: 5 7. Observaţi faptul că variabila care reţine
referinţa către obiectul sumă a fost iniţializată cu ajutorul metodei adun() a
obiectului z1.

Observaţie ! Clasele pot conţine variabile de tip referinţă la propriile obiecte (sau
la obiectele altei clase).
Exemplul 7.10. Listă liniară simplu înlănţuită. Pornind de la această observaţie,
construim o listă liniară simplu înlănţuită. Priviţi programul următor care creează şi
afişează o listă liniară simplu înlănţuită:
class Nod {
int info;
Nod adr_urm;
}

public class Lista {


static Nod v=null; // nu este obligatorie iniţializarea
static void adaug(int nr)
{ Nod c=new Nod();
c.info=nr;
c.adr_urm=v;
v=c;
}

static void afis()


{ Nod c=v;
while (c!=null)
{ System.out.println(c.info);
c=c.adr_urm; }
}
public static void main(String[] args) {
for (int i=1;i<=9;i++) adaug(i);
afis();
}
}

Un nod reţine o informaţie oarecare, s-o numim info şi să presupunem că


este de tip int şi o referinţă către nodul următor (adr_urm). Evident, referinţa este
către obiecte ale aceleiaşi clase. Clasa respectivă am numit-o Nod.
Capitolul 7. Programare orientată pe obiecte 261

Clasa care construieşte lista (Lista) conţine o dată membru de tip static
de tip referinţă către un obiect al clasei Nod. De asemenea, clasa conţine şi două
metode adaug() şi afis().

 Metoda adaug() are rolul de a adăuga un nod listei liniare. Ea primeşte ca


argument numărul care trebuie reţinut de info. Observaţi cum s-a procedat:
s-a creat un nou obiect al clasei Nod, iar referinţa către el este reţinută de c.
Data membru a acestui obiect, info, este iniţializată cu valoarea primită ca
parametru de metodă, iar adr_urm cu referinţa către nodul anterior, este
reţinută de v. În final, v reţine referinţa către ultimul nod creat. În acest fel,
lista va reţine nodurile în ordinea inversă creării lor. Am preferat acest
algoritm pentru simplitatea lui.
 Metoda afis() listează valorile reţinute de data membru info a fiecărui nod.

O problemă de terminologie. Am văzut că metodele pot întoarce referinţe către


obiecte. De asemenea, parametrii metodelor pot fi de tip referinţă către obiecte.
Prin abuz de limbaj, pentru a nu complica exprimarea, vom spune uneori, că
metodele întorc obiecte, vom vorbi despre obiectul (obiectele) primit ca parametru
de o metodă. Însă, acestea trebuie înţelese ca referinţe către obiecte.

Garbage Collector. Pe parcursul rulării unui program se pot aloca multe obiecte,
iar altele devin inutile, adică nu mai există referinţă către ele. Dacă numărul obiectelor
alocate este foarte mare, este posibil ca programul să nu mai dispună de suficientă
memorie şi, prin urmare, executarea sa să nu mai poată continua. Pentru a rezolva
această problemă, programele java conţin o secvenţă (fir de executare), numită
Garbage Collector, care intervine automat (fără ca programul nostru să conţină
instrucţiuni scrise special în acest scop) şi eliberează memoria ocupată de obiectele
nereferite. Aceasta poate duce uneori, la o încetinire a executării programelor.
Momentul în care intervine Garbage Collector nu este stabilit de programator. Cu
alte cuvinte, în Java nu vom folosi destructori, existenţi în alte limbaje de
programare, cum ar fi C++.

7.6. Masive de obiecte


Întrebarea este: se pot crea masive care reţin obiecte? De exemplu, putem
să creăm un vector care reţine obiecte de tipul Complex? Răspunsul este
afirmativ! Elementele unui masiv pot reţine referinţe către obiecte.
Exemplul 7.11. În programul următor se creează şi se afişează un
vector cu componente de tip Complex (vezi figura alăturată):

Figura 7.2. Rezultat


262 Manual de Informatică pentru clasa a XII-a

class Complex {
double x,y;
Complex (double x)
{ this.x=x; }
Complex (double x, double y)
{ this.x=x; this.y=y; }
void afis()
{ System.out.println(x+" "+y);}
Complex adun(Complex z)
{ return new Complex (x+z.x,y+z.y); }
}
public class test {
public static void main(String[] args) {
Complex[] V=new Complex[3];
for (int i=0;i<3;i++) V[i]=new Complex(i+1,i+2);
for (int i=0;i<3;i++) V[i].afis();
}
}
Pentru a înţelege modul în care a fost construit vectorul de obiecte rezultate
ca instanţe ale clasei Complex, analizaţi figura următoare:

V[0] V[1] V[2]

1 2 afis() 2 3 afis() 3 4 afis()


x y x y x y

Figura 7.3. Construcţia vectorului de obiecte

Analizaţi şi exemplele care sunt prezentate în continuare!

Exemplul 7.12. În secvenţa următoare, V1 reţine o referinţă către un vector cu 10


componente care pot reţine referinţe către obiecte ale clasei Complex. Se
instanţiază un obiect al clasei Complex şi referinţa sa este atribuită lui V1[2].
Ultimele trei instrucţiuni au rolul de a proba cele prezentate:
Complex[] V1 =new Complex[10];
V1[2]=new Complex(10,11);
V1[2].afis();

Exemplul 7.13. În secvenţa următoare, V1 reţine o referinţă către o matrice cu 8


linii şi 5 coloane. Fiecare componentă a matricei poate reţine o referinţă către un
obiect al clasei Complex. Se instanţiază un obiect al clasei Complex şi referinţa
sa este atribuită lui V1[2][3].
Capitolul 7. Programare orientată pe obiecte 263

Complex[][] V1 =new Complex[8][5];


V1[2][3]=new Complex(10,11);
V1[2][3].afis();

Exemplul 7.14. V1 reţine o referinţă către o matrice cu 5 linii şi un număr


neprecizat de coloane. Un element al matricei va reţine o referinţă către un obiect
al clasei Complex. Linia de indice 3, va avea 6 elemente. Elementul aflat în linia
de indice 3 şi coloana de indice 4 va reţine o referinţă către un obiect al clasei
Complex. Apoi, se probează...
Complex[][] V1=new Complex[5][];
V1[3]=new Complex[6];
V1[3][4]=new Complex(100,200);
V1[3][4].afis();

7.7. Aplicaţii ale noţiunilor prezentate. Lucrul cu


numere raţionale
Este momentul să învăţăm să creăm clase şi apoi să le utilizăm. Înainte de a
prezenta aplicaţiile precizăm că, dacă lucrăm în folder-ul bin, aşa cum am lucrat
până acum, putem compila o clasă oarecare fără ca ea să conţină metoda main().
Fişierul obţinut (are extensia .class) se va găsi în bin (dacă cel cu extensia .java
este tot acolo). Orice altă clasă care conţine main() din bin, poate folosi clasa
compilată, fără a o mai declara într-un fel. De altfel, această problemă va fi tratată pe
larg în acest capitol.

Aplicaţia 7.1. Să se creeze o clasă cu ajutorul căreia să se poată lucra uşor cu


numere raţionale. Un număr raţional q este de forma m/n cu m şi n numere întregi şi n
diferit de 0.
• Clasa va avea două date membru, m şi n, ambele tip int.
• Constructorul clasei este Rational(int m,int n). Obiectul este creat numai
dacă n≠0. Datorită faptului că un număr raţional poate fi reţinut în mai multe feluri
(de exemplu, 2/3=4/6=8/12) se va reţine numărul simplificat (pentru exemplul
dat, m=2 şi n=3, chiar dacă introducem 8 şi 12). Pentru a putea realiza
simplificarea fracţiei, m şi n se împart la cel mai mare divizor comun al lor.
• Clasa va dispune de o metodă static int cmmdc(int m, int n),
apelată de constructor, prin care se calculează cel mai mare divizor comun al
valorilor reţinute de datele membru m şi n.
• Metoda Rational add(Rational r) creează un obiect al clasei
Rational care este rezultatul adunării dintre obiectul curent şi obiectul a cărui
referinţă a fost primită ca parametru şi returnează referinţa către el. Faptul că a
fost apelat constructorul cu datele membru ale obiectului sumă are ca efect
faptul că obiectul care reţine suma este deja simplificat (m şi n au fost împărţite
la cmmdc al lor).
264 Manual de Informatică pentru clasa a XII-a

• Metoda Rational sub(Rational r) creează un obiect al clasei


Rational care este rezultatul scăderii dintre obiectul curent şi obiectul a
cărui referinţă a fost primită ca parametru şi returnează referinţa către el.
• Metoda Rational mul(Rational r) creează un obiect al clasei
Rational care este rezultatul înmulţirii dintre obiectul curent şi obiectul a
cărui referinţă a fost primită ca parametru şi returnează referinţa către el.
• Metoda Rational div(Rational r) creează un obiect al clasei
Rational care este rezultatul împărţirii dintre obiectul curent şi obiectul a
cărui referinţă a fost primită ca parametru şi returnează referinţa către el.
• Metoda boolean maiMare (Ratioanal r) compară obiectul curent cu
obiectul a cărui referinţă a fost primită ca parametru şi returnează true
dacă obiectul curent este strict mai mare decât cel a cărui referinţă a fost
transmisă ca parametru şi false, în caz contrar.
• Metoda boolean maiMic (Ratioanal r) compară obiectul curent cu
obiectul a cărui referinţă a fost primită ca parametru şi returnează true
dacă obiectul curent este strict mai mic decât cel a cărui referinţă a fost
transmisă ca parametru şi false, în caz contrar.
• Metoda boolean egal (Ratioanal r) compară obiectul curent cu
obiectul a cărui referinţă a fost primită ca parametru şi returnează true
dacă obiectul curent este egal cu cel a cărui referinţă a fost transmisă ca
parametru şi false în caz contrar.

Mai jos puteţi observa modul în care arată clasa Rational:


class Rational {
int m,n;
static int cmmdc(int m, int n)
{ if (n!=0) return cmmdc(n, m%n);
else return m; }
Rational (int m, int n)
{ if (n!=0)
{ int d=cmmdc(m,n);
this.m=m/d; this.n=n/d; }
else System.out.println("Numitorul este nul"); }
Rational add(Rational r)
{ return new Rational (m*r.n+r.m*n, n*r.n); }
Rational sub(Rational r)
{ return new Rational (m*r.n-r.m*n, n*r.n); }
Rational mul(Rational r)
{ return new Rational (m*r.m,n*r.n); }
Rational div(Rational r)
{ if (r.m!=0) return new Rational (m*r.n,n*r.m);
else return new Rational (0,1); }
Capitolul 7. Programare orientată pe obiecte 265

boolean maiMare(Rational r)
{ return (double) m/n > (double)r.m/r.n; }
boolean maiMic(Rational r)
{ return (double) m/n < (double)r.m/r.n; }
boolean egal(Rational r)
{ return (double) m/n == (double)r.m/r.n; }
}

În continuare, ne propunem să rezolvăm câteva aplicaţii în care intervin


numere raţionale.

Aplicaţia 7.2. Se citesc două numere raţionale q1 şi q2 (≠0). Se cere să se afişeze


q1+q2, q1-q2, q1*q2, q1/q2. Rezultatele vor fi tot două numere raţionale.

Rezolvare. Variabila q3 este de tip referinţă către un obiect al clasei Rational.


După fiecare operaţie, ea va reţine referinţa către obiectul rezultat în urma operaţiei.
class I {
public static void main(String[] args) {
int m=Integer.parseInt(cin.Token());
int n=Integer.parseInt(cin.Token());
Rational q1=new Rational (m,n);
m=Integer.parseInt(cin.Token());
n=Integer.parseInt(cin.Token());
Rational q2=new Rational (m,n);
Rational q3=q1.add(q2);
System.out.println("Suma="+q3.m+"/"+q3.n );
q3=q1.sub(q2);
System.out.println("Diferenta="+q3.m+"/"+q3.n );
q3=q1.mul(q2);
System.out.println("Produsul="+q3.m+"/"+q3.n );
q3=q1.div(q2);
System.out.println("Catul="+q3.m+"/"+q3.n );
}
}

Aplicaţia 7.3. Se citesc k numere raţionale. Se cere să se afişeze suma lor sub
formă de număr raţional.

Rezolvare. Obiectul s va reţine iniţial o referinţă către un număr raţional nul (m=0,
n=1). Se citesc pe rând cele k numere raţionale. Pentru fiecare număr raţional citit, se
construieşte obiectul suma între s şi obiectul care reţine numărul raţional, iar referinţa
către el este atribuită lui s. În final, se afişează datele membru ale obiectului s.
class I {
public static void main(String[] args) {
System.out.print("k=");
int k=Integer.parseInt(cin.Token());
Rational s=new Rational(0,1);
266 Manual de Informatică pentru clasa a XII-a

for (int i=0;i<k;i++)


{ System.out.print("m=");
int m=Integer.parseInt(cin.Token());
System.out.print("n=");
int n=Integer.parseInt(cin.Token());
Rational q=new Rational (m,n);
s=s.add(q);
}
System.out.println("Suma="+s.m+"/"+s.n );
}
}

Aplicaţia 7.4. Se citeşte un vector cu k componente numere raţionale (obiecte


ale clasei Rational). Se cere să se afişeze vectorul sortat crescător.

Rezolvare. După citirea vectorului vom utiliza metoda de sortare prin


interschimbare. Pentru comparare se utilizează metoda maiMare().
class I {
public static void main(String[] args) {
System.out.print("k=");
int k=Integer.parseInt(cin.Token());
Rational [] V=new Rational [k];
for (int i=0;i<k;i++)
{ System.out.print("V["+i+"].m=");
int m=Integer.parseInt(cin.Token());
System.out.print("V["+i+"].n=");
int n=Integer.parseInt(cin.Token());
V[i]=new Rational(m,n);
}
boolean gasit;
Rational man;
do
{ gasit=false;
for (int i=0;i<k-1;i++ )
if (V[i].maiMare(V[i+1]))
{ man=V[i];
V[i]=V[i+1];
V[i+1]=man;
gasit=true;
}
} while (gasit);
for (int i=0;i<k;i++)
System.out.println("V["+i+"].m=" + V[i].m +
" V["+i+"].n="+V[i].n);
}
}
Capitolul 7. Programare orientată pe obiecte 267

7.8. Studiul unor clase din limbajul Java

Până în prezent am învăţat să construim şi să utilizăm clasele. Desigur, a


fost doar un început, întrucât studiul claselor va continua şi în capitolul următor.
Totuşi, este foarte important să cunoaştem şi să folosim clasele mai importante cu
care limbajul Java este înzestrat. Pachetul java.lang conţine mai multe clase
care alcătuiesc nucleul aplicaţiilor Java. Din acest motiv, pentru utilizarea lor nu
mai este necesară folosirea directivei import.

7.8.1. Clasa Math

Clasa Math face parte din pachetul java.lang şi conţine mai multe
metode statice prin care se calculează valorile mai multor funcţii clasice din
matematică (logaritmice, exponenţiale, trigonometrice, etc):

Metoda Ce calculează ?
long abs(long x) Modul din x (|x|).
double abs(double x) ...
int abs(int x) ...
float abs(float x) ...
int abs(int x) ...
double acos(double x) arccos(x)
double asin(double x) arcsin(x)
Cel mai mic întreg mai mare sau
double ceil(double x)
egal cu x.
Cel mai mare întreg mai mic sau
double floor(double x)
egal cu x ([x], parte întreagă din x).
double cos(double x) cos(x)
double sin(double x) sin(x)
double tan(double x) tg(x)
double pow(double a, double b) ab
double sqrt(double x) Radical din x.
long round(double x) Cel mai apropiat întreg de x.
int round (float x) ...
Număr aleator (întâmplător) din
double random()
intervalul [0,1).
double max(double x, double y) max{x,y}
float max(float x, float y) ...
int max(int x, int y) ...
long max(long x, long y) ...
double min(double x, double y) min{x,y}
float min(float x, float y) ...
long min(long x, long y) ...
268 Manual de Informatică pentru clasa a XII-a

int min(int x, int y) ...


double exp(double x) ex
double log (double x) Logaritm natural din x (ln(x)).
double E Constanta e.
double PI Constanta π.

Tabelul 7.1. Metodele clasei Math

Exemplul 7.15. Analizaţi apelurile de mai jos:


 Math.ceil(2.35) returnează 3;
 Math.ceil(-2.35) returnează -2;
 Math.floor(2.35) returnează 2;
 Math.floor(-2.35) returnează -3;
 Math.round(2.35) returnează 2;
 Math.round(-2.35) returnează -2;
 Math.round(2.55) returnează 3;
 Math.round(-2.55) returnează -3;
 Math.round(-2.5) returnează -2;
 Math.round(2.5) returnează 3.
Exemplul 7.16. Programul de mai jos afişează o valoare naturală aleatoare din
intervalul [1.101]. Math.random() returnează o valoare aleatoare în intervalul
[0,1), Math.random()*100 returnează o valoare reală din intervalul [0,100),
Math.ceil(Math.random()*100) returnează o valoare întreagă din intervalul
[0,100], iar 1+Math.ceil(Math.random()*100) returnează o valoare naturală
din intervalul [1,101].
public static void main(String[] args) {
System.out.println(1+Math.ceil(Math.random()*100));
}

7.8.2. Clasa String

7.8.2.1. Constructorii şi lungimea unui şir de caractere

Un obiect al clasei String reţine un şir de caractere. Până acum am lucrat


cu obiecte ale clasei String, dar acum este momentul ca această clasă să fie
prezentată în mod sistematic. Clasa este înzestrată cu doi constructori:
⇒ String(); - iniţializează un obiect String care reţine şirul vid.

Exemplul 7.17. Secvenţa de mai jos afişează "un sir":


String s = new String ();
s="Un sir";
System.out.println(s);
Capitolul 7. Programare orientată pe obiecte 269

⇒ String (String s); - iniţializează un obiect String care reţine un şir de


caractere dat.
Exemplul 7.18. Secvenţa de mai jos afişează "un sir".
String s =new String ("Un sir");
System.out.println(s);

⇒ int length() - întoarce numărul de caractere din şir.

Exemplul 7.19. Secvenţa de mai jos afişează "6":


String s =new String ("Un sir");
System.out.println(s.length());

În Java nu este permisă adresarea unui caracter al şirului prin indice, pentru
exemplul precedent, s[k]. În schimb, avem metoda de mai jos, unde primul
caracter al şirului are indicele 0, al doilea are indicele 1, ş.a.m.d.

⇒ char charAt(int i) returnează caracterul de pe poziţia i.

Exemplul 7.20. Pentru şirul s, din exemplul precedent, instrucţiunea afişează ”n”:
System.out.println(s.charAt(1));

7.8.2.2. Compararea şirurilor de caractere

Şirurile de caractere reţinute de obiectele clasei String pot fi comparate din


punct de vedere lexicografic (ordinea din dicţionar). Pentru aceasta, clasa String
conţine mai multe metode.

⇒ int compareTo (String s) compară şirul de caractere reţinut de


obiectul curent cu şirul de caractere reţinut de s. Metoda returnează:
 o valoare negativă, dacă şirul reţinut de obiectul curent este situat, în
ordine lexicografică, înaintea şirului reţinut de obiectul s;
 0, dacă şirurile reţinute de cele două obiecte coincid;
 o valoare pozitivă, dacă şirul reţinut de obiectul curent este situat, în
ordine lexicografică, după şirul reţinut de obiectul s.

Exemplul 7.21. Secvenţa afişează -2, 0, 2:


String s =new String ("abc");
String s1=new String("cd");
System.out.println(s.compareTo(s1)+ " "
+s.compareTo(s)+" "+s1.compareTo(s));

⇒ int compareToIgnoreCase(String s) – la fel precum compareTo(),


numai că nu se face diferenţa între literele mari şi cele mici.
270 Manual de Informatică pentru clasa a XII-a

Exemplul 7.22. Secvenţa de mai jos afişează 0:


String s =new String ("AB");
String s1=new String("ab");
System.out.println(s.compareToIgnoreCase("ab"));

⇒ boolean equals(String s) – returnează true dacă şirurile de caractere


reţinute de obiectul curent şi cel transmis ca parametru sunt identice.
⇒ boolean equalsIgnoreCase(String s) – la fel ca mai sus numai că nu
se face distincţie între literele mari şi cele mici.

7.8.2.3. Subşiruri

Vom înţelege prin subşir al un şir de caractere, mai multe caractere


consecutive ale acestuia. De exemplu, ”text” are ca subşir ”ex”.

⇒ boolean startsWith(String s) – returnează true dacă şirul reţinut


de s precede şirul reţinut de obiectul curent.

⇒ boolean endsWith(String s) – returnează true dacă şirul reţinut de


s se află la sfârşitul şirului reţinut de obiectul curent.

Exemplul 7.23. Cu ajutorul metodelor startsWidth() şi endsWith(), secvenţa


de mai jos afişează de două ori true:
String s =new String ("123");
String s1=new String("12");
String s3=new String("23");
System.out.println(s.startsWith(s1));
System.out.println(s.endsWith(s3));

⇒ boolean regionMatches(int i1,String s,int i2,int l)


compară două subşiruri de lungime l. Primul subşir este al obiectului curent
şi începe de pe poziţia i1, al doilea subşir este al şirului s şi începe pe poziţia
i2. În caz de egalitate, metoda returnează true, contrar returnează false.

Exemplul 7.24. Secvenţa de mai jos afişează şirul ”567 coincid”:


if (s.regionMatches(4, s1, 2, 3))
System.out.println("567 coincid");

⇒ String substring (int index) – metoda returnează subşirul şirului


curent care este între poziţia index şi sfârşitul şirului.

Exemplul 7.25. Secvenţa de mai jos afişează ”456789”:


String s =new String ("123456789");
System.out.println(s.substring(3));
Capitolul 7. Programare orientată pe obiecte 271

⇒ String substring (int index, int sf) – metoda returnează


subşirul şirului curent care este între poziţia index şi sf-1.

Exemplul 7.26. Secvenţa de mai jos afişează ”45”:


String s =new String ("123456789");
System.out.println(s.substring(3,5));

⇒ String replace(char c1, char c2) – metoda returnează şirul


obţinut dacă se înlocuiesc, în şirul reţinut de obiectul curent, toate apariţiile
caracterului c1 cu caracterul c2.

Exemplul 7.27. Secvenţa de mai jos afişează ”tata”:


String s =new String ("mama");
System.out.println(s.replace('m','t'));

⇒ String replaceAll(String s1,String s2) – metoda returnează


şirul obţinut dacă se înlocuiesc, în şirul reţinut de obiectul curent, toate
apariţiile subşirului s1 cu subşirul s2.

Exemplul 7.28. Secvenţa de mai jos afişează ”*** doi *** doi trei”:
String s =new String ("unu doi unu doi trei");
System.out.println(s.replaceAll("unu","***" ));

⇒ String replaceFirst (String s1, String s2) – la fel ca mai


sus, doar că se înlocuieşte numai prima apariţie a subşirului.
Exemplul 7.29. Secvenţa de mai jos afişează ”*** doi unu doi trei”:
String s =new String ("unu doi unu doi trei");
System.out.println(s.replaceFirst("unu","***" ));

⇒ String trim() întoarce subşirul şirului reţinut de obiectul curent, subşir


obţinut prin eliminarea spaţiilor (blank-urilor de la început şi de la sfârşit).

⇒ int indexOf (String s) returnează indicele primei apariţii a subşirului


s în şirul reţinut de obiectul curent. În cazul în care s nu este găsit ca subşir
al şirului referit de obiectul curent, metoda returnează -1.

Exemplul 7.30. Secvenţa de mai jos afişează ”4”:


String s1=new String("un exemplu");
String s2=new String("xe");
System.out.println(s1.indexOf(s2));

7.8.2.4. Concatenarea şirurilor de caractere

Aşa cum deja ştim, în Java şirurile de caractere pot fi concatenate cu


ajutorul operatorului +.
272 Manual de Informatică pentru clasa a XII-a

Exemplul 7.31. Secvenţa următoare afişează ”Un sir Alt sir”:


String s =new String ("Un sir" );
String s1 = new String(" Alt sir");
s=s+s1;
System.out.println(s);

Acelaşi lucru este afişat şi de secvenţa de mai jos:


String s =new String ("Un sir "+"Alt sir" );
System.out.println(s);

Observaţie ! După cum observaţi, concatenarea şirurilor nu este comutativă, deci


înseamnă că prezintă importanţă ordinea în care şirurile sunt puse în expresie.

⇒ Metoda String concat(String s) returnează şirul obţinut prin


concatenarea şirului reţinut de obiectul curent cu s.

Exemplul 7.32. Secvenţa următoare afişează ”Un sir Alt sir”:


String s =new String ("Un sir ");
String s1 =new String ("Alt sir");
System.out.println(s.concat(s1));

7.8.2.5. Parametrii metodei main()

Acum suntem în măsură să analizăm parametrii metodei main():


public static void main(String[] args).
Antetul conţine un vector cu elemente de tip String. În exemplu, numele
vectorului este args.

1. Câte elemente are vectorul? Acest număr se poate afla uşor, ca la orice vector:
args.length.
2. Unde se introduc şirurile de caractere primite ca parametri de către main()?
Aceste şiruri se introduc pe linia de comandă a programului Java şi sunt separate
prin spaţii.
Exerciţiu! Programul de mai jos calculează suma valorilor introduse ca parametri.
Evident, mai întâi acestea sunt convertite către int. Exemple de utilizare:
a) Dacă apelul este java t 3 4 se va afişa 7.
b) Dacă apelul este java t 1 2 3 4 se va afişa 10.

class t {
public static void main(String[] args) {
int s=0;
for (int i=0;i<args.length;i++)
s+=Integer.parseInt(args[i]);
System.out.println("suma argumentelor este ="+s); }
}
Capitolul 7. Programare orientată pe obiecte 273

În continuare, prezentăm două aplicaţii ale clasei String.

Aplicaţia 7.5. Să se citească de la tastatură un şir de caractere, apoi să se afişeze.

Rezolvare. Vom utiliza clasa cin (cea pe care am folosit-o şi până acum) pentru
toate exerciţiile din acest paragraf.
public static void main(String[] args) {
String s =new String ();
s=cin.linie();
System.out.println(s);
}

Aplicaţia 7.6. Se citesc două şiruri de caractere.


Să se listeze indicele fiecărei apariţii a primului şir
citit ca subşir al celui de-al doilea şir citit. Iată cum
arată executarea programului (figura alăturată).

Figura 7.4. Rezultatul

Rezolvare. Ideea este următoarea: după ce subşirul a fost identificat, se afişează


poziţia de început, apoi se extrage din şir subşirul de început ce conţine inclusiv
prima apariţie a subşirului, după care procedeul se repetă până când subşirul
căutat nu mai este găsit. O problemă aparte este dată de faptul că trebuie, de
fiecare dată, să afişăm poziţia de început a subşirului în şirul iniţial şi nu în şirul
rămas. Din acest motiv, utilizăm mai multe variabile: poz - poziţia de început a
subşirului în şirul rămas; ind - suma lungimilor şirurilor extrase. De fiecare dată se
va afişa ca indice de apariţie a subşirului, ind+poz.
public static void main(String[] args) {
String subsir =new String (cin.linie());
String sir =new String (cin.linie());
int poz=0, ind=0, lsubs=subsir.length();
while (poz!=-1)
{ poz=sir.indexOf(subsir);
if (poz!=-1)
{ System.out.println(ind+poz);
ind+=poz+lsubs;
sir=sir.substring(poz+lsubs); }
}
}

2.8.3. Clase înfăşurătoare int – Integer


short - Short
Pentru fiecare tip primitiv s-a construit câte o long – Long
byte – Byte
clasă înfăşurătoare. Un obiect al clasei înfăşurătoare
char – Character
poate reţine o valoare a tipului primitiv. Alăturat, puteţi float – Float
observa corespondenţa între numele tipurilor primitive şi double – Double
numele claselor înfăşurătoare. boolean – Boolean
274 Manual de Informatică pentru clasa a XII-a

⇒ Fiecare clasă înfăşurătoare este înzestrată cu o metodă constructor.

Exemplul 7.33. Analizaţi liniile de mai jos:


int n=4;
Integer nr=new Integer(n);
Double x=new Double (-12.34);
Character c=new Character ('e');
Boolean este=new Boolean(true);

⇒ Constructorii acestor clase sunt supraîncărcaţi, în sensul că există şi


constructori care au ca parametru de intrare referinţe către obiecte de tip
String.

Exemplul 7.34. Analizaţi liniile de mai jos:


Integer nr=new Integer("10");
Double x=new Double ("-12.34");
Boolean este=new Boolean("true");

⇒ Fiecare clasă înfăşurătoare conţine o metodă care returnează valoarea


reţinută de obiectul instanţiat de ea.

Exemplul 7.35. Se extrag valorile reţinute de obiectele create în primele exemple:


int n1=nr.intValue();
double x1=x.doubleValue();
char c1=c.charValue();
boolean este1=este.booleanValue();

⇒ Fiecare clasă care reţine o valoare numerică conţine câte o metodă statică
(atenţie la apel!) pentru conversia către un tip primitiv a unui obiect de tip
String. Astfel avem:
a) int parseInt(String s); // in Integer
De exemplu: int t=Integer.parseInt("10");
b) parseFloat(String S); // in Float
De exemplu: float b=Float.parseFloat("-12.34");
c) double parseDouble (String s) // in Double
De exemplu: double b=Double.parseDouble("-12.34");
d) parseLong(String s); // in Long
De exemplu: long t=Long.parseLong("1000");
e) parseByte(String s) // in Byte
De exemplu: byte x=Byte.parseByte("12");

 Dacă şirul de caractere nu poate fi convertit către valoarea numerică de tipul


dorit, se generează o excepţie în urma căreia executarea programului se
întrerupe.
Capitolul 7. Programare orientată pe obiecte 275

 Conversia inversă, de la un tip primitiv către un şir se poate realiza uşor, aşa
cum am mai întâlnit de multe ori concatenând un şir (eventual vid) cu o
valoare numerică.
Exemplul 7.36. Secvenţa următoare afişează şirul ”10”:
int i=10;
String s=new String(i+"");
System.out.println(s);

⇒ Clasele înfăşurătoare conţin constantele MIN_VALUE şi MAX_VALUE care


reţin cea mai mică şi cea mai mare valoare a tipului respectiv. În cazul
variabilelor de un tip real (float, double) MIN_VALUE are semnificaţia de
cea mai mică valoare pozitivă care poate fi reţinută de tipul respectiv.
Exemplul 7.37. Priviţi liniile de mai jos:
System.out.println(Integer.MIN_VALUE);
System.out.println(Integer.MAX_VALUE);
System.out.println(Double.MIN_VALUE);
System.out.println(Double.MAX_VALUE);
Figura 7.5. Rezultatul

⇒ Clasele înfăşurătoare ale tipurilor reale (double, float) conţin constanta


NaN (Not a Number). Valoarea NaN se obţine dacă, într-o expresie de tip
real, se împarte 0 la 0, sau se extrage radical (indice 2) dintr-o valoare
negativă, sau se aplică logaritmul unui număr negativ, etc.

Exemplul 7.38. Secvenţa de mai jos afişează NaN:


double x=0,y=0,z;
z=x/y;
System.out.println(z);

Exemplul 7.39. Secvenţa de mai jos afişează NaN:


int x=-2;
System.out.println(Math.sqrt(x));

⇒ Clasele înfăşurătoare ale tipurilor reale (double, float) conţin metodele


boolean isNaN (double e), respectiv boolean isNaN (float e). Cele
două metode returnează true dacă se obţine NaN.

Exemplul 7.40. Secvenţa de mai jos afişează: "Ambii operanzi sunt 0":
int x=0; double y=0;
if (Double.isNaN(x/y))
System.out.println("Ambii operanzi sunt 0");

Exemplul 7.41. Secvenţa afişează: "Radical dintr-un numar negativ":


if (Double.isNaN(Math.sqrt(x)))
System.out.println("Radical dintr-un numar negativ");
276 Manual de Informatică pentru clasa a XII-a

Observaţie ! Comparările precum cele de mai jos nu au efect. De exemplu,


secvenţa nu afişează nici un mesaj:
if (Math.sqrt(x)==Double.NaN)
System.out.println("Radical din numar negativ");

⇒ Clasele înfăşurătoare ale tipurilor reale (double, float) conţin constantele


POSITIVE_INFINITY, NEGATIVE_INFINITY. Constanta POSITIVE_INFINITY
se obţine dacă, într-o expresie de tip real, se împarte o valoare pozitivă la 0,
iar constanta NEGATIVE_INFINITY se obţine dacă, într-o expresie de tip
real, se împarte la 0 o valoare negativă.
double x=2;
System.out.println(x/0);
x=-2;
System.out.println(x/0); Figura 7.6. Rezultatul

Observaţie ! Dacă expresia este de tip întreg, atunci se generează o excepţie


(excepţiile vor fi studiate separat), iar programul este întrerupt, ca în secvenţa de
mai jos:
int x=2;
System.out.println(x/0);

⇒ Clasele înfăşurătoare ale tipurilor reale (double, float) conţin metoda


booleană boolean isInfinite(double) (sau float) prin care se
testează dacă s-a obţinut una din constantele de mai sus.

Exemplul 7.42. Secvenţa de mai jos afişează "Impartire la 0":


double x=2;
if (Double.isInfinite(x/0))
System.out.println("Impartire la 0");

7.9. Extinderea claselor (moştenirea)

1. Pornind de la o clasă dată se poate crea o altă clasă, care o extinde


(moşteneşte) pe aceasta. Noua clasă va avea toate datele membru şi toate
metodele clasei de la care s-a pornit, cărora li se pot adăuga noi date membru
şi/sau noi metode. În Java, clasa care este extinsă se numeşte superclasă, iar
noua clasă se numeşte subclasă.
Exemplul 7.43. Analizaţi codul de mai jos:
class C1
{ int x,y; }
Capitolul 7. Programare orientată pe obiecte 277

class C2 extends C1
{ int z;
void afis()
{ System.out.println(x+" "+ y+" "+z); }
}
public class C {
public static void main(String[] args) {
C2 ref= new C2();
ref.x=3;
ref.y=4;
ref.z=5;
ref.afis();
}
}

Aici s-a extins clasa C1. Ea conţine două date membru x şi y, ambele de tip int.
În exemplul dat, C1 este superclasă.
Noua clasă C2 va conţine datele membru ale clasei C1 (în exemplu x şi y) dar şi o
nouă dată membru (z, de tip int). De asemenea, clasa C2 conţine şi metoda
afis(), care are rolul de a afişa conţinutul datelor membru ale unui obiect. În
exemplu, clasa c2 este subclasă. Programul creează un obiect al clasei C2, numit
ref, îi iniţializează datele membru şi le afişează.

2. Pentru a marca faptul că o clasă extinde o altă clasă se foloseşte cuvântul


extends (în exemplu, class C2 extends C1).

3. Iniţializarea unui obiect al subclasei are ca efect apelul, în această ordine, al


constructorului superclasei şi apelul constructorului subclasei. Este normal să fie
aşa, pentru că subclasa include datele membru şi metodele superclasei.
Exemplul 7.44. Analizaţi programul de mai jos, în care fiecare clasă conţine câte
un constructor:
class Unu{
Unu () { System.out.println("Constructor 1"); }
}
class Doi extends Unu
{ Doi() { System.out.println("Constructor 2"); };
}
public class C {
public static void main(String[] args) {
Doi x=new Doi();
}
}

Programul afişează:
Constructor 1
Constructor 2
278 Manual de Informatică pentru clasa a XII-a

4. Există posibilitatea ca anumite date membru sau metode să aibă acelaşi nume
atât în superclasă cât şi în subclasă. În astfel de cazuri, implicit, la întâlnirea
numelui datei membru (sau metodei) se apelează data membru (metoda) a
subclasei. În cazul în care se doreşte ca să fie apelată data membru (metoda) a
superclasei, se utilizează cuvântul cheie super. El are semnificaţia de obiect
curent al superclasei. În exemplul de mai jos, x este dată membru atât a
superclasei cât şi a subclasei.
Exemplul 7.45. Programul următor va afişa ”1 2 3”:
class C1
{ int x=1,y; }
class C2 extends C1
{ int x;
void afis()
{ System.out.println(super.x+" "+ y+" "+x); }
}
class C {
public static void main(String[] args) {
C2 pt= new C2();
pt.x=3;
pt.y=2;
pt.afis();
}
}

Observaţie ! Cuvântul cheie super nu poate fi folosit în afara clasei.


5. În cazul în care superclasa este înzestrată cu un constructor care primeşte
parametri, atunci este obligatoriu ca acesta să fie apelat de constructorul subclasei.
De ce? Aşa cum am arătat, constructorul subclasei apelează automat constructorul
superclasei. În cazul în care apelul nu este explicit, este apelat constructorul
implicit (fără parametri) al superclasei. Ori, am învăţat faptul că, în condiţiile
existenţei unui constructor cu parametri, nu mai este posibil să apelăm
constructorul implicit, pentru că apare eroare. Mai mult, prima instrucţiune a
constructorului subclasei trebuie să fie apelul constructorului superclasei. Apelul
constructorului superclasei se face prin:
super (lista_parametri).
Exemplul 7.46. Analizaţi programul următor, în care clasa Elev conţine numele şi
prenumele unui elev, iar clasa Olimpic extinde clasa Elev şi conţine în plus o
dată membru, materia la care elevul este olimpic şi o metodă prin care se afişează
numele, prenumele elevului şi materia respectivă.
class Elev
{ String nume, prenume;
Elev (String nume, String prenume)
{ this.nume=new String(nume);
this.prenume=new String(prenume); }
}
Capitolul 7. Programare orientată pe obiecte 279

class Olimpic extends Elev


{ String materia;
Olimpic(String nume, String prenume, String materia)
{ super(nume,prenume); // apel constructor al superclasei
this.materia=new String(materia);}
void afis()
{ System.out.println(nume+" "+prenume+" "+materia); }
}
public class test {
public static void main(String[] args) {
//primul mod de creare a unui obiect olimpic
Olimpic A=new Olimpic("Pascu", "Marius", "informatica");
//al doilea mod de creare a unui obiect olimpic
String n=new String("Grosu");
String p=new String("Bogdan");
String mat=new String("matematica");
Olimpic B=new Olimpic(n,p,mat); A.afis(); B.afis();
}
}
6. În Java, o clasă poate extinde (moşteni) o singură superclasă. Nu există un
mecanism de moştenire multiplă, aşa precum există în alte limbaje. Din acest
motiv, ierarhia claselor are o structură arborescentă.

7.9.1. Un exemplu de extindere a unei clase

Fie clasa Complex, de mai jos. Are două date membru, x şi y, care reţin
partea reală şi partea imaginară a unui număr complex. De asemenea, clasa este
înzestrată cu un constructor şi metoda afis(), care afişează numărul complex
reţinut de obiect.
class Complex
{ double x,y;
Complex (double x, double y)
{ this.x=x;
this.y=y; }
void afis() { System.out.println(x+" "+y); }
}
Clasa este extinsă la o alta, Complex_op, care conţine şi metode prin care
se efectuează operaţiile de mai jos cu numere complexe:
z 1 + z 2 = x 1 + i ⋅ y1 + x 2 + i ⋅ y 2 = x 1 + x 2 + i ⋅ (y1 + y 2 ).
z 1 − z 2 = x 1 + i ⋅ y1 − x 2 − i ⋅ y 2 = x 1 − x 2 + i ⋅ (y1 − y 2 ).
z 1 ⋅ z 2 = (x 1 + i ⋅ y1 )(x 2 + i ⋅ y 2 ) = x 1 ⋅ x 2 − y1 y 2 + i ⋅ (x 1 y 2 + x 2 y1 ).
z1 x + i ⋅ y1
= 1
( x + i ⋅ y1 ) ⋅ ( x 2 − i ⋅ y 2 ) x1 x 2 + y 1 y 2 + i( x 2 y1 − x1 y 2 )
= 1 =
z2 x2 + i ⋅ y 2 (x2 + i ⋅ y 2 ) ⋅ (x2 − i ⋅ y 2 ) x 22 + y 22
280 Manual de Informatică pentru clasa a XII-a

Iată ce conţine, în plus, clasa Complex_op:

⇒ Doi constructori. Primul dintre ei acceptă partea reală şi partea imaginară a


unui număr complex. Al doilea, acceptă numai partea reală (număr real
inclus evident în mulţimea numerelor complexe).
⇒ Metodele add, sub, mul, div - efectuează operaţiile de adunare, respectiv
scădere, înmulţire, împărţire a două numere complexe. Ele returnează
numărul complex rezultat în urma operaţiei.
class Complex_op extends Complex
{
Complex_op (double x, double y)
{ super(x,y); }
Complex_op (double x)
{ super(x,0); }
Complex_op add(Complex_op z)
{ Complex_op t=new Complex_op (x+z.x,y+z.y);
return t; }
Complex_op sub(Complex_op z)
{ Complex_op t=new Complex_op (x-z.x,y-z.y);
return t; }
Complex_op mul(Complex_op z)
{ Complex_op t=new Complex_op (x*z.x-y*z.y, x*z.y+z.x*y);
return t; }
Complex_op div(Complex_op z)
{ double num=z.x*z.x+z.y*z.y;
Complex_op t;
if (num!=0)
t=new Complex_op ((x*z.x+y*z.y)/num,(z.x*y-x*z.y)/num);
else t=new Complex_op(0,0);
return t;
}
}

În continuare, sunt prezentate exemple de lucru cu numerele complexe.

Exemplul 7.47. Să se creeze două obiecte de tip Complex_op şi să se afişeze


suma, diferenţa, produsul şi câtul lor.
public class test {
public static void main(String[] args) {
// instantiez z si il afisez
Complex_op z=new Complex_op(2,3);
z.afis();
// instantiez z1 si il afisez
Complex_op z1= new Complex_op(10);
z1.afis();
Capitolul 7. Programare orientată pe obiecte 281

// Afisez suma dintre z si z1


z.add(z1).afis();
// Afisez diferenta dintre z si z1
z.sub(z1).afis();
// Afisez produsul dintre z si z1
z.mul(z1).afis();
// Afisez catul dintre z si z1
z.div(z1).afis();
}
}

Exemplul 7.48. Se citesc a şi b două numere reale care reprezintă partea reală şi
partea complexă a numărului z=a+b*i şi n, un număr natural mai mare sau egal
cu 1. Se cere să se afişeze zn.
public class test {
public static void main(String[] args) {
System.out.print("a=");
double a=Double.parseDouble(cin.Token());
System.out.print("b=");
double b=Double.parseDouble(cin.Token());
Complex_op z= new Complex_op(a,b);
z.afis();
// initializez produsul cu 1;
Complex_op P= new Complex_op(1);
System.out.print("n=");
int n=Integer.parseInt(cin.Token());
for (int i=0;i<n;i++) P=P.mul(z);
P.afis();
}
}

Exemplul 7.49. Să se extindă clasa Complex_op, la o alta numită Cmpl, care să


conţină, în plus, o metodă prin care returnează modulul numărului complex şi o altă
metodă booleană care returnează true, în cazul în care numărul este real (y are
valoarea 0).

Rezolvare. Întrucât constructorii nu se moştenesc, a fost necesară rescrierea lor:


class Cmpl extends Complex_op
{
Cmpl (double x, double y)
{ super(x,y); }
Cmpl (double x)
{ super(x,0); }
double modul()
{ return Math.sqrt(x*x+y*y);}
boolean real()
{ return y==0; }
}
282 Manual de Informatică pentru clasa a XII-a

Exemplul 7.50. Se citeşte un vector de numere complexe. Se cere să se sorteze


crescător elementele vectorului în funcţie de modulul lor.

Rezolvare. Datorită faptului că avem nevoie de modulul numerelor complexe, vom


apela la ultima clasă creată: Cmpl. Observaţi ierarhia acestor clase: la bază este
Complex, apoi Complex_op, iar ultima este Cmpl. Programul utilizează şi metoda
Afis(), care aparţine clasei complex.
public class test {
public static void main(String[] args) {
System.out.print("n=");
int n=Integer.parseInt(cin.linie());
Cmpl[] V=new Cmpl[n];
for (int i=0;i<n;i++)
{ System.out.print("V["+i+"].x=");
double x=Double.parseDouble(cin.linie());
System.out.print ("V["+i+"].y=");
double y=Double.parseDouble(cin.linie());
V[i]=new Cmpl(x,y);
}
boolean gasit;
Cmpl man;
do
{ gasit=false;
for (int i=0;i<n-1;i++)
if (V[i].modul()>V[i+1].modul())
{ man=V[i];
V[i]=V[i+1];
V[i+1]=man;
gasit=true;
}
} while (gasit);
for (int i=0;i<n;i++) V[i].afis();
}
}

7.10. Polimorfism

Prin polimorfism vom înţelege posibilitatea ca atât superclasa, cât şi


subclasa să aibă metode cu acelaşi nume (metodele pot fi redefinite).

Deşi, în aparenţă, înţelegerea polimorfismului nu este dificilă, în realitate,


apar anumite probleme pe care ne propunem să le rezolvăm în acest paragraf. Mai
mult, polimorfismul reprezintă unul din punctele cheie ale programării orientate pe
obiecte şi este un instrument puternic de programare.
Capitolul 7. Programare orientată pe obiecte 283

Fie B o clasă care extinde o clasă A. Prin urmare, toate datele membru şi
metodele clasei A se regăsesc şi în clasa B. Am mai învăţat faptul că o metodă a
clasei A poate fi redefinită, adică în clasa B scriem o metodă cu acelaşi nume (în
exemplu, void tip()). Vom trata două cazuri, cazul în care metodele sunt
nestatice şi cazul în care metodele sunt statice.
I) Metodele şi datele membru sunt nestatice.

Exemplul 7.51. Fie O un obiect al clasei A şi O1 un obiect al clasei B. Vedeţi


exemplul următor, al cărui rezultat îl puteţi observa în Fig. 7.7:
class A
{ int i=1;
void tip() { System.out.println("clasa A"); }
}
class B extends A
{ void tip() { System.out.println("clasa B"); }
}
Figura 7.7.
public class test { Rezultatul
public static void main(String[] args) {
// Cazul 1
A O=new A(); O.tip();
// Cazul 2
B O1=new B(); O1.tip();
// Cazul 3
A O2=new B(); O2.tip();
}
}

• În cazul 1 se apelează metoda tip() a clasei A. Se va afişa clasa A şi


valoarea 1 (pentru i). Este normal să fie aşa, obiectul este al clasei A,
referinţa este către un obiect al clasei A.
• În cazul 2 se apelează metoda tip() a clasei B. Se va afişa clasa B şi
valoarea 2 (pentru i). Este normal să fie aşa, obiectul este al clasei B,
referinţa este către un obiect al clasei B.
• În cazul 3, acesta este cazul interesant pe care-l studiem în acest
moment, se va apela metoda tip() a clasei B, prin urmare se va afişa
clasa B şi valoarea 1 (pentru i). Să observăm că obiectul este al clasei
B, dar variabila care reţine referinţa către el este o referinţă către obiecte
ale clasei A. Cu toate că a fost apelată metoda clasei B, a fost afişat
conţinutul variabilei i a clasei A.
Foarte important ! În cazul unei metode a superclasei, redefinită în subclasă,
două elemente prezintă importanţă: tipul variabilei referinţă (către obiecte ale
superclasei sau către obiecte ale subclasei) şi tipul obiectului creat (al
superclasei sau al subclasei). Se disting, astfel două cazuri:
284 Manual de Informatică pentru clasa a XII-a

A) tipul referinţei şi tipul obiectului creat coincid (sunt fie ale superclasei, fie
ale subclasei). În acest caz este apelată metoda care este din tipul comun. De
asemenea, se afişează variabila care aparţine obiectului de tip comun. Vezi,
mai sus, cazurile 1 şi 2.
B) tipul referinţei este al superclasei, iar tipul obiectului creat este al subclasei
(invers nu este posibil, aşa cum am arătat). În acest caz, dacă metoda
redefinită este nestatică, Java ia în considerare tipul obiectului creat şi deci,
va fi apelată metoda subclasei. Vezi, mai sus, cazul 3. În schimb, se obţine
accesul la data membru a superclasei.
II) Metodele şi datele membru sunt statice.

Exemplul 7.52. Reluăm problema pentru acest caz. Vedeţi programul de mai jos,
iar rezultatul afişat de el, în Fig. 7.8. În cazurile 1 şi 2 comportamentul este acelaşi,
dar în cazul 3 este apelată metoda superclasei, deci se afişează clasa A.
Observaţi faptul că, în acest caz, comportamentul este diferit.
class A
{ static int i=1;
static void tip() { System.out.println("clasa A"); }
}

class B extends A
{ static int i=2;
static void tip() { System.out.println("clasa B"); }
}
public class test {
public static void main(String[] args)
{ // Cazul 1
System.out.println("Cazul 1");
A O=new A(); O.tip();
System.out.println(O.i);
// Cazul 2
System.out.println("Cazul 2"); Figura 7.8.
B O1=new B(); O1.tip(); Rezultatul
System.out.println(O1.i);
// Cazul 3
System.out.println("Cazul 3");
A O2=new B(); O2.tip();
System.out.println(O2.i);
}
}

În terminologia programării orientate pe obiecte veţi întâlni termenul de


legare (statică, dinamică). Care este semnificaţia lui? Pornind de la referinţa către
obiect, se apelează o metodă redefinită. Am văzut că, în unele cazuri se apelează
metoda superclasei, în altele, se apelează metoda subclasei. Cu alte cuvinte, se
apelează (leagă) o metodă sau alta. Aceasta este semnificaţia termenului de
legare (adică apel al unei metode sau alta).
Capitolul 7. Programare orientată pe obiecte 285

⇒ Legarea este statică dacă înainte de executarea programului se poate şti


care metodă este apelată şi este dinamică dacă numai în momentul
executării se decide metoda care va fi apelată. În Java este permisă şi
legarea dinamică.
Priviţi exemplul de mai jos, în care legarea dinamică este evidentă.
Exemplul 7.53. Dacă se introduce 0 se afişează clasa A, iar dacă se introduce o
valoare diferită de 0 se afişează clasa B:
class A
{ int i=1;
void tip() { System.out.println("clasa A"); }
}
class B extends A
{ void tip() { System.out.println("clasa B"); }
}
public class Clasa1 {
public static void main(String[] args) {
A x;
int n=Integer.parseInt(cin.Token());
if (n==0) x=new A();
else x=new B();
x.tip();
}
}

7.10.1. Un exemplu de polimorfism

Să se creeze o clasă numită Muncitor. Clasa va conţine data membru


ore_lucrate şi un constructor prin care acesteia i se atribuie o valoare. De
asemenea, clasa conţine o metodă nestatică salariu() prin care se calculează
suma câştigată de acesta (se obţine ca produs între numărul orelor lucrate şi suma
încasată pentru o oră lucrată, în exemplu 2 lei). Dintre muncitori, se selectează
şeful de echipă, care are în subordine mai mulţi muncitori. Se ştie că şeful de
echipă primeşte mai mult pentru o oră lucrată (în exemplu, 5 lei). Se construieşte
clasa Sef_echipa, care este subclasă a clasei Muncitor. Metoda salariu()
este redefinită. Dintre şefii de echipă, unii sunt selectaţi pentru a urma o şcoală de
maiştri. După ce devin maiştri, au în subordine mai mulţi şefi de echipă. Să se
construiască clasa Maistru, care are ca superclasă clasa Sef_echipa. Un
maistru primeşte pe oră mai mult decât un şef de echipă (în exemplu 10 lei), deci
metoda salariu() este redefinită. Se cere să se scrie un program care citeşte un
număr natural n între 1 şi 3. Dacă n este 1, se construieşte un obiect al clasei
muncitor, dacă n este 2, se construieşte un obiect al clasei sef_echipa, iar
dacă n este 3, se construieşte un obiect al clasei Maistru. De asemenea, se
citeşte numărul de ore lucrat de persoana respectivă. În final, se va afişa salariul
încasat de persoana citită.
286 Manual de Informatică pentru clasa a XII-a

class Muncitor
{ int ore_lucrate;
Muncitor(int ore_lucrate)
{ this.ore_lucrate=ore_lucrate; }
double salariu()
{ return ore_lucrate * 2; }
}

class Sef_echipa extends Muncitor


{ Sef_echipa(int ore_lucrate)
{ super(ore_lucrate); }
double salariu()
{ return ore_lucrate * 5; }
}

class Maistru extends Sef_echipa


{ Maistru(int ore_lucrate)
{ super(ore_lucrate); }
double salariu()
{ return ore_lucrate * 10; }
}

public class test {


public static void main(String[] args) {
Muncitor x=null;
int tip=Integer.parseInt(cin.Token());
int ore=Integer.parseInt(cin.Token());
switch (tip)
{ case 1: x=new Muncitor(ore); break;
case 2: x=new Sef_echipa(ore); break;
case 3: x=new Maistru(ore); break;
}
System.out.println(x.salariu());
}
}

Observaţii !

 Exemplul dat se referă la polimorfism şi la legarea dinamică. Metoda salariu


este prezentă în toate cazurile. Este rulată o metodă sau alta în funcţie de
valoarea citită, prin urmare avem legare dinamică.

 Există multe alte metode de rezolvare ale acestei probleme. Judecând după
problema în sine, ar rezulta că utilizarea polimorfismului poate fi evitată. Aşa
este, dar în cazul programelor complexe (de exemplu, în programarea
vizuală), utilizarea lui se dovedeşte extrem de utilă.
Capitolul 7. Programare orientată pe obiecte 287

7.11. Clase abstracte


Limbajul Java pune la dispoziţia programatorilor un mecanism care se
dovedeşte uneori extrem de eficient şi anume clasele abstracte.
O clasă abstractă conţine date membru (nu în mod obligatoriu) şi mai multe
metode, dar unele pot fi, la rândul lor abstracte. Pentru o metodă abstractă, în
clasă se trece doar prin antetul ei. Metodele abstracte urmează să fie redefinite în
subclase. Orice clasă abstractă trebuie să fie precedată de cuvântul cheie
abstract şi orice metodă abstractă din cadrul ei trebuie şi ea să fie precedată de
acelaşi cuvânt cheie. Clasele abstracte nu se folosesc direct, adică nu se
instanţiază obiecte ale lor, ci se utilizează doar pentru a fi extinse (sunt prin
definiţie superclase).
Exemplul 7.54. În programul de mai jos clasa Ex este abstractă. Conţine două
metode abstracte, afis1() şi afis2(), dar şi o metodă decid(), care în funcţie
de un parametru apelează una dintre cele două metode abstracte. Pentru a putea
folosi clasa Ex, o extindem obţinând astfel clasa Ex1. În clasa Ex1, redefinim cele
două metode. Totuşi, clasa Ex1 nu redefineşte metoda decid(), deci orice obiect
al ei va folosi metoda din clasa abstractă. Acest mecanism, permite ca în clasa
abstractă să existe un anumit “motor” (metodă) care apelează alte metode care
urmează a fi redefinite. Programul de mai jos apelează mai întâi Afis 1 şi apoi
Afis 2:
abstract class Ex
{ abstract void afis1();
abstract void afis2();
void decid(int b)
{ if (b>0) afis1();
else afis2();
}
}
class Ex1 extends Ex
{ void afis1()
{ System.out.println("Afis 1"); }
void afis2()
{ System.out.println("Afis 2"); }
}
public class test {
public static void main(String[] args) {
Ex1 a=new Ex1();
a.decid(1);
a.decid(-1);
}
}
288 Manual de Informatică pentru clasa a XII-a

7.11.1. Un exemplu de clasă abstractă

Cei care au studiat backtracking în variantă iterativă, standardizată, au văzut


faptul că există o unică metodă care apelează mai multe metode care au acelaşi
nume, parametri şi acelaşi rol. A rezolva o problemă sau alta înseamnă a rescrie
metodele specifice (init(), succesor(), ş.a.m.d.) dar motorul (metoda
back()) rămâne aceeaşi. De aici şi ideea: o clasă abstractă (Bkt) va reţine
metoda back(), care nu este abstractă, iar celelalte metode sunt abstracte. A
rezolva o problemă înseamnă a crea o subclasă în care redefinim metodele
necesare (init(), succesor(), valid(),...) conform cerinţelor problemei.
Exemplul 7.55. Programul de mai jos, utilizează clasa bkt, pentru a o extinde în
vederea rezolvării problemei particulare de generare a tuturor permutărilor mulţimii
{1,2,...,n}, pentru n citit.
abstract class Bkt
{ int[] st; int n;
abstract void init(int k);
abstract boolean am_Succesor (int k);
abstract boolean e_Valid(int k);
abstract boolean solutie(int k);
abstract void tipar();
void back()
{ boolean AS;
int k=1;
st=new int[n+1];
init(k);
while (k>0)
{ do { } while ((AS=am_Succesor(k)) && !e_Valid(k));
if (AS)
if (solutie(k)) tipar();
else {k++;init(k);}
else k--; }
}
}
class Permut extends Bkt {
Permut (int n)
{ this.n=n; }
void init(int k)
{ st[k]=0; }
boolean am_Succesor (int k)
{ boolean rasp=false;
if (st[k]<n) { st[k]++; rasp=true; }
return rasp; }
Capitolul 7. Programare orientată pe obiecte 289

boolean e_Valid(int k)
{ boolean rasp=true;
for (int i=1;i<k;i++)
if (st[i]==st[k]) rasp=false;
return rasp; }
boolean solutie(int k)
{ return k==n; }
void tipar()
{ for (int i=1;i<=n;i++) System.out.print(st[i]);
System.out.println(); }
}
public class test {
public static void main(String[] args) {
System.out.print("n=");
int n=Integer.parseInt(cin.Token());
Permut x=new Permut(n);
x.back();
}
}

Exerciţiu ! Se cere să se rezolve problema celor n dame. Folosind clasele


anterioare şi polimorfismul, problema devine foarte uşoară. Obţinem clasa Dame
care extinde clasa Permut. O singură metodă trebuie redefinită, metoda boolean
e_Valid(int k).
class Dame extends Permut
{ Dame (int n)
{ super(n); }
boolean e_Valid(int k)
{ boolean rasp=true;
for (int i=1;i<k;i++)
if ((st[i]==st[k]) ||
(Math.abs(st[k]-st[i])==Math.abs(k-i)))
rasp=false;
return rasp;
}
}

Iar programul este asemănător celui anterior:


public class test {
public static void main(String[] args) {
System.out.print("n=");
int n=Integer.parseInt(cin.Token());
Bkt x=new Dame(n);
x.back();
}
}
290 Manual de Informatică pentru clasa a XII-a

7.12. Interfeţe
Prin interfaţă vom înţelege un proiect de clasă. O interfaţă poate conţine
doar constante şi antete de metode. Ele sunt acceptate de limbaj şi se
presupune că ulterior, interfeţele vor fi implementate de una sau mai multe clase. O
interfaţă arată ca o clasă, numai că, în locul cuvântului class, se foloseşte
cuvântul interface. Atunci când scriem o clasă care implementează o anumită
interfaţă, se foloseşte cuvântul cheie implements, ca în exemplul de mai jos. O
interfaţă poate fi implementată de una sau mai multe clase.

Exemplul 7.56. Mai jos, avem o interfaţă numită InterfA. Interfaţa este
implementată de două clase, A şi B. În main() probăm toate acestea prin crearea
a două obiecte, unul care instanţiază clasa A, altul care instanţiază clasa B.
Programul afişează:
Afis din clasa A=6 5
Afis din clasa B=7 5
iar codul este:
interface InterfA {
int i=5;
void afis();
}
class A implements InterfA{
int i=6;
public void afis()
{ System.out.println("Afis din clasa A="+i+" "+InterfA.i);}
}
class B implements InterfA {
int i=7;
public void afis()
{ System.out.println("Afis din clasa B="+i+" "+InterfA.i); }
}
public class test {
public static void main(String[] args) {
A x=new A(); x.afis();
B y=new B(); y.afis(); }
}

Mai observăm că:

 Constantele declarate în interfaţă (în exemplu constanta i, cu valoarea 5) se


apelează prin numele interfeţei, urmat de ‘.’ şi de numele constantei.
 Constantele pot fi redefinite de date membru (în exemplu de i cu valoarea 6 şi
i cu valoarea 7). Atât constanta cât şi redefinirile ei pot fi apelate simultan.
Capitolul 7. Programare orientată pe obiecte 291

⇒ Variabila de tip referinţă către interfaţă poate memora o referinţă către orice
clasă care implementează respectiva interfaţă. Mai mult, legarea este
dinamică, aşa cum rezultă din exemplul următor.

Exemplul 7.57. Pentru clasele implementate anterior, se poate obţine acelaşi efect
dacă main() se scrie astfel:
public static void main(String[] args) {
int tip=Integer.parseInt(cin.Token());
if (tip==1) { interfA x=new A(); x.afis(); }
else { interfA y=new B(); y.afis(); }
}

⇒ Interfaţa poate extinde mai multe interfeţe.

Exemplul 7.58. Să observăm că o clasă poate extinde o singură clasă, dar o


interfaţă poate extinde mai multe interfeţe, ca mai jos:
interface A { void metA(); }
interface B { void metB(); }
interface C { void metC(); }
interface Extinsa extends A,B,C
{ void MetE(); }

⇒ A implementa o interfaţă extinsă înseamnă a implementa toate metodele


interfeţelor care au stat la baza extinderii, plus metodele a căror antet se
găseşte în interfaţa extinsă.

Exemplul 7.59. Mai jos se implementează clasa Extinsa:


class Ex implements Extinsa {
public void metA() {System.out.println("metA");}
public void metB() {System.out.println("metB");}
public void metC() {System.out.println("metC");}
public void metE() {System.out.println("metE");}
}
public class test {
public static void main(String[] args) {
Ex x=new Ex();
x.metA(); x.metB(); x.metC(); x.metE();
}
}

4. O clasă poate implementa oricâte interfeţe.

Exemplul 7.60. Analizaţi programul următor:


interface A { void metA(); }
interface B { void metB(); }
interface C { void metC(); }
292 Manual de Informatică pentru clasa a XII-a

class Ex implements A,B,C {


public void metA() { System.out.println("metA"); }
public void metB() { System.out.println("metB"); }
public void metC() { System.out.println("metC"); }
}
public class test {
public static void main(String[] args) {
Ex x=new Ex(); x.metA(); x.metB(); x.metC(); }
}
⇒ În multe programe se solicită citirea unui număr natural. Aceasta se poate
face prin afişarea unui mesaj, apoi urmează citirea propriu-zisă a acestuia.
Pentru a permite ca programul să rămână aproape neschimbat atunci când
citim un număr natural într-un fel sau altul, metoda care citeşte se va găsi
într-o interfaţă, care este implementată diferit de mai multe clase.

Exemplul 7.61. În acest exemplu interfaţa CitScriu conţine antetul unei metode
de citire a unui număr natural. Două clase, IO1 şi IO2 implementează această
interfaţă. Clasa Suma este înzestrată cu un constructor care are ca parametru o
referinţă către obiectul care efectuează citirea şi o metodă, afis(), care citeşte
două numere naturale şi afişează suma lor. Rulaţi programul şi prin crearea
obiectului Suma, cu ajutorul instrucţiunii: Suma s=new Suma (new IO2());.
interface CitScriu {
int citeste(); }
class IO1 implements CitScriu {
public int citeste()
{ System.out.print("Introduceti valoarea ");
return Integer.parseInt(cin.linie()); }
}
class IO2 implements CitScriu {
public int citeste()
{ System.out.print("Tastati valoarea dorita ");
return Integer.parseInt(cin.linie());}
}
class Suma {
CitScriu x;
Suma(CitScriu x) { this.x=x; }
void afis()
{ int n=x.citeste(); n+=x.citeste();
System.out.println("Suma este "+n); }
}
public class test {
public static void main(String[] args) {
Suma s=new Suma (new IO1()); s.afis();
}
}
Capitolul 7. Programare orientată pe obiecte 293

7.13. Specificatori de acces (modificatori de acces)

Forma generală prin care o clasă este definită se poate observa mai jos. Tot
ce este trecut între paranteze drepte este opţional.
[<Modificatori clasa>] class <nume clasa> [extends <nume
clasa>] implements [lista interfete]
{ [...] }
Până acum, nu am prezentat modificatorii de clasă. Aceştia sunt: public,
abstract şi final şi se folosesc în această ordine.
1. Modificatorul public. Dacă este trecut acest modificator, atunci clasa
respectivă poate fi accesată de orice cod Java care accesează pachetul în care se
găseşte acea clasă. Dacă acest modificator este absent, atunci clasa poate fi
accesată doar din pachetul în care se găseşte. Clasele publice trebuie scrise în
fişiere care le poartă numele şi au extensia .java.
Observaţie foarte importantă ! În cazul în care la crearea clasei nu se foloseşte
clauza package (nu se realizează un pachet), se consideră că respectiva clasă
face parte dintr-un pachet fără nume. Pachetul fără nume este alcătuit din
totalitatea claselor fără clauza package care se găsesc într-un folder. Din acest
motiv, cât timp am lucrat numai cu clase aflate în folder-ul bin, nu a fost nevoie ca
acestea să conţină clauza package.
2. Modificatorul abstract - marchează o clasă abstractă (revedeţi clasele
abstracte). În absenţă, se consideră că respectiva clasă nu este abstractă.
3. Modificatorul final este trecut atunci când nu se doreşte ca respectiva clasă
să fie extinsă (derivată, moştenită), caz în care această operaţie este interzisă.
În rest, am învăţat faptul că o clasă poate extinde o singură clasă, dar poate
implementa mai multe interfeţe (vedeţi: extends, implements).

Pentru definirea datelor membru în Java, avem forma generală:


[<Modificatori>] <tip data>
<Nume data membru1>[=valoare]
[Nume data membru2][=valoare]...

Modificatorii sunt:
1. public - data membru poate fi accesată de oriunde este accesibilă (deci şi
din afara pachetului) şi poate fi moştenită;
2. protected - data membru poate fi accesată de codul aflat în acelaşi pachet
şi poate fi moştenită;
3. private - data membru poate fi accesată numai din clasa în care se află şi
nu este moştenită (sau dacă vreţi, este moştenită, dar nu poate fi accesată din
clasa care o moşteneşte, ceea ce este acelaşi lucru);
294 Manual de Informatică pentru clasa a XII-a

4. modificatorul implicit (package) – are efect în absenţa modificatorilor de mai


sus. Data poate fi accesată de cod din acelaşi pachet şi poate fi moştenită numai
de clase ale aceluiaşi pachet;
5. final – data membru este considerată constantă, deci nu poate fi modificată;
6. static - data membru nu este memorată de fiecare obiect al clasei respec-
tive (modificatorul a mai fost prezentat).

Modificatorii public, protected, private şi cel implicit (package) se


numesc modificatori de acces. Evident, o definiţie de dată membru va conţine
numai unul din cei trei modificatori sau, în absenţa lor, se consideră că avem
modificatorul implicit.

Pentru declararea unei metode se utilizează forma generală:


[<Modificatori>] <Tip metoda> <Nume> (<lista parametri>)
[throws <TipClasa1>[<TipClasa2>]...]]<metoda>
Modificatorii sunt prezentaţi mai jos, iar clauza throws va fi studiată în capitolul
care tratează excepţiile.
1. Modificatorii de acces - au aceeaşi semnificaţie ca la datele membru.
2. final - specifică faptul că într-o clasă derivată, metoda nu poate fi redefinită.
3. static - are ca efect faptul că metoda nu este reţinută de fiecare obiect al
clasei respective. Acest modificator a fost prezentat.

7.13.1. Exemple de utilizare a modificatorilor

Exemplul 7.62. Modificatorii sunt absenţi. Clasa poate fi accesată din interiorul
pachetului, poate fi derivată, data membru i poate fi moştenită ca şi metoda
met(). De asemenea, data membru şi metoda pot fi accesate de date aflate în
acelaşi pachet.
class A
{ int i=2;
void met() {System.out.println(“Test”);}
};
Exemplul 7.63. Clasa test trebuie să se găsească în fişierul test.java (deoarece
este publică). Pentru ea nu se pot crea subclase (pentru că are modificatorul final).
Data membru i este statică, adică nu se regăseşte în fiecare obiect al clasei
respective, iar metoda este nestatică, deci se regăseşte în fiecare obiect al clasei
respective.
public final class test
{ static int i=2;
void met() {System.out.println("Test"); }
};
Capitolul 7. Programare orientată pe obiecte 295

În aceste condiţii, definiţia clasei de mai jos este eronată, chiar dacă se găseşte în
acelaşi pachet cu clasa test.
class B extends test {}

Exemplul 7.64. Fie clasele de mai jos:


class A
{ private int i=2;
void met() { System.out.println("Test"); }
void metp() { System.out.println(i); }
};
class B extends A
{ void met1() { System.out.println("Test1"); }
}

În aceste condiţii, dacă în clasa de mai jos, aflată în acelaşi pachet, se înlocuiesc
cele trei puncte cu instrucţiunile următoare, atunci:
public class test {
public static void main(String[] args) {
A x=new A();
... }
}
a) System.out.println(x.i); - avem eroare, deoarece i are modificatorul
private, deci nu poate fi accesat din afara clasei;
b) x.met(); - se afişează Test pentru că metoda nu este privată;
c) B y=new B(); y.met1(); - se afişează Test1;
d) B y=new B(); y.met(); - se afişează Test;
e) x.metp(); - se afişează 2. Deşi i este privat, el este afişat de met() care
are acces la datele private ale propriei clase.

Exemplul 7.65. Fie clasa de mai jos. Atunci:


class A
{ final int i=2;
final void met() {System.out.println("Test");}
void metp() { System.out.println(i);}
}

a) Clasa următoare, aflată în acelaşi pachet, este eronată pentru că data membru
i este cu modificatorul final, este deci considerată constantă şi prin urmare nu i
se poate modifica valoarea:
public class test {
public static void main(String[] args) {
A x=new A(); x.i=4; }
}
296 Manual de Informatică pentru clasa a XII-a

b) Clasa următoare, aflată în acelaşi pachet, este eronată pentru că extinde clasa
A şi redefineşte o metodă care conţine modificatorul final:
class B extends A
{ void met()
{ System.out.println("Test1"); }
}

c) Clasa următoare, aflată în acelaşi pachet, este corectă pentru că, deşi extinde
clasa A, redefineşte o metodă care nu are modificatorul final:
class B extends A
{ void metp()
{ System.out.println("Test2"); }
}

7.14. Excepţii (tratarea erorilor)


Prin excepţie vom înţelege o situaţie nedorită în care poate ajunge un
program în timpul rulării. Există nenumărate exemple de excepţii:
• se doreşte citirea unui număr natural, dar din greşeală, utilizatorul introduce
un caracter;
• datele introduse pentru diverse câmpuri nu sunt în plaja de valori admisă
pentru câmpul respectiv;
• un vector are n componente (indicii sunt de la 0 la n-1) şi se încearcă, de
exemplu, să se atribuie o valoare componentei de indice n;
• se încearcă deschiderea unui fişier inexistent;
• ...

Pentru a rezolva astfel de situaţii, în Java există un mecanism extrem de


bine pus la punct (mecanism de tratare a excepţiilor).

7.14.1. Mecanismul de tratare a excepţiilor

Pentru a prezenta acest mecanism vom porni de la un exemplu extrem de


simplu, atât de simplu încât ar putea fi tratat fără probleme şi în absenţa acestuia.

Exemplul 7.66. Să se citească şi să se afişeze un număr natural 1≤n≤5. Practic,


problema se reduce la citirea unui întreg şi afişarea lui. Dar, în timpul executării,
din greşeală, se poate introduce o valoare numerică care nu este între aceste
valori. Cum procedăm, altfel decât în mod clasic?
Capitolul 7. Programare orientată pe obiecte 297

Priviţi exemplul următor, în care dacă numărul citit este între 1 şi 5, acesta
este afişat, altfel se afişează mesajul 1<=n<=5:
class Eroare extends Exception
{ void afis()
{ System.out.println("1<=n<=5"); }
}
class t {
public static int citesc() throws Eroare
{ int n=Integer.parseInt(cin.linie());
if (n>=1 && n<=5) return n;
else throw new Eroare();
}
public static void main(String[] args) {
try
{ int numar=citesc();
System.out.println(numar);}
catch (Eroare er) {er.afis();}
}
}
a) Clasa Eroare extinde clasa Exception (este obligatoriu să fie precizată
această extensie. Ea conţine o singură metodă, void afis(), care are rolul de a
afişa mesajul de eroare.
b) La sfârşitul antetului metodei int citesc() se găseşte cuvântul cheie
throws, urmat de numele clasei care tratează eroarea respectivă. Prin aceasta se
anunţă că respectiva metodă poate întoarce fie un întreg (în caz de introducere
reuşită a datelor, fie o referinţă către un obiect al clasei Eroare (în caz de
introducere nereuşită a datelor). Iată deci, că în acest caz, metodele pot întoarce
şi date de alt tip decât cel dat de tipul metodei! Acest aspect este esenţial.
Instrucţiunea throw returnează referinţa către un obiect al clasei Eroare.
c) Utilizarea metodei citesc() se face, în mod obligatoriu, cu ajutorul
instrucţiunii try (încearcă). Secvenţa în care poate apărea excepţia, se găseşte în
instrucţiunea compusă subordonată lui try (în exemplu int numar=citesc()).
Dacă citirea reuşeşte, programul îşi încheie executarea, altfel, se verifică dacă
obiectul întors de metodă este de tip Eroare (vezi clauza catch). În caz afirmativ,
se execută metoda afis() a acestui obiect (er este referinţa către obiect).
În sinteză, putem afirma:
 clauza throws are rolul de a specifica faptul că o metodă poate întoarce şi
referinţe către obiectele altor clase (dacă extind clasa Exception). Dacă
sunt mai multe clase, atunci numele acestora sunt separate prin virgulă.
 instrucţiunea throw - returnează referinţa către unul din obiectele claselor
trecute după clauza throws.
 instrucţiunea try are forma generală (ceea ce este trecut între paranteze
drepte este facultativ):
298 Manual de Informatică pentru clasa a XII-a

try { secvenţa de instrucţiuni care pot conduce către excepţii }


catch (ER1 ob1) { secvenţa care tratează excepţia cu clasa Er1 }
[ catch (ER2 ob2) { secvenţa care tratează excepţia cu clasa Er2 }
catch (ER3 ob3) { secvenţa care tratează excepţia cu clasa Er2 }
...
catch (ERn obn) { secvenţa care tratează excepţia cu clasa Ern } ]
[ finally { secvenţa se execută indiferent dacă a fost eroare sau nu}]

Exemplul 7.67. Extindem, ce-i drept, în mod artificial exemplul anterior. Pentru
cele două excepţii (n<1 şi n>5) vom utiliza două metode diferite aflate în clase
diferite (Eroare1 şi Eroare2). În acest caz metodele sunt de tip constructor, deci
corpurile catch sunt vide.
class Eroare1 extends Exception
{ Eroare1() { System.out.println("1<=n");}
}
class Eroare2 extends Exception
{ Eroare2() { System.out.println("n<=5"); }
}
class t {
public static int citesc() throws Eroare1,Eroare2
{ int n=Integer.parseInt(cin.linie());
if (n<1) throw new Eroare1();
else
if (n>5) throw new Eroare2();
else return n;
}
public static void main(String[] args) {
try
{ int numar=citesc();
System.out.println(numar); }
catch (Eroare1 er1) {}
catch (Eroare2 er2) {}
}
}

⇒ Una dintre raţiunile existenţei unui mecanism de tratare a excepţiilor este


dată de faptul că, în anumite cazuri, excepţia poate fi tratată în mod
corespunzător, după care secvenţa se poate relua (fără ca programul să-şi
încheie executarea).

Exemplul 7.68. Revenim asupra exemplului dat, în care se citesc numere naturale
din intervalul [1,5]. Programul următor citeşte şi afişează un vector cu 3 astfel de
componente. În momentul în care s-a introdus un număr greşit citirea se reia.
Programul îşi încheie executarea atunci când au fost citite toate cele 3 componente
ale vectorului.
Capitolul 7. Programare orientată pe obiecte 299

class Eroare extends Exception


{ void afis()
{ System.out.println("1<=n<=5");
}
}
class e {
public static int citesc() throws Eroare
{ int n=Integer.parseInt(cin.linie());
if (n>=1 && n<=5) return n;
else throw new Eroare();
}
public static void main(String[] args) {
int[] V=new int[3];
for (int i=0;i<3;i++)
try { V[i]=citesc(); }
catch (Eroare er) { er.afis(); i--; }
System.out.println("Am citit");
for (int i=0;i<3;i++)
System.out.print(V[i]+" ");
}
}

⇒ Dacă clasa care tratează excepţia extinde clasa Exception, atunci este
obligatoriu ca apelul metodei ce poate returna o excepţie să se facă în
construcţia try, ca în exemplul anterior, sau metoda care apelează o astfel
de metodă să conţină în antet clauza throws.

Exemplul 7.69. Dacă în metoda main() de mai sus, am avea V[]=citesc(),


fără construcţia try, atunci am primi eroare de compilare.

Exemplul 7.70. citesc() poate fi apelată ca mai jos, unde metoda main()
conţine clauza throws. Oricum, în acest caz, dacă numărul nu este în intervalul
[1.5], excepţia este tratată printr-un mesaj implicit în care se precizează numele
clasei căreia îi aparţine obiectul returnat.
public static void main(String[] args) throws Eroare {
System.out.println(citesc()); }

Clasa Exception conţine (printre altele):

 un constructor implicit (fără parametru): Exception();


 un constructor cu parametru de tip String: Exception(String mes);
 o metodă care returnează mesajul mes, primit de constructor: String
getMessage().

Exemplul 7.71. În aceste condiţii, programul din exemplul 7.68 poate fi scris şi ca
mai jos (mai simplu):
300 Manual de Informatică pentru clasa a XII-a

class e {
public static int citesc() throws Exception
{ int n=Integer.parseInt(cin.linie());
if (n>=1 && n<=5) return n;
else throw new Exception("1<=n<=5");
}
public static void main(String[] args) {
int[] V=new int[3];
for (int i=0;i<3;i++)
try { V[i]=citesc();}
catch (Exception er)
{i--; System.out.println(er.getMessage()); }
System.out.println("Am citit");
for (int i=0;i<3;i++)
System.out.print(V[i]+" "); }
}

Uneori, este deranjant faptul că instrucţiunea capabilă să producă o excepţie


trebuie pusă automat sub try, iar clasa căreia îi aparţine trebuie să conţină clauza
throws. Mai mult, chiar în Java există metode care pot produce excepţii, dar care
pot fi folosite fără try. De exemplu, metoda parseInt a clasei Integer. Priviţi
programul următor, în care dacă şirul de caractere introdus poate fi convertit către
un întreg se afişează numărul, altfel programul se termină cu excepţie. Şi toate
acestea fără try...
class e {
public static void main(String[] args) {
int n=Integer.parseInt(cin.linie()); }
}

Să analizăm antetul complet al metodei parseInt:


public static int parseInt(String s)
throws NumberFormatException

Observăm că, în cazul în care apare o excepţie, se apelează la clasa


NumberFormatException. De aici, putem deduce o primă observaţie: dacă
dorim ca programul nostru să furnizeze un mesaj în caz de excepţie, putem
proceda ca mai jos, adică să folosim construcţia try, şi în caz că se returnează un
obiect al clasei NumberFormatException, să afişăm un mesaj de eroare lămuritor.
class e {
public static void main(String[] args) {
System.out.print("n="); int n=1;
try { n=Integer.parseInt(cin.linie());}
catch (NumberFormatException e)
{ System.out.println("Valoare nenumerica"); }
System.out.println(n);
}
}
Capitolul 7. Programare orientată pe obiecte 301

Mai mult, citirea se poate efectua până când valoarea introdusă este corectă, ca în
programul următor:
class e {
public static void main(String[] args) {
int i=1, n=1;
while (i==1)
{ System.out.print("n=");
try
{ n=Integer.parseInt(cin.Token()); i=0; }
catch (NumberFormatException e)
{ System.out.println ("Valoare nenumerica"); }
}
System.out.println(n);
}
}

 Dacă în secvenţa subordonată lui try se depistează o excepţie, se


abandonează executarea tuturor instrucţiunilor. În exemplu, aceasta implică
faptul că i rămâne 1, deci se reia secvenţa subordonată lui while. Dacă nu
a apărut excepţia, i devine 0 şi prin urmare, executarea lui while este
considerată încheiată.

 Dacă nu l-am fi declarat de la început pe n cu valoare iniţială, oricare ar fi


ea, programul ar fi semnalat eroare la compilare, pentru că se ajunge la
afişarea lui. Ori, în Java, nu este permisă afişarea conţinutului unei variabile
neiniţializate.

Totuşi, nu se rezolvă problema pusă: cum este posibil ca parseInt să


poată fi folosită fără construcţia try?

Obiectele claselor care extind clasa RuntimeException sau Error pot fi


apelate fără ca antetul lor să conţină clauza throws, ca mai jos:

class Eroare extends RuntimeException


{ void afis()
{ System.out.println("1<=n<=5");}
}
class e {
public static int citesc() // fara throws
{ int n=Integer.parseInt(cin.linie());
if (n>=1 && n<=5) return n;
else throw new Eroare();
}
public static void main(String[] args) {
...
}
}

Pot exista următoarele cazuri:


302 Manual de Informatică pentru clasa a XII-a

a) Dacă în main() avem secvenţa de mai jos, atunci distingem două cazuri:
int numar=citesc();
a1) Se introduce un număr între 1 şi 5 - programul nu generează excepţie şi
totul este OK!
a2) Se introduce un număr în afara intervalului. Va fi afişată o excepţie într-un
format implicit şi nu se va afişa mesajul "1<=n<=5".
b) Dacă în main() avem secvenţa:
try
{ int numar=citesc();
System.out.println(numar); }
catch (Eroare er) { er.afis(); }

b1) Se introduce un număr între 1 şi 5 - programul nu generează excepţie şi


totul este OK!
b2) Se introduce un număr în afara intervalului. Va fi afişată excepţia cu
mesajul "1<=n<=5".

7.14.2. Metodele care pot returna, în caz de excepţii, obiecte


ale unor alte clase

Priviţi antetul metodei parseInt a clasei Integer. Din considerente


didactice, până acum antetul nu a fost prezentat integral. În cazul în care se
întâlneşte o excepţie, se returnează un obiect al clasei NumberFormatException:
public static int parseInt(String s)
throws NumberFormatException
Exemplul 7.72. Aceasta poate ajuta programatorul să “gestioneze” situaţia, ca în
exemplul de mai jos, unde se citeşte o variabilă întreagă care este afişată. În cazul
în care valoarea introdusă nu este corectă, se reia citirea.
class e {
public static void main(String[] args) {
int i=0;
while (i==0)
try
{ int numar=Integer.parseInt(cin.Token());
System.out.println(numar);
i=1; }
catch (NumberFormatException e)
{ System.out.println("Numar eronat"); }
}
}
Capitolul 7. Programare orientată pe obiecte 303

Iată şi antetul complet al metodelor parseFloat şi parseDouble:


1. public static double parseDouble(String s)
throws NumberFormatException
2. public static float parseFloat(String s)
throws NumberFormatException

⇒ În cazul împărţirii la 0 pentru tipuri întregi, se returnează un obiect al clasei


ArithmeticException.

Exemplul 7.73. Vedeţi codul de mai jos:


class t {
public static void main(String[] args) {
System.out.print("n=");
int n=Integer.parseInt(cin.Token());
System.out.print("m=");
int m=Integer.parseInt(cin.Token());
try { System.out.println(n/m); }
catch (ArithmeticException e)
{ System.out.println ("Impartire la 0 "); }
}
}

⇒ În cazul în care se încearcă să se atribuie o valoare unei componente


inexistente a unui vector, se returnează pentru tipuri întregi un obiect al
clasei ArrayIndexOutOfBoundsException.

Exemplul 7.74. Vedeţi codul de mai jos:


class t {
public static void main(String[] args) {
int []v=new int[3];
System.out.print("indice=");
int indice=Integer.parseInt(cin.Token());
try { v[indice]=1; }
catch (ArrayIndexOutOfBoundsException e)
{ System.out.println ("Eroare indice"); }
}
}

Observaţie foarte importantă ! Clasele ArrayIndexOutOfBoundsException,


ArithmeticException ca şi multe altele de acest tip, sunt rezultate în urma
unor derivări ale clasei Exception. Cum un parametru de tip referinţă către un
obiect al superclasei poate reţine referinţe către obiectele subclaselor sale, atunci
putem scrie clauza catch de forma:
catch (Exception e) {...}
304 Manual de Informatică pentru clasa a XII-a

7.14.3. Exemple de tratare a excepţiilor

Exemplul 7.75. Validare pentru numere reale. Să se scrie un program care


citeşte n, număr natural şi n numere reale. Se cere să se calculeze suma
numerelor citite. Dacă un număr real se introduce greşit (nu respectă formatul de
număr real) se reia citirea lui.
Metoda parseDouble, a clasei Double, returnează fie un număr de format
double, fie un obiect al clasei NumberFormatException.
class e {
public static void main(String[] args) {
double s=0;
System.out.print("n=");
int n=Integer.parseInt(cin.linie());
for (int i=0;i<n;i++)
try { double x=Double.parseDouble(cin.linie());s+=x; }
catch (NumberFormatException e)
{ System.out.println("Numar eronat");i--; }
System.out.println("S="+s);
}
}
Exemplul 7.76. Validare alfabetică. Se citeşte un şir de caractere alcătuit din mai
multe cuvinte separate prin blank-uri. Dacă şirul citit conţine numai literele
alfabetului (mici sau mari) sau blank-uri, acesta se va afişa, altfel se va tipări
mesajul sir nealfabetic.
Metoda citSir() citeşte şirul şi îl validează. Dacă şirul este valid, el este
returnat, altfel se returnează un obiect al clasei Nealfabetic. În main() se
testează dacă a fost returnat şirul (try), caz în care acesta este afişat, sau a fost
returnat un obiect al clasei Nealfabetic, caz în care se afişează mesajul de
eroare sir nealfabetic prin utilizarea metodei mesaj() a obiectului.
class Nealfabetic extends RuntimeException {
String mesaj()
{ return "sir nealfabetic"; }
}
class e {
static String citSir()
{ String sir=new String(cin.linie());
boolean gasit=false;
for (int i=0;i<sir.length();i++)
if ( (sir.charAt(i)<'A' || sir.charAt(i)>'Z') &&
(sir.charAt(i)<'a' || sir.charAt(i)>'z') &&
sir.charAt(i)!=' ') gasit=true;
if (gasit) throw new Nealfabetic();
else return sir;
}
Capitolul 7. Programare orientată pe obiecte 305

public static void main(String[] args) {


boolean corect=false;
System.out.print("Tastati sirul ");
String s="";
try { s=citSir(); System.out.println(s); }
catch (Nealfabetic e) { System.out.println(e.mesaj()); }
}
}

Exerciţiile 1. şi 2. se referă la clasa de mai jos, care se găseşte deja compilată în


directorul bin:
class a {
int a=1;
int a()
{ int a=2;
return a; }
}

1. Care dintre programele de mai jos este corect din punct de vedere sintactic?

a) b)
class ex { class ex {
public static void public static void
main(String[] args) { main(String[] args) {
a a=new a(); } a x=new a; }
} }

c) d)
class ex { class ex {
public static void public static void
main(String[] args) { main(String[] args) {
x a=new a(); } a x=new (); }
} }

2. Fiind dată x, o variabilă care reţine o referinţă către un obiect al clasei a, care
dintre instrucţiunile de mai jos afişează valoarea 2?

a) System.out.println(x.a);
b) System.out.println(x.a.a);
c) System.out.println(x.a());
d) Nici una dintre instrucţiunile de mai sus nu afişează valoarea 2.
306 Manual de Informatică pentru clasa a XII-a

3. Fiind dată clasa de mai jos, ce afişează instrucţiunea aflată în main():


A.M(3.5)?
class A {
static void M(int x) {System.out.println(1);}
static void M(float x) {System.out.println(2);}
static void M(double x) {System.out.println(3);}
static void M(char x) {System.out.println(4);}
}
a) 1; b) 2; c) 3; d) 4.

4. Ce afişează programul următor?


class A {
int a,b;
A(int a, int b)
{ this.a=a;
this.b=b; }
A (int x) {b=x;}
void Afis() {System.out.print (a+" "+b);}
}
class ex {
public static void main(String[] args) {
A x=new A(3);
x.Afis(); }
}
a) Eroare; b) 3 0; c) 0 0; d) 0 3.

5. Creaţi o clasă numită Lista, care operează cu liste liniare simplu înlănţuite. Un
element al listei liniare simplu înlănţuite este descris de clasa Nod:
class Nod
{ Nod adr_urm;
int nr; }
Clasa Lista va conţine:
 Data membru v - adresa primului nod al listei. În cazul în care lista este nulă,
v reţine null.
 Metoda void adaug (int nr) - adaugă la sfârşitul listei un nod care va
reţine valoarea numerică nr, primită de metodă ca parametru.
 Metoda void afis() - care afişează valorile reţinute de noduri.

6. Adăugaţi clasei Lista o metodă void stergP() care permite ştergerea


primului nod introdus.
7. Adăugaţi clasei Lista o metodă void stergU() care permite ştergerea
ultimului nod introdus.
Capitolul 7. Programare orientată pe obiecte 307

8. Adăugaţi clasei Lista o metodă void adaugI(int nr) care permite ca la


începutul listei să se adauge un nod care să conţină valoarea nr, primită de
metodă ca parametru.
9. Scrieţi un program care creează o listă liniară simplu înlănţuită. Programul va
utiliza clasa Lista, creată anterior. Numerele se citesc de la tastatură şi se vor
găsi în listă în ordinea în care au fost introduse. Şirul de numere se consideră
încheiat atunci când se citeşte numărul 0 (acesta nu este introdus în listă).
10. Realizaţi o clasă numită Stiva, care operează cu stive alocate ca liste liniare
simplu înlănţuite. Un element al listei este descris de clasa Nod:
class Nod
{ Nod adr_prec;
int nr; }
Clasa Stiva va conţine următoarele:
 Data membru varf - reţine adresa ultimului nod introdus în stivă.
 Metoda void push(int nr) - adaugă un nod stivei şi acesta va reţine
valoarea numerică nr, primită de metodă ca parametru.
 Metoda int pop() - extrage un nod din stivă şi returnează valoarea pe care
acesta o reţinea. Dacă stiva este vidă, returnează -1.

11. Scrieţi un program care să citească 0<a<b, numere naturale şi să afişeze un


număr aleator în intervalul [a,b].
12. Scrieţi un program care citeşte x, număr real, şi n>0, număr natural şi
calculează P=sin(x)*sin(2x)*...sin(n*x). Se presupune că x reprezintă o
valoare exprimată în radiani.
13. Se citeşte de la tastatură un şir de caractere. Şirul conţine cel puţin 10
caractere. Se cere să se afişeze numai primele 10 caractere din şir.
14. Se citeşte de la tastatură un şir de caractere. Dacă şirul are mai mult de 4
caractere să se afişeze numai primele 4, altfel se va afişa şirul citit.
15. Scrieţi o clasă, numită Afis, care conţine metoda String aNum(int
lung, String s) metodă ce are rolul de a întoarce şirul reţinut de s, pe
lungimea lung. Dacă numărul de caractere ale şirului este mai mare decât lung,
se întoarce subşirul format din primele lung caractere ale şirului, altfel se întoarce
un şir pe lungimea lung, şir alcătuit din caracterele şirului iniţial la care se adaugă
un număr corespunzător de blank-uri. Exemple pentru lung=5:
 Şirul: “Mihai” - se returnează “Mihai”.
 Şirul: “tastatura” - se returnează “tasta”.
 Şirul: “aer” - se returnează “aer ”.
Observaţie ! O astfel de metodă este utilă pentru afişarea unui şir de caractere pe
o anumită lungime.
308 Manual de Informatică pentru clasa a XII-a

16. Scrieţi un program care citeşte n, număr natural şi n şiruri de caractere.


Programul va afişa pe câte o linie, primele 5 caractere ale fiecărui şir citit. Dacă
şirul are mai puţin de 5 caractere, se va afişa şirul, urmat de un număr de blank-uri
astfel încât lungimea totală afişată să fie de 5 caractere.
17. Adăugaţi clasei Afis metoda String num(int lung, int v) care
are rolul de a returna şirul de lungime lung, alcătuit din şirul obţinut din convertirea
întregului v în şir şi în cazul în care acest şir are lungimea mai mică decât lung, el
va fi precedat de un număr corespunzător de blank-uri. În situaţia în care lungimea
şirului obţinut din conversia numărului este mai mare decât lung, metoda va
returna un mesaj de eroare. Exemple pentru lung=3:
 Numărul 125 - se returnează “125”.
 Numărul 1 - se returnează “ 1”.
 Şirul: “3152” - se returnează "Numarul nu poate fi afisat";
18. Scrieţi un program care citeşte n, număr natural şi n numere naturale.
Programul va afişa, pe câte o linie, fiecare dintre cele n numere naturale citite.
Numerele se vor afişa pe 5 caractere şi vor fi aliniate la dreapta.
Exemplu: n=3, numerele citite sunt: 12234, 45, 4. Se va afişa:
12234
45
4
Observaţie ! În practică, şirurile alcătuite din caractere se afişează aliniate la
stânga, iar valorile numerice se afişează aliniate la dreapta.
19. Adăugaţi clasei Afis metoda String num(int lung, int zec,
double v) care returnează şirul rezultat din conversia unui număr real (indiferent
de numărul de zecimale). Şirul are lungimea lung, numărul este afişat aliniat la
dreapta şi va avea zec zecimale. În ipoteza în care numărul nu poate fi afişat prin
utilizarea a lung caractere, se va returna un mesaj de eroare.
 Num(5,2,23.3456) returnează “23.34”;
 Num(5,2,3.3456) returnează “ 3.34”;
 Num(5,2,-9) returnează “-9.00”;
 Num(5,2,123) returnează “Numarul nu poate fi afisat”.
20. Scrieţi un program care citeşte n, număr natural şi n numere reale. Programul
va afişa pe câte o linie fiecare număr citit. Numerele se vor afişa pe 8 caractere,
vor fi aliniate la dreapta şi vor avea obligatoriu două zecimale (indiferent de
numărul de zecimale pe care îl au).
21. Să se extindă clasa cin. Noua clasă se va numi Cit şi va conţine metodele:
static int Intreg() // citeşte şi returnează un număr întreg;
static double Real() // citeşte şi returnează un număr real;
static char Caracter() // citeşte şi returnează un caracter;
static String Sir() // citeşte şi returnează un şir de caractere.
Capitolul 7. Programare orientată pe obiecte 309

22. Utilizaţi noua clasă într-un program care citeşte şi afişează un număr întreg,
unul real şi un caracter.
23. Fiind dată clasa de mai jos (Baza), scrieţi o clasă (Lista) care creează o
listă liniară simplu înlănţuită în care elementele sunt obiectele clasei Baza.
Evident, elementele acestei liste nu au nici o altă informaţie, în afara celei de
adresă.
class Baza { Baza adr_urm; }
Lista va conţine:
• Baza v; - data membru; reţine vârful listei;
• Baza varf() - returnează vârful listei liniare (adresa primului element);
• void adaug (Baza Nod) - adaugă la sfârşitul listei un element.
24. Creaţi clasa Int, care să extindă clasa Baza şi să conţină în plus:
• int val; - dată membru;
• Int (int val) - constructor;
• int valoare() - returnează valoarea reţinută de val.
25. Scrieţi un program care creează o listă liniară simplu înlănţuită cu n elemente
(n citit de la tastatură) de tip Int. Valorile reţinute de obiectele de tip Int sunt, de
asemenea, citite de la tastatură. Lista va fi construită cu ajutorul clasei Lista.
26. Scrieţi un program care creează o listă liniară simplu înlănţuită cu n elemente
(n citit de la tastatură) de tip String. Şirurile de caractere reţinute de obiectele de
tip Sir sunt, de asemenea, citite de la tastatură. Lista va fi construită cu ajutorul
clasei Lista.

Testele de la 27 la 30 se referă la clasele următoare. De fiecare dată,


instrucţiunea (sau setul de instrucţiuni) la care se referă întrebarea va fi scrisă în
locul liniei lipsă (punctată):
class A
{ int x=1;
void met() {System.out.println("Clasa A");}
}
class B extends A
{ int x=2;
void met() {System.out.println("Clasa B");}
}
class C extends B
{ int x=3;
void met() {System.out.println("Clasa C");}
}
public class test {
public static void main(String[] args) {
...
}
}
310 Manual de Informatică pentru clasa a XII-a

27. Ce se afişează în urma executării secvenţei: A x=new B();x.met(); ?


a) Clasa A; b) Clasa B; c) Clasa C; d) EROARE.
28. Ce se tipăreşte în urma executării secvenţei:
A x=new B(); System.out.println(x.x); ?
a) 1; b) 2; c) 3; d) EROARE.
29. Ce se afişează în urma executării secvenţei de mai jos?
B x=(A)new B(); x.met();
a) Clasa A; b) Clasa B; c) Clasa C; d) EROARE.

30. Ce se tipăreşte în urma executării secvenţei: B x=new C(); x.met(); ?


a) Clasa A; b) Clasa B; c) Clasa C; d) EROARE.
31. Utilizând polimorfismul, scrieţi un program care citeşte un număr natural n şi
dacă este prim, afişaţi succesorul său în mulţimea numerelor prime, dacă este
impar (fără a fi prim) afişaţi succesorul său în mulţimea numerelor impare, iar dacă
este par, afişaţi succesorul său în mulţimea numerelor pare. Exemple: n=7 se
afişează 11; n=21 se afişează 23; n=8 se afişează 10.
32. Se citesc n, număr natural şi n numere reale. Se cere să se afişeze suma
numerelor citite. Pentru citirea numerelor, programul va utiliza mecanismul
excepţiilor (în caz de introducere greşită a datelor - care nu corespund formatului de
număr real, se va afişa un mesaj corespunzător şi se va relua citirea numerelor).
33. La fel ca mai sus numai că cele n numere citite trebuie să fie mai mici decât
10. De asemenea, se va folosi mecanismul excepţiilor atât pentru formatul real, cât
şi pentru valorile admise.
34. Scrieţi un program care citeşte două numere reale a şi b şi afişează rezultatul
împărţirii lui a la b. Dacă ambele numere sunt 0, se va afişa un mesaj lămuritor,
dacă numai b este 0, se va tipări alt mesaj lămuritor, iar dacă împărţirea se poate
face, se va afişa rezultatul împărţirii. Evident, programul va utiliza mecanismul
excepţiilor şi metode ale claselor înfăşurătoare (de revăzut!).
35. La fel ca mai sus numai că se vor utiliza excepţiile şi la citirea numerelor a şi b,
iar în caz că împărţirea nu se poate efectua se va repeta citirea numerelor a şi b.

(pentru verificare, rezolvările se găsesc la pag. 384)


CAPITOLUL
Programare vizuală

Prin studierea acestui capitol vom învăţa să scriem propriile programe utilizând
programarea vizuală. Astăzi, activitatea de programare este de neconceput în
absenţa ei. De asemenea, studiul acestui capitol reprezintă o excelentă
recapitulare a OOP. Vă veţi da seama că, în absenţa OOP, este
foarte greu să realizezi un astfel de program. Pentru toate
programele pe care le realizaţi, nu uitaţi să proiectaţi
interfeţe frumoase şi uşor de înţeles pentru utilizatori.

 Concepte de bază ale programării vizuale în Java

 Studiul principalelor componente

 Obiecte grafice. Clasa Graphics

 Accesarea şi prelucrarea datelor

Cuvinte cheie: fereastră, container, componentă, poziţionare,


gestionare, meniu, accelerator, cutie de dialog, culoare,
bară de unelte, imagine, date, flux, JDBC
312 Manual de Informatică pentru clasa a XII-a

8.1. Conceptele de bază ale programării vizuale în Java

Pentru a înţelege conceptele care stau la baza programării vizuale vom porni
de la un exemplu arhicunoscut în programarea clasică.

Exemplul 8.1. “Rezolvarea ecuaţiei de gradul 2“. Am putut observa, atunci când
am rezolvat în mod clasic problema, că programul obţinut este cât se poate de
“neprietenos” si inestetic. În plus, un program clasic îndepărtează un eventual
utilizator neinformatician al programului. Acesta are impresia că are nevoie de
multe cunoştinţe pentru utilizarea programului.

Figura 3.1. Interfaţa grafică cu utilizatorul şi cutia de dialog cu rezultatele

Rulaţi programul următor şi testaţi-l! În primul rând veţi observa că interfaţa


cu utilizatorul este una prietenoasă. Este evident pentru oricine că trebuie
introduşi coeficienţii şi că, pentru a obţine rezultatul, trebuie “apăsat” butonul
“Rezultat“. În fapt, interfaţa grafică cu utilizatorul este, dacă vreţi, “ambalajul”
programului, pentru că acesta conţine, ascuns, algoritmul clasic de rezolvare.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Fer extends JFrame implements ActionListener
{ JTextField a,b,c,r; JButton but;
public Fer(String titlu) {
super(titlu);
setSize(210,200); setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
//a
x.setLayout(new FlowLayout ());
JLabel et1=new JLabel ("a="); x.add(et1);
a=new JTextField(15); x.add(a);
//b
JLabel et2=new JLabel ("b="); x.add(et2);
b=new JTextField(15); x.add(b);
Capitolul 8. Programare vizuală 313

//c
JLabel et3=new JLabel ("c="); x.add(et3);
c=new JTextField(15); x.add(c);
//butonul
but=new JButton("Rezultat"); x.add(but);
but.addActionListener(this);
setVisible(true);
}
public void actionPerformed (ActionEvent e)
{ double aR=0,bR=0,cR=0, er=0;
try // incerc sa-l citesc pe A
{ aR=Double.parseDouble(a.getText()); }
catch (NumberFormatException exc)
{ er=1;
JOptionPane.showMessageDialog(this,
"a este introdus gresit");
}
try // incerc sa-l citesc pe B
{ bR=Double.parseDouble(b.getText()); }
catch (NumberFormatException exc)
{ er=1;
JOptionPane.showMessageDialog(this,
"b este introdus gresit");
}
try // incerc sa-l citesc pe c
{ cR=Double.parseDouble(c.getText()); }
catch (NumberFormatException exc)
{ er=1;
JOptionPane.showMessageDialog(this,
"c este introdus gresit");
}
if (er==0)// daca a b c sunt corecte rezolvarea ecuatiei
if (aR!=0)
if (bR*bR-4*aR*cR<0)
JOptionPane.showMessageDialog(this,
"Nu are solutii reale");
else
JOptionPane.showMessageDialog(this,
"x1="+(-bR+Math.sqrt(bR*bR-4*aR*cR))/(2*aR)+"\n"+
"x2="+(-bR-Math.sqrt(bR*bR-4*aR*cR))/(2*aR));
else
if(bR!=0)
JOptionPane.showMessageDialog(this, "x1="+-cR/bR);
else
if(cR!=0)
JOptionPane.showMessageDialog(this, "NU are solutii");
else JOptionPane.showMessageDialog(this,
"Infinitate de solutii");
}
}
314 Manual de Informatică pentru clasa a XII-a

public class baza {


public static void main(String args[]) {
Fer fp=new Fer("Ecuatia de gradul 2");
}
}

La baza programării vizuale stă noţiunea de fereastră. Fereastra va conţine


mai multe componente vizuale cum ar fi edit-uri, butoane, imagini, etc. Asupra lor
utilizatorul poate acţioana cu mouse-ul sau prin intermediul tastaturii. În programul
nostru, fereastra iniţială afişează trei etichete a=0, b=0, c=0 şi trei edit-uri care
permit introducerea coeficienţilor a, b, c.

Unele componente trebuie să răspundă unor evenimente. Un exemplu de


eveniment este, executarea unui clic cu mouse-ul asupra unei componente. În
programul nostru, executarea unui clic asupra butonului ”Rezultat” lansează o
metodă, numită actionPerformed, care validează datele de intrare (verifică
corectitudinea lor). În caz că acestea sunt valide (corecte), calculează rădăcinile
ecuaţiei, altfel afişează mesaje de informare. Afişarea mesajelor de eroare şi a
rezultatelor se face cu ajutorul unor cutii de dialog de informare.

O fereastră şi, în general, orice componentă este un obiect al unei clase.


Pentru a putea realiza un program care utilizează programarea vizuală, trebuie să
putem răspunde întrebărilor următoare:

1. Cum putem stabili caracteristicile ferestrei?


2. Care este mecanismul prin care unei ferestre i se ataşează alte componente?
3. Care este mecanismul prin care componentele răspund evenimentelor?
4. Cum se stabileşte modul în care arată o componentă?
5. Cum putem scrie un program care să ruleze independent de rezoluţia
monitorului?
6. Care este mecanismul prin care poziţionăm diversele componente în cadrul
ferestrei?

La toate aceste întrebări vom răspunde în acest paragraf !

8.1.1. Prima fereastră

O fereastră este un obiect al clasei JFrame. Clasa


JFrame este reţinută în pachetul javax.swing.

Exemplul 8.2. În continuare, puteţi observa un program


care afişează o fereastră:

Figura 8.2.
Exemplu de fereastră
Capitolul 8. Programare vizuală 315

import javax.swing.*;
public class pv {
public static void main(String args[])
{
JFrame fer=new JFrame("Prima mea fereastra");
fer.setSize(200,300);
fer.setLocation(300,400);
fer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fer.setVisible(true);
}
}

Să observăm că fereastra conţine meniul implicit, poate fi maximizată,


minimizată (adusă pe bara de task-uri), dar poate fi şi închisă.

Din analiza programului, deducem câteva metode pe care le are clasa


JFrame:

⇒ JFrame() - constructor. Dacă o fereastră este creată printr-un astfel de


constructor ea apare fără titlu.

⇒ JFrame(String titlu) - constructor. Construieşte o fereastră care


afişează un anumit titlu (în exemplu, Prima mea fereastra).

⇒ void setSize(int width, int height) - stabileşte lăţimea şi


înălţimea ferestrei.

⇒ void setLocation (int x, int y) - stabileşte poziţia unde va fi


afişat colţul din stânga sus al ferestrei (şi implicit poziţia ferestrei), în raport
cu colţul din stânga sus al ecranului. Parametrul x precizează distanţa pe
orizontală a colţului ferestrei, iar y distanţa pe verticală a acestuia (ambele
sunt date în pixeli).

⇒ void setDefaultCloseOperation(int a) - stabileşte ce se întâmplă


atunci când se închide fereastra (s-a păstrat acel buton x). Parametrii sunt
constante de tip întreg ale clasei. Cea mai importantă constantă este
EXIT_ON_CLOSE şi prin ea, se cere închiderea ferestrei şi încheierea
executării programului.

⇒ void setResizable(boolean ac) - dacă parametrul este false nu


se pot modifica dimensiunile ferestrei.

⇒ setVisible(boolean x) - stabileşte dacă fereastra este vizibilă (apare


pe ecran) sau nu (deşi există, nu este afişată).

În programul care rezolvă ecuaţia de gradul de 2, fereastra este un obiect al


clasei Fer. Analizaţi cum am descris modul în care trebuie să arate fereastra.
316 Manual de Informatică pentru clasa a XII-a

8.1.2. Mecanismul prin care se ataşează componente ferestrei.


Clasa Container

Foarte important ! Pentru ca unei ferestre (obiect de tip JFrame) să i se poată


ataşa alte componente (cum ar fi butoanele, liste, etc. – care sunt obiecte de alte
tipuri), este necesar ca aceasta să conţină o referinţă către o structură specială,
care la rândul ei va reţine referinţe către obiectele (componentele) care sunt
ataşate ferestrei. Structura care reţine referinţele către obiectele care se află pe
fereastră este un obiect al clasei Container.

Alăturat putem observa ierarhia Object


claselor din care a rezultat clasa Component
JFrame. Prin urmare, un obiect Container
de tip JFrame sau dintr-o Window
subclasă a lui JFrame conţine java.awt.Frame
javax.swing.JFrame
datele membru şi metodele
clasei Container.

Accesul la container-ul unei ferestre se face utilizând o metodă a clasei


JFrame, numită getContentPane().
⇒ Container getContentPane() - returnează o referinţă către
container-ul ferestrei. Pornind de la această referinţă, putem realiza două
lucruri:
1. Putem adăuga ferestrei componentele dorite. Pentru aceasta se foloseşte
metoda add() a clasei Container:

 Component add(Component comp) - adaugă o componentă ferestrei.


Important: toate componentele sunt derivate din clasa Component. Prin
urmare, parametrul comp poate reţine referinţe către componente de orice tip.
2. Putem spune cum să fie aranjate în fereastră componentele adăugate.
Important: Mecanismul din Java care rezolvă această problemă presupune
existenţa unor aşa numiţi gestionari de poziţionare. Gestionarii de poziţionare
sunt obiecte ale unor clase specifice. Ei aranjează automat componentele unui
container. Pentru a ataşa unui container un gestionar de poziţionare, se
utilizează metoda clasei Container numită setLayout():

 void setLayout(LayoutManager gest) - ataşează unui container


un gestionar de poziţionare. LayoutManager - este o interfaţă. Toţi
gestionarii de poziţionare pe care îi vom studia într-un paragraf separat au
rezultat ca urmare a implementării acestei interfeţe. Aceasta înseamnă că
metoda poate fi utilizată pentru ataşarea oricărui gestionar de poziţionare.
Observaţie ! Pentru început, vom folosi gestionarul de poziţionare FlowLayout, care
are un constructor fără parametri. Pe scurt, acesta aşează componentele în
fereastră, pe linie, una după alta. Dacă o linie s-a umplut, se trece la linia următoare.
Capitolul 8. Programare vizuală 317

 Clasa Container se găseşte în pachetul java.awt.

Exemplul 8.3. Programul care urmează afişează


două butoane! Apăsarea butoanelor nu are nici un
efect.
import java.awt.*;
import javax.swing.*;
class Fer extends JFrame
{ public Fer(String titlu) { Figura 8.3. Fereastră
super(titlu); cu două butoane
setSize(200,100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
x.setLayout(new FlowLayout ());
JButton A=new JButton("Buton 1"); x.add(A);
JButton B=new JButton("Buton 2"); x.add(B);
setVisible(true); }
}
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Doua butoane"); }
}

Observaţie ! Butoanele ataşate sunt componente de tip JButton, care au un


constructor de tip JButton(String s). Şirul s va apărea pe suprafaţa butonului.
Exerciţiu ! Analizaţi, în programul care rezolvă ecuaţia de gradul 2, modul în care
am ataşat ferestrei principale componentele vizuale (etichetele, edit-urile şi butonul).

8.1.3. Un mecanism prin care butoanele răspund


evenimentului de “apăsare”

Până în prezent ştim să construim o fereastră, ştim să-i ataşăm unul sau mai
multe butoane, dar nu ştim să facem de aşa manieră încât la “apăsarea” butonului
(click pe suprafaţa lui) să aibă loc o anumită acţiune. Este exact ce ne propunem
să prezentăm în acest paragraf.

În Java există o interfaţă numită ActionListener, “ascultătorul de


evenimente“ de tip ActionEvent. Un exemplu de eveniment de tip ActionEvent
este “apăsarea” unui buton. Interfaţa conţine antetul unei singure metode:
actionPerformed(ActionEvent e).

Pentru ca o componentă să poată răspunde la un eveniment de tipul


ActionEvent, trebuie să implementeze clasa ActionListener. Aceasta
înseamnă că:
1. Clasa care include componenta (fereastra) trebuie să conţină clauza
implements ActionListener.
318 Manual de Informatică pentru clasa a XII-a

2. Să fie implementată metoda actionPerformed(). Această metodă se va


executa automat atunci când este apăsat butonul. Prin urmare, implementarea ei
va scrie codul necesar acţiunii dorite.

ActionEvent este o clasă care conţine metoda:

 String getActionCommand() - returnează şirul de caractere asociat


componentei care a transmis evenimentul. Metoda poate fi utilizată pentru a
depista componenta care a transmis evenimentul.

Exemplul 8.4. Extindem programul prezentat în paragraful anterior. Când se


apasă un buton, în fereastra CMD va apărea şirul reţinut de butonul apăsat:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Fer extends JFrame implements ActionListener
{
public Fer(String titlu) {
super(titlu);
setSize(200,100);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
x.setLayout(new FlowLayout ());
JButton A=new JButton("Buton 1");
x.add(A);
JButton B=new JButton("Buton 2");
x.add(B);
A.addActionListener(this);
B.addActionListener(this);
setVisible(true);
}
public void actionPerformed (ActionEvent e)
{ if( e.getActionCommand().compareTo("Buton 1")==0)
System.out.println("Ai apasat Buton 1");
else System.out.println("Ai apasat Buton 2");
}
}

public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Doua butoane"); }
}

Exerciţiu ! Analizaţi, în programul care rezolvă ecuaţia de gradul 2, modul în care


s-a implementat metoda actionPerformed(). Veţi observa modul de citire a
coeficienţilor. Aceştia sunt introduşi sub forma unor şiruri de caractere, se preiau
din edit-uri şi se încearcă convertirea lor către un tip real. În cazul în care conversia
reuşeşte, se presupune că au fost introduşi corect. Altfel, se va da mesaj de
eroare. Atenţie ! Validarea datelor de intrare este esenţială.
Capitolul 8. Programare vizuală 319

8.1.4. Componente: elemente de design

Prin componentă vom înţelege un obiect care are o reprezentare grafică.


Exemple de componente: butoane, liste, edit-uri, etichete (am preferat denumirea
lor din cursul de Tehnologia Informaţiei). Dacă o componentă este obiect,
înseamnă că o componentă rezultă în urma instanţierii unei clase. Fiecare tip de
componentă pe care o vom studia rezultă în urma instanţierii unei clase specifice
ei. De exemplu, un buton rezultă în urma instanţierii clasei JButton, o etichetă
rezultă în urma instanţierii clasei JLabel, un edit rezultă în urma instanţierii clasei
JtextField, ş.a.m.d.

Important ! Clasele tuturor componentelor enumerate mai sus sunt subclase ale
clasei JComponent. Aceasta înseamnă că putem folosi metodele clasei
JComponent pentru orice componentă.

Observaţie ! Clasa JComponent este descendentă, dar nu direct, a unei alte clase
numită Component. Atunci când prezentăm unele metode ale clasei JComponent,
care sunt moştenite de la clasa Component nu vom mai face referire la acest lucru,
ci le vom trata ca făcând parte din clasa JComponent.

În continuare, prezentăm câteva metode ale clasei JComponent:

⇒ void setBackground(Color c) - metoda stabileşte culoarea de fond


a componentei. Să observăm că parametrul ei este de tip Color.
⇒ void setForeground(Color c) - setează culoarea caracterelor (în
cazul în care componenta conţine un text).

Clasa Color conţine anumite constante care indică culoarea şi mai multe
metode prin care se poate stabili o culoare. Exemple de constante de
culoare: black, red, white, yellow, etc. De asemenea, clasa conţine
constructorul Color(float r, float g, float b) prin care se poate
forma o culoare în sistemul RGB(Red, Green, Blue), sistem studiat la
tehnologia informaţiei.

⇒ setFont(Font f) setează font-ul cu care se scrie, stilul său şi mărimea.


Parametrul este un obiect al clasei Font.
Clasa Font are, printre altele, constructorul:
Font(String nume, int stil, int marime).
unde:
nume - este numele font-ului;
stil - stilul. Valorile uzuale sunt: Font.ITALIC (italic), Font.BOLD
(bold), Font.PLAIN (clasic). Se pot folosi şi sume, cum ar fi pentru italic
şi bold: Font.ITALIC+Font.BOLD.
marime - mărimea font-ului.
320 Manual de Informatică pentru clasa a XII-a

Exemplul 8.5. Butonul (“Apasa”) va avea fondul de culoare roşie, va conţine text
scris cu verde, se va utiliza font-ul Arial, de mărime 20 şi este scris înclinat şi
îngroşat (italic şi bold). Să observăm faptul că dimensiunea butonului este stabilită
automat, în funcţie de mărimea textului pe care îl conţine.
JButton A=new JButton("Apasa");
A.setBackground(Color.red);
A.setFont(new Font("Arial",Font.ITALIC+Font.BOLD, 20));
A.setForeground(Color.GREEN);

⇒ void setToolTipText(String text); - metoda setează un şir de


caractere care va fi afişat atunci când cursorul mouse-ului staţionează
asupra componentei. Şirul are rolul unui mesaj lămuritor despre funcţia
respectivei componente.

Exemplul 8.6. Priviţi liniile de cod de mai jos:


JButton B=new JButton("Buton 2");
B.setToolTipText("Eu sunt butonul 2");
Figura 8.4. Mesaj lămuritor

⇒ void setEnabled(boolean v) - Face ca o componentă să fie activată (v


reţine true) sau nu (v reţine false). O componentă dezactivată nu mai
răspunde comenzilor şi are un aspect specific prin care utilizatorul este
anunţat că aceasta este dezactivată.

Exemplul 8.7. În imaginea alăturată butonul 1


este dezactivat şi butonul 2 este activat.
Figura 8.5. Exemplu de
buton dezactivat

⇒ void setVisible(boolean v) - dacă parametrul reţine true,


componenta este vizibilă, altfel ea este invizibilă.

8.1.5. Independenţa programelor de rezoluţie

Se ştie că programele trebuie să ruleze independent de rezoluţia monitorului.


O clasă care face posibil acest lucru este clasa ToolKit. În acest sens, cele mai
importante metode ale ei sunt:

⇒ public static Toolkit getDefaultToolkit() - returnează un


obiect Toolkit (conţine date despre setările curente);
⇒ Dimension getScreenSize() - returnează o referinţă către un obiect de
tip Dimension care conţine lungimea (width) şi înălţimea (height) în
pixeli a ecranului.

Exemplul 8.8. Programul următor creează o fereastră care iniţial, ocupă întreg
ecranul:
Capitolul 8. Programare vizuală 321

import java.awt.*;
import javax.swing.*;
class Fer extends Jframe {
public Fer(String titlu)
{ super(titlu);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Toolkit ec=Toolkit.getDefaultToolkit();
Dimension dim = ec.getScreenSize();
int i = dim.height;
int l = dim.width;
setSize(dim.width, dim.height);
setVisible(true);
}
}
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Fereastra pe intreg ecranul");
}
}

8.1.6. Poziţionarea componentelor

Pentru a aşeza componentele în poziţia dorită, putem să utilizăm


poziţionarea absolută (dar este nerecomandată pentru că programul trebuie să
ruleze corect pe o diversitate de platforme) sau unul dintre gestionarii de
poziţionare existenţi. Cum facem acest lucru? Veţi vedea în paragraful acesta!
Oricum, trebuie să ştiţi că mecanismul este puţin mai complicat decât cel cu care
aţi fost obişnuiţi în ipoteza că aţi studiat programarea vizuală (de exemplu, în
Borland Delphi sau Borland Builder).

Nu uitaţi ! Programele Java trebuie să funcţioneze pe orice platformă!

8.1.6.1. Poziţionarea absolută

Pentru a utiliza poziţionarea absolută a componentelor trebuie să lucrăm în


absenţa unui gestionar de poziţionare, iar coordonatele sunt date în pixeli. Pentru
aceasta trebuie să cunoaştem următoarele:

1. Secvenţa de mai jos se utilizează pentru a lucra în absenţa unui gestionar de


poziţionare:
Container x=getContentPane();
x.setLayout(null);

2. În poziţionarea absolută componentele trebuie dimensionate şi poziţionate,


altfel nu sunt vizibile. Testaţi...
322 Manual de Informatică pentru clasa a XII-a

Pentru dimensionarea componentelor, se utilizează următoarele metode ale


clasei JComponent:

⇒ setBounds(int x, int y, int lat, int inal); metoda poziţionează


şi dimensionează componenta. Parametrii x şi y dau poziţia componentei
raportată la colţul din stânga-sus al componentei care o găzduieşte, iar lat
şi lung o dimensionează.

Metoda de mai sus poate fi înlocuită cu următoarele două metode:

⇒ setLocation(int x, int y) - metodă care are rolul de poziţionare;

⇒ setSize(int lat, int lung) - metodă care are rolul de dimensionare.

Exemplul 8.9. Utilizăm poziţionarea absolută şi aşezăm un buton în fereastră:


Container x=getContentPane();
x.setLayout(null);
JButton A=new JButton ("Exemplu");
A.setBounds(10,10, 100, 40);

8.1.6.2. Gestionarul de poziţionare FlowLayout


.
Componentele sunt afişate pe linii, în
ordinea în care au fost declarate. Pe fiecare
linie ele sunt afişate de la stânga la dreapta
(atâtea câte încap).

Exemplul 8.10. În continuare, puteţi observa


cum a fost creată fereastra alăturată:
class Fer extends JFrame { Figura 8.6. Exemplu de
public Fer(String titlu) poziţionare a componentelor
{
super(titlu);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300,150);
Container x=getContentPane();
x.setLayout(new FlowLayout ());
JButton A=new JButton("Buton 1"); x.add(A);
JButton B=new JButton("Buton 2"); x.add(B);
JButton C=new JButton("Buton 3"); x.add(C);
JButton D=new JButton("Buton 4"); x.add(D);
JButton E=new JButton("Buton 5"); x.add(E);
JButton F=new JButton("Buton 6"); x.add(F);
JButton G=new JButton("Buton 7"); x.add(G);
setVisible(true);
}
}
Capitolul 8. Programare vizuală 323

Clasa FlowLayout conţine constante de aliniere pe linie, din care mai


importante sunt: CENTER, aliniere în centru, opţiune implicită, LEFT, la stânga şi
RIGHT, la dreapta.

⇒ Clasa FlowLayout este înzestrată cu 3 constructori:

a) FlowLayout() - distanţa între rânduri este de 5 unităţi, distanţa pe orizontală


între componente este de 5 unităţi şi componentele sunt aliniate pe linie la centru
(CENTER).
b) FlowLayout(int aliniere) - se cere explicit ca alinierea să fie într-un
anumit fel (CENTER, RIGHT, LEFT, acestea sunt constante ale clasei FlowLayout).
c) FlowLayout(int aliniere,int dist_oriz,int dist_vert) - se
specifică şi distanţa pe orizontală între componente şi distanţa pe verticală dintre ele.

Exemplul 8.11. Priviţi exemplele de utilizare a constructorilor de mai jos:

FlowLayout (FlowLayout.LEFT) FlowLayout (FlowLayout.RIGHT,15,8)

Figura 8.7. Exemple de utilizare a constructorilor

De reţinut !

1. Dimensionarea componentelor şi poziţionarea lor este făcută automat de către


gestionar.
2. Metodele utilizate în poziţionarea absolută pentru poziţionarea şi dimensionarea
componentelor (setBounds(), setLocation(), setSize()) deşi sunt acceptate la
compilare, nu au nici un efect.
3. Există totuşi o metodă care dimensionează componentele şi este acceptată de
gestionarul FlowLayout. Ea aparţine clasei JComponent:

⇒ setPreferredSize(Dimension dim). Clasa Dimension are construc-


torul Dimension(int lat, int inalt) prin care se specifică lăţimea,
respectiv înălţimea componentei.

Exemplul 8.12. Prin utilizarea gestionarului FlowLayout se adaugă unei ferestre


două butoane, primul de dimensiune stabilită, al doilea de dimensiune implicită:
324 Manual de Informatică pentru clasa a XII-a

Container x=getContentPane();
x.setLayout(new FlowLayout());
JButton A=new JButton ("Buton 1");
A.setPreferredSize(new Dimension(100,100));
JButton B=new JButton ("Buton 2");
x.add(A);
x.add(B);
Figura 8.8. Exemplu de
fereastră cu două butoane

3.1.6.3. Gestionarul de poziţionare GridLayout

Clasa GridLayout aranjează componentele într-o altă logică. Ideea de


bază este aceea că se împarte suprafaţa ferestrei în mai multe dreptunghiuri de
suprafaţă egală şi în fiecare dreptunghi astfel obţinut se aşează o componentă
care este de cele mai multe ori extinsă ca suprafaţă, astfel încât să ocupe întreaga
suprafaţă a dreptunghiului care îi revine. Pentru a înţelege modul de aranjare a
componentelor vom prezenta pe scurt cei trei constructori ai clasei:
a) GridLayout() - dacă avem n componente care trebuie aşezate, suprafaţa
ferestrei este împărţită într-o singură linie şi n coloane. Fiecare componentă este
aşezată într-un dreptunghi, iar componentele sunt fără spaţiu între ele.

b) GridLayout(int nr_linii, int nr_coloane) - suprafaţa este


împărţită în nr_linii × nr_coloane dreptunghiuri. Fiecare dreptunghi reţine o
componentă (vezi figura de mai jos).

Figura 8.9.
GridLayout(3,3)

c) GridLayout(int nr_linii, int nr_col, int sp_o, int sp_v) -


se procedează ca anterior, numai că se trec şi spaţiile pe orizontală şi pe verticală
între dreptunghiurile generate.

Figura 8.10.
GridLayout(3,3,5,8)

 Pentru GridLayout, metoda setPreferredSize() nu are niciun efect.


Capitolul 8. Programare vizuală 325

8.1.6.4. Gestionarul de poziţionare BorderLayout

Clasa BorderLayout împarte suprafaţa ferestrei în 5 părţi: nord (NORTH),


sud (SOUTH), est (EAST), vest (WEST) şi centru (CENTER). În fiecare parte se poate
aşeza o componentă.
Exemplul 8.13. Mai jos puteţi observa cum am obţinut aşezarea componentelor ca
în fereastra din figura alăturată:
x.setLayout(new BorderLayout ());
JButton A=new JButton("Buton 1");
x.add(A,BorderLayout.SOUTH);
JButton B=new JButton("Buton 2");
x.add(B,BorderLayout.NORTH);
JButton C=new JButton("Buton 3");
x.add(C,BorderLayout.WEST);
JButton D=new JButton("Buton 4");
x.add(D,BorderLayout.EAST); Figura 8.11. Exemplu de
aşezare a componentelor
JButton E=new JButton("Buton 5");
x.add(E,BorderLayout.CENTER);

De reţinut !

1. Pentru adăugarea unei componente container-ului se foloseşte metoda add


cu 2 parametri, al doilea fiind cel care precizează poziţia în care este adăugată
componenta. Vezi mai sus!

2. Componentele sunt extinse pentru a ocupa întreaga suprafaţă alocată. Vedeţi


figura de mai sus.

3. Dacă lipseşte componenta din nord, sau cea din sud, spaţiul este ocupat de
linia din centru.

4. Dacă lipseşte componenta din centru, spaţiul este lăsat liber. Dacă lipseşte
componenta din est, sau cea din vest, spaţiul este ocupat de componenta din
centru.

5. Metoda setPreferredSize() are efect parţial. Astfel rezultă: dacă este


aplicată unei componente din nord sau din sud, se ia în considerare numai
înălţimea transmisă de metodă. Dacă este aplicată unei componente din est, vest,
sau centru se ia în considerare numai lăţimea componentei.
326 Manual de Informatică pentru clasa a XII-a

8.2. Studiul principalelor componente

8.2.1. Componente de tip JButton

Cu ajutorul componentelor de acest tip se creează butoane. În general, prin


apăsarea unui buton se dau anumite comenzi programului. Vom prezenta cele mai
importante metode (constructori):

⇒ JButton() - creează un buton fără text, fără imagine asociată.


⇒ JButton(String text) - creează un buton care afişează un text.
⇒ JButton(Icon icon) - creează un buton care reţine o imagine de
mici dimensiuni.

Exemplul 8.14. Liniile de mai jos formează butonul alăturat:


Icon icon = new ImageIcon("om.gif");
JButton A=new JButton(icon);
Figura 8.12.
Exemplu de buton

⇒ JButton(String text,Icon icon) - creează un buton cu text şi imagine.

Exemplul 8.15. Liniile de mai jos formează butonul alăturat:


Icon icon = new ImageIcon("om.gif");
JButton A=new JButton( "Java...",icon);

Figura 8.13. Exemplu de


buton cu text şi imagine

⇒ metoda setVerticalTextPosition(constanta) setează poziţia pe


verticală a textului în raport cu imaginea: deasupra (JButton.TOP),
dedesubt (JButton.BOTTOM), în centru (JButton.CENTER).

⇒ metoda setHorizontalTextPosition(constanta) setează poziţia pe


orizontală a textului în raport cu imaginea: stânga (JButton.LEFT),
dreapta (JButton.RIGHT), în centru (JButton.CENTER).

Exemplul 8.16. Liniile de mai jos formează butonul alăturat:


Icon icon = new ImageIcon("om.gif");
JButton A=new JButton( "Java...",icon);
A.setVerticalTextPosition(JButton.TOP);
A.setHorizontalTextPosition(JButton.CENTER);

 Mărimea imaginii determină mărimea butonului ! Figura 8.14. Exemplu


Capitolul 8. Programare vizuală 327

8.2.2. Componente de tip JLabel

Componentele de acest tip se utilizează pentru a afişa texte şi imagini, cu rol


lămuritor. Clasa este înzestrată cu următoarele metode mai importante:

⇒ JLabel(String S) - se utilizează pentru a afişa un şir de caractere.

Exemplul 8.17. Dacă constructorul ferestrei conţine secvenţa de mai jos, atunci
pe fereastră apare ce se vede în figura alăturată:
Container x=getContentPane();
x.setLayout(new BorderLayout ()); Figura 8.15.
JLabel A=new JLabel ("Un text"); Exemplu
x.add(A);

⇒ JLabel(Icon image) - se utilizează pentru a afişa o imagine.

Exemplul 8.18. La fel ca mai sus, numai că pe fereastră se afişează o imagine:


Container x=getContentPane();
x.setLayout(new BorderLayout ());
Icon icon = new ImageIcon("idee.gif");
JLabel A=new JLabel (icon);
x.add(A); Figura 8.16.
Exemplu

⇒ JLabel(String text, Icon icon, int horizontalAlignment)


afişează o imagine şi un text. Ansamblul (imagine + text) se aliniază pe
orizontală, conform ultimului parametru (CENTER, LEFT, RIGHT).
⇒ setVerticalTextPosition(c), setHorizontalTextPosition(c)
pot fi folosite şi la JLabel la fel ca la Jbutton:
Exemplul 8.19. Se va afişa ce se vede alăturat:
Container x=getContentPane(); Figura 8.17.
x.setLayout(new GridLayout()); Exemplu
Icon icon = new ImageIcon("idee.gif");
JLabel A=new JLabel
("Asta era!!!",icon,JLabel.CENTER);
A.setHorizontalTextPosition(Jlabel.CENTER);
A.setVerticalTextPosition(JLabel.TOP);
x.add(A);

8.2.3. Componente de tip JPanel

Componentele JPanel (paneluri) sunt de tip container, adică au rolul de a


conţine pe suprafaţa lor alte componente, având în general un rol de grupare, dar şi
unul de poziţionare a componentelor. Clasa este înzestrată cu următoarele metode:
328 Manual de Informatică pentru clasa a XII-a

⇒ JPanel() - constructor, obiectul rezultat are gestionarul de poziţionare


FlowLayout().
⇒ JPanel(LayoutManager layout) - constructor, obiectul rezultat are
gestionarul de poziţionare transmis ca parametru.
⇒ setLayout(LayoutManager layout); - setează gestionarul de
poziţionare.
⇒ add(Component c) - adaugă o componentă obiectului.

Exemplul 8.20. Fereastra programului


următor conţine o componentă de tip
JPanel. Pe ea sunt ataşate 3 butoane. La
apăsarea unui buton, componenta de tip
JPanel va avea culoarea afişată de buton.
Figura 8.18.
import java.awt.*; Fereastra programului
import java.awt.event.*;
import javax.swing.*;
class Fer extends JFrame implements ActionListener
{ JPanel panel;
public Fer(String titlu) {
super(titlu); setSize(300,300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
x.setLayout(new FlowLayout ());
panel=new JPanel();
JButton A=new JButton("Rosu");
panel.add(A); A.addActionListener(this);
JButton B=new JButton("Galben");
panel.add(B); B.addActionListener(this);
JButton C=new JButton("Albastru");
panel.add(C); C.addActionListener(this);
x.add(panel);
setVisible(true);
}
public void actionPerformed (ActionEvent e)
{ String culoare=e.getActionCommand();
if (culoare.compareTo("Rosu")==0)
panel.setBackground(Color.red);
else
if (culoare.compareTo("Galben")==0)
panel.setBackground(Color.yellow);
else panel.setBackground(Color.blue);
}
}
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Fereastra cu panel"); }
}
Capitolul 8. Programare vizuală 329

8.2.4. Componente de tip JTextField

Componentele de tip JTextField (edit-uri) sunt utilizate pentru ca


utilizatorul să introducă sau să afişeze şiruri de caractere de la tastatură, şiruri pe
care programul urmează să le prelucreze. Cele mai importante metode ale acestui
obiect sunt:
⇒ JTextField(int nr) - creează un edit vid, dar care are o lăţime
suficientă pentru a vizualiza simultan nr caractere. Şirul de caractere
introdus poate avea orice lungime.

Figura 8.19. Un edit vid

⇒ JTextField(String s) - creează un edit care iniţial afişează un şir de


caractere.
Figura 8.20. Un edit cu text iniţial

⇒ JTextField(String S, int nr) - creează un edit care iniţial


afişează un şir de caractere şi care are o lăţime suficientă pentru a afişa
simultan un număr de nr caractere.
⇒ String getText() - returnează şirul de caractere reţinut de edit la un
moment dat.
⇒ void setText(String s) - are rolul de a determina ca edit-ul să
conţină şirul de caractere specificat.
Exemplul 8.21. Programul următor afişează
fereastra din figura alăturată. Utilizatorul
introduce un şir de caractere şi, la apăsarea
butonului se afişează, în fereastra CMD,
textul introdus de acesta.
import java.awt.*; Figura 8.21. Fereastra programului
import java.awt.event.*;
import javax.swing.*;
class Fer extends JFrame implements ActionListener
{ JTextField txt;
public Fer(String titlu) {
super(titlu); setSize(300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
x.setLayout(new FlowLayout ());
JLabel et=new JLabel ("Numele dv:"); x.add(et);
txt=new JTextField(15); x.add(txt);
JButton but=new JButton("Ce-am introdus?"); x.add(but);
but.addActionListener(this);
setVisible(true);
}
330 Manual de Informatică pentru clasa a XII-a

public void actionPerformed (ActionEvent e)


{ System.out.println(txt.getText()); }
}
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Exemplu de edit");
}
}

3.2.5. Componente de tip JComboBox

Obiectele clasei JComboBox sunt aşa numitele liste, din care utilizatorul poate
selecta o anumită opţiune (unică). Principalele metode ale clasei JComboBox sunt:

⇒ JComboBox () – constructor.
⇒ void addItem(Object s) - adaugă listei o opţiune. Cum clasa Object
este la baza ierarhiei de clase Java, parametrul efectiv poate fi o referinţă
către orice obiect, inclusiv către tipul des utilizat String.
⇒ Object getSelectedItem() – returnează şirul de caractere corespun-
zător opţiunii selectate.
⇒ int getItemCount() - returnează numărul de opţiuni.
⇒ int getSelectedIndex() - returnează indexul opţiunii selectate.
⇒ Object getItemAt(int ind) - returnează obiectul reţinut de item-ul
de indice ind (dacă trebuie să obţinem un obiect de tip String, atunci
convertiţi către String prin operatorul de conversie).
Exemplul 8.22. Programul următor afişează
o listă. Selectaţi din listă o opţiune şi apăsaţi
butonul. În fereastra CMD va fi afişată opţiunea
selectată:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*; Figura 8.22. Fereastra programului

class Fer extends JFrame implements ActionListener


{ JComboBox lista;
public Fer(String titlu) {
super(titlu); setSize(300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
x.setLayout(new FlowLayout ());
JLabel et=new JLabel ("Selectati materia preferata:");
x.add(et);
lista=new JComboBox();
lista.addItem("Matematica");
Capitolul 8. Programare vizuală 331

lista.addItem("Informatica");
lista.addItem("Engleza");
lista.addItem("Alta materie");
x.add(lista);
JButton but=new JButton("Ce-am selectat?");
x.add(but);
but.addActionListener(this);
setVisible(true);
}
public void actionPerformed (ActionEvent e)
{ System.out.println(lista.getSelectedItem()); }
}

public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Exemplu de lista");
}
}

3.2.6. Componente de tip JCheckBox şi JRadioButton.


Gruparea lor
Obiectele clasei JCheckBox sunt aşa-numitele butoane de validare.
Fereastra poate conţine unul sau mai multe astfel de butoane. Principalele metode
ale acestei clase sunt:
⇒ JCheckBox(String s) - creează un buton de validare care conţine şirul
de caractere transmis ca parametru.
⇒ JCheckBox(String s, boolean v) - creează un buton de validare care
conţine şirul de caractere transmis ca parametru şi care este marcat sau nu în
funcţie de valoarea pe care o reţine parametrul v, respectiv true sau false.
⇒ JCheckBox(String s, Icon f) - creează un buton de validare care
conţine şirul de caractere transmis ca parametru şi o imagine.
⇒ boolean isSelected() - returnează true dacă butonul a fost selectat şi
false în caz contrar.
⇒ String getText() - returnează şirul de caractere reţinut de buton.

Exemplul 8.23. Programul următor afişează mai multe


butoane de validare, din care unul (cel care afişează
”Informatica”) este selectat de la început! La apăsarea
butonului ”Ce-am selectat?” este afişată selecţia făcută.

import java.awt.*;
import java.awt.event.*; Figura 8.23.
import javax.swing.*; Fereastra programului
332 Manual de Informatică pentru clasa a XII-a

class Fer extends JFrame implements ActionListener


{ JCheckBox b1,b2,b3,b4;
public Fer(String titlu) {
super(titlu); setSize(150,200);
Container x=getContentPane();
x.setLayout(new FlowLayout (FlowLayout.LEFT));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel et=new JLabel ("Selectati");
x.add(et);
b1=new JCheckBox("Matematica");x.add(b1);
b2=new JCheckBox("Informatica",true);x.add(b2);
b3=new JCheckBox("Engleza"); x.add(b3);
b4=new JCheckBox("Biologie");x.add(b4);
JButton but=new JButton("Ce-am selectat?");
x.add(but);
but.addActionListener(this);
setVisible(true);
}
public void actionPerformed (ActionEvent e)
{ if (b1.isSelected()) System.out.println(b1.getText());
if (b2.isSelected()) System.out.println(b2.getText());
if (b3.isSelected()) System.out.println(b3.getText());
if (b4.isSelected()) System.out.println(b4.getText());
}
}
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Validare"); }
}

⇒ Obiectele de tip JRadioButton sunt asemănătoare cu cele de tip


JCheckBox, negrupate au acelaşi comportament, numai că arată ca nişte
butoane radio.
Butoanele pot fi grupate, adică pot fi toate tratate ca un întreg. Un exemplu
convingător este dat de necesitatea grupării butoanelor radio (unde, la un moment
dat, numai un singur buton poate fi selectat). Pentru a grupa butoanele se
foloseşte un obiect al clasei ButtonGroup. Cele mai importante metode ale
acestei clase sunt:

⇒ ButtonGroup() - constructor;
⇒ void add(AbstractButton b) - adaugă un buton grupului (clasa
AbstractButton este superclasă pentru JButton, JRadioButton,
JCheckBox).
⇒ Enumeration getElements(); - returnează un pointer la grupul de
butoane.
⇒ int getButtonCount() - returnează numărul de butoane din grup.
Capitolul 8. Programare vizuală 333

Exemplul 8.24. Priviţi programul de mai jos:


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
class Fer extends JFrame implements ActionListener
{ ButtonGroup grup;
public Fer(String titlu) {
super(titlu); setSize(150,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
x.setLayout(new FlowLayout (FlowLayout.LEFT));
JLabel et=new JLabel ("Selectati"); x.add(et);
JRadioButton b1=new JRadioButton("Matematica");x.add(b1);
JRadioButton b2=new JRadioButton("Informatica",true);
x.add(b2);
JRadioButton b3=new JRadioButton("Engleza"); x.add(b3);
JRadioButton b4=new JRadioButton("Biologie");x.add(b4);
JButton but=new JButton("Ce-am selectat?"); x.add(but);
but.addActionListener(this);
grup = new ButtonGroup();
grup.add(b1);grup.add(b2);
grup.add(b3);grup.add(b4);
setVisible(true);
}
public void actionPerformed (ActionEvent e)
{ Enumeration en=grup.getElements();
while (en.hasMoreElements())
{ JRadioButton b=(JRadioButton)en.nextElement();
if(b.isSelected()) System.out.println(b.getText());
}
}
}
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Validare"); }
}

3.2.7. Meniuri

În Java, meniurile se construiesc prin utilizarea obiectelor mai multor clase.

A) Clasa JMenuBar - obiectele acestei clase se utilizează pentru a obţine meniuri


clasice, aflate în partea de sus a ferestrei. Cele mai importante metode ale acestei
clase sunt:
⇒ JMenuBar() - constructor;
⇒ add(JMenu) - adaugă meniului componente de tip JMenu, vedeţi în
continuare.
334 Manual de Informatică pentru clasa a XII-a

B) Clasa JMenu - obiectele acestei clase au rolul de a înscrie în meniu anumite


opţiuni, care la rândul lor pot conţine alte opţiuni. Cele mai importante metode ale
acestei clase sunt:
⇒ JMenu(String s) - constructor. Obiectul va afişa şirul s.
⇒ add(JMenuItem meniu) - adaugă o componentă de tip JMenuItem
(vedeţi mai jos clasa JMenuItem;).
⇒ add (Component c) - adaugă o altă componentă (de un tip derivat din
tipul Component).

C) Clasa JMenuItem - o astfel de componentă care apare în meniu, arată ca o


opţiune şi are rolul unui buton, adică selectată, conduce la o anumită acţiune. Cele
mai importante metode ale acestei clase sunt:

⇒ JMenuItem(String s) - constructor, opţiunea afişează şirul s;


⇒ JMenuItem(Icon ic) - constructor, opţiunea afişează o mică imagine;
⇒ JMenuItem(String s, Icon ic) - constructor, opţiunea afişează un
şir de caractere şi o mică imagine.
Exemplul 8.25. Programul următor construieşte un
meniu clasic. Pentru fiecare opţiune selectată, se
afişează în fereastra CMD şirul generat de opţiune.
import java.awt.*;
Figura 8.24.
import java.awt.event.*;
import javax.swing.*;
class Fer extends JFrame implements ActionListener
{ TextArea t;
public Fer(String titlu) {
super(titlu);
setSize(400,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Bara meniu
JMenuBar bara = new JMenuBar();
// Creez meniul principal
JMenu meniu1 = new JMenu("Operatii 1");
bara.add(meniu1);
JMenu meniu2 = new JMenu("Operatii 2");
bara.add(meniu2);
// adaug itemi pentru fiecare optiune din meniul principal
JMenuItem item11 = new JMenuItem("OP 11");
item11.addActionListener(this);
meniu1.add(item11);
JMenuItem item12 = new JMenuItem("OP 12");
item12.addActionListener(this);
meniu1.add(item12);
JMenuItem item21 = new JMenuItem("OP 21");
Capitolul 8. Programare vizuală 335

item21.addActionListener(this);
meniu2.add(item21);
setJMenuBar(bara);
Container x=getContentPane();
x.setLayout(new GridLayout ());
setVisible(true);
}
public void actionPerformed (ActionEvent e)
{ System.out.println(e.getActionCommand()); }
}
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Fereastra cu meniu"); }
}

Observaţie ! Metoda clasei JFrame setJMenuBar(JMenuBar b) are rolul de a


ataşa bara de meniu ferestrei.

Meniurile pot conţine şi submeniuri. Pentru


aceasta, unei componente de tip JMenu i se adaugă, pe
lângă alte componente de tip JMenuItem, o altă
componentă, tot de tip JMenu. Acesteia din urmă i se
adaugă componente de tip JMenuItem.

Exemplul 8.26. Pentru a obţine meniul alăturat,


adăugaţi programului de mai sus secvenţa următoare:
//submeniuri
JMenu altele = new JMenu("Altele"); Figura 8.25.
meniu1.add(altele); Exemplu de meniu
JMenuItem item131 = new JMenuItem("OP 131");
altele.add(item131);
item131.addActionListener(this);
JMenuItem item132 = new JMenuItem("OP 132");
altele.add(item132);
item132.addActionListener(this);

 Evident, procedeul se poate repeta pentru a obţine oricâte submeniuri doriţi.

Acceleratori. În multe aplicaţii, anumite opţiuni din meniuri sunt înzestrate cu


acceleratori (shortcut-uri de meniu) prin care o anumită comandă se poate obţine
fie din meniu, fie dintr-o combinaţie de taste. Şi în Java se pot crea acceleratori şi
acest mecanism este prezentat în continuare. Metoda:
void setAccelerator(KeyStroke keyStroke)
are rolul de a ataşa unui obiect de tip JMenuItem un accelerator, adică de a
invoca acţiunea specifică acestuia atunci când utilizatorul a apăsat fie o tastă, fie o
combinaţie de taste. În primul caz (o tastă), se foloseşte metoda:
static KeyStroke getKeyStroke(char keyChar),
336 Manual de Informatică pentru clasa a XII-a

iar în al doilea caz, metoda:


static KeyStroke getKeyStroke(int keyCode, int modifiers)

Cum obţinem parametrii pentru a doua metodă getKeyStroke()?


 Primul parametru este o constantă a clasei KeyEvent. Iată câteva astfel de
constante: static int VK_1 (tasta 1), static int VK_2 (tasta 2),
static int VK_F1 (tasta F1), static int VK_V (tasta V), ş.a.m.d.
 Al doilea parametru este o constantă a clasei ActionEvent: SHIFT_MASK,
(codul 1), CTRL_MASK (codul 2), META_MASK (codul 4), ALT_MASK (codul 8).
Exemplul 8.27. În primul program de la începutul
paragrafului, pentru item21 dorim să avem un
accelerator, adică să obţinem acelaşi efect prin
apăsarea combinaţiei de taste ALT+2 ca şi în cazul în
care operăm selecţia din meniu:
JMenuItem item21 = new JMenuItem("OP 21"); Figura 8.26.
item21.setAccelerator(KeyStroke.getKeyStroke Exemplu de meniu
(KeyEvent.VK_2, ActionEvent.ALT_MASK));
item21.addActionListener(this);

În acest caz, dacă apăsăm ALT+2, obţinem acelaşi efect ca atunci când
operăm selecţia din meniu. Dacă dorim să obţinem o combinaţie din trei taste, de
exemplu CTRL+ALT+2, vom folosi (datorită codificării din ActionEvent):
getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK
+ ActionEvent.CTRL_MASK));

8.2.8. Cutii (casete) de dialog predefinite

Cutiile de dialog predefinite sunt extrem de utile pentru introducerea sau


afişarea unor date. Pentru a putea folosi astfel de cutii, vom utiliza clasa
JOptionPane care conţine mai multe metode statice care le afişează. Cutiile
sunt predefinite, conţinând automat anumite componente (nu mai este necesar ca
acestea să fie create de programator).

8.2.8.1. Cutii de dialog de intrare

Iată câteva metode prin care putem apela astfel de cutii:

⇒ public static String showInputDialog(Object mes) creează şi


afişează în centrul ecranului o cutie de dialog care afişează mesajul transmis
ca parametru. În cazul în care utilizatorul apasă ”Cancel”, se returnează
pointer-ul null, motiv pentru care trebuie tratată această excepţie.
Capitolul 8. Programare vizuală 337

Exemplul 8.28. Priviţi secvenţa de mai jos:


try { String intr = JOptionPane.showInputDialog("a=");
if (intr.length()==0) System.out.println("Intr vida");
else System.out.println(intr);
}
catch(NullPointerException exc)
{ System.out.println("S-a apasat Cancel"); }

Figura 8.26. Exemplu


de cutie de dialog

⇒ public static String showInputDialog(Object mes, Object


val) - la fel ca mai sus, numai că edit-ul memorează de la început valoarea
transmisă de al doilea parametru (valoare iniţială). În exemplul de mai jos,
valoarea iniţial afişată este ”0”:
String intr = JOptionPane.showInputDialog("a=","0");
⇒ public static String showInputDialog(Component par,
Object mes) - ca mai sus, numai că se afişează o cutie de dialog care are
o componentă părinte. În exemplul următor, afişarea se face cu ajutorul
clasei care descrie fereastra principală, deci părintele este this (acest obiect):
String intr = JOptionPane.showInputDialog(this,"a=");
⇒ public static String showInputDialog(Component par,
Object mes, Object val) - ca mai sus, numai că se afişează o cutie
de dialog în care edit-ul reţine şi o valoare iniţială.

8.2.8.2. Cutii de dialog pentru afişarea mesajelor (de informare)

Astfel de cutii de dialog se utilizează pentru a transmite utilizatorului anumite


mesaje de eroare, sau rezultate.
⇒ public static void showMessageDialog(Component par,
Object mes) - afişează o cutie de dialog cu un mesaj dorit.

Exemplul 8.29. Secvenţa de mai jos afişează


ferestra alăturată:
int a=125;
JOptionPane.showMessageDialog(this,
"a="+a);

Figura 8.27. Exemplu


338 Manual de Informatică pentru clasa a XII-a

8.2.8.3. Cutii de dialog de confirmare

O astfel de cutie de dialog afişează trei butoane: Yes, No şi Cancel.

⇒ public static int showConfirmDialog(Component par,Object


mes); - metoda returnează un întreg a cărui valoare este dată de butonul
pe care-l apasă utilizatorul: 0 pentru Yes, 1 pentru No sau 2 pentru Cancel.

Observaţie ! De fapt, se returnează indicele butonului apăsat: Yes are 0 pentru


că este primul buton, No are 1 pentru că este al doilea buton, iar Cancel are 2
deoarece este al treilea buton.

Exemplul 8.30. Secvenţa următoare testează, prin afişare, valorile returnate de


showConfirmDialog():

Figura 8.28. Exemplu


int a=125;
int rasp= JOptionPane.showConfirmDialog(this,"a="+a+"?");
System.out.println(rasp);

8.2.9. Componente de tip JTextArea

Componentele de acest tip permit utilizatorului să introducă text pe mai multe


linii. Se poate utiliza un singur font, de o singură mărime! Un astfel de text, cu un
singur font, care nu permite să fie formatat se numeşte text plan.

Cele mai importante metode ale clasei sunt:

⇒ JTextArea() - constructor.
⇒ void append(String S) - adaugă la sfârşitul şirului reţinut de
componentă un alt şir.
⇒ void insert(String s, int pozitie) - inserează în text,
începând de la pozitie un şir de caractere. Dacă pozitie depăşeşte
indicele ultimului caracter, atunci inserarea se face la sfârşitul şirului reţinut
de componentă.
⇒ void replaceRange(String str, int start, int end) -
înlocuieşte şirul dintre indicii start şi end cu şirul transmis ca parametru.
Evident, dacă acesta din urmă este vid, se şterge întreg textul.
⇒ setFont(Font f) - setează fontul utilizat.
Capitolul 8. Programare vizuală 339

⇒ String getText() - returnează şirul de caractere conţinut de


componentă (inclusiv dacă el conţine newline, altfel spus, mai multe
paragrafe).
⇒ void setText(String s) - determină ca obiectul de tip JTextArea să
reţină şirul s.
⇒ void setBackground(Color c) - setează culoarea de fond a
suprafeţei care afişează literele.
⇒ String getSelectedText() - returnează şirul de caractere selectat.

⇒ void selectAll() - selectează întreg textul reţinut de componentă.


⇒ int getSelectionStart() - returnează indicele primului caracter selectat.

⇒ int getSelectionEnd() - returnează indicele ultimului caracter selectat.

⇒ void setLineWrap(boolean v) - dacă reţine true, setează obiectul ca


textul scris fără newline (adică un singur paragraf) să se afişeze pe mai
multe rânduri (în cazul în care nu încape pe lăţime). Dacă reţine false,
acesta este afişat pe o singură linie, chiar dacă, la un moment dat, nu este
toată vizibilă.

Obiectele de tip JTextArea nu se afişează pe fereastră în mod direct, ci


prin intermediul altor obiecte de tip JScrollPane, asemănătoare obiectelor de tip
JPanel, dar care permit ataşarea unor bare de scroll, aşa cum se vede mai jos:
JScrollPane panel = new JScrollPane(t);
panel.setVerticalScrollBarPolicy(JScrollPane.
VERTICAL_SCROLLBAR_ALWAYS);
panel.setHorizontalScrollBarPolicy(JScrollPane.
HORIZONTAL_SCROLLBAR_ALWAYS);

Exemplul 8.29. Programul următor afişează o


componentă de tip JTextArea şi un meniu.
Utilizatorul introduce un text la alegerea sa.
Textul poate fi salvat cu ajutorul meniului
(File şi Save) şi poate fi recuperat tot cu
ajutorul meniului (File şi Open). Pentru
simplificarea programului, fişierul în care se
salvează este întotdeauna test.txt. Înainte
de a studia programul, recomand o scurtă
recapitulare a lucrului cu fişiere.
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*; Figura 8.29. Exemplu
import javax.swing.*;
340 Manual de Informatică pentru clasa a XII-a

class Fer extends JFrame implements ActionListener


{ JTextArea t;
public Fer(String titlu) {
super(titlu); setSize(200,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
x.setLayout(new GridLayout());
JMenuBar bara = new JMenuBar();
JMenu meniu1 = new JMenu("File");
bara.add(meniu1);
JMenuItem item11 = new JMenuItem("Open");
item11.addActionListener(this); meniu1.add(item11);
JMenuItem item12 = new JMenuItem("Save");
item12.addActionListener(this); meniu1.add(item12);
setJMenuBar(bara);
t=new JTextArea(); t.setLineWrap(true);
JScrollPane panel = new JScrollPane(t);
panel.setVerticalScrollBarPolicy
(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
panel.setHorizontalScrollBarPolicy
(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
x.add(panel);
setVisible(true);
}
void scriuFisier() throws IOException
{ FileOutputStream f=new FileOutputStream("test.txt");
PrintStream fchar=new PrintStream (f);
StringTokenizer tok=new StringTokenizer(t.getText(),"\n");
while (tok.hasMoreTokens())
fchar.println(tok.nextToken());
fchar.close();
}
void citFisier() throws IOException
{ FileInputStream f=new FileInputStream("test.txt");
InputStreamReader fchar=new InputStreamReader (f);
BufferedReader buf = new BufferedReader(fchar);
t.setText(""); String linie;
while ((linie=buf.readLine() )!=null)
t.append(linie+"\n");
}
public void actionPerformed (ActionEvent e)
{ if( e.getActionCommand().compareTo("Save")==0)
// Daca s-a selectat Save
{ try {scriuFisier(); }
catch (Exception excp) {} }
else
// Daca s-a selectat Open
{ try {citFisier(); }
catch (Exception excp) {} }
}
}
Capitolul 8. Programare vizuală 341

public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Fereastra din care pot introduce textul");}
}

8.2.10. Cutii de tip Open / Save

Astfel de cutii se utilizează în operaţiile de încărcare şi salvare a fişierelor.


Cu ajutorul lor se selectează fişierele şi folder-ele necesare acestor operaţii. Ele
pot fi obţinute cu metodele clasei JFileChooser(). Cele mai importante metode
ale acestei clase sunt:
⇒ JFileChooser() - constructor;
⇒ int showOpenDialog(Component fer_parinte) - afişează o cutie de
dialog de tip Open, aşa cum este cea de mai jos:

Figura 8.30. Cutie de tip Open


Valoarea returnată este 0, dacă s-a apăsat butonul Open sau este 1 dacă
s-a apăsat butonul Close. Rolul ei este ca, atunci când a fost selectat un
anumit fişier şi s-a apăsat Open, obiectul de tip JFileChooser să conţină
date despre fişierul selectat.
⇒ int showSaveDialog(Component fer_parinte) - afişează o cutie de
dialog de tip Save, asemănătoare cu cutia precedentă. Valoarea returnată
este 0 dacă s-a apăsat butonul Save şi 1 dacă s-a apăsat butonul Cancel.
Ca şi cutia precedentă (de tip Open), rolul ei este ca obiectul de tip
JFileChooser să conţină date despre fişierul salvat.

Atenţie ! Cutia de tip Open nu deschide fişierul, iar cutia de tip Save nu-l salvează.
Rolul lor este de a obţine informaţiile necesare deschiderii şi salvării fişierelor.
⇒ File getSelectedFile() - metoda returnează, atât în cazul salvării,
cât şi în cazul deschiderii fişierelor, date despre fişierul selectat (furnizate de
showOpenDialog() şi showSaveDialog()). Pentru a putea accesa
aceste informaţii, trebuie să studiem câteva metode ale tipului File.
342 Manual de Informatică pentru clasa a XII-a

⇒ void addChoosableFileFilter(Filter x); - metoda se utilizează


pentru a adăuga un filtru cutiilor de tip Open şi Save. Despre filtre vom
învăţa în cadrul acestui paragraf.
⇒ setCurrentDirectory(File f) - setează cutia astfel încât să se
deschidă într-un anumit folder.
Clasa File. Cele mai importante metode ale acestei clase sunt:
 File() - constructor;
 File(String nume) - construieşte un obiect care conţine numele unui
fişier (folder).
 boolean isDirectory() - returnează true dacă fişierul reţinut de obiect
este folder (director) sau false, în caz contrar.
 String getName() - returnează numele fişierului.
 String getPath() - returnează numele întreg al fişierului, inclusiv calea
către el.
Filtre. În partea de jos a cutiilor de tip Open sau Save se găseşte o listă (File
Name). Dacă programul nostru nu conţine un filtru, implicit se afişează doar
opţiunea All Files, adică cutiile vizualizează toate folder-ele şi toate fişierele,
indiferent de tipul lor. În cazul în care dorim ca programul să conţină filtre, adică să
se vizualizeze doar fişierele de un anumit tip (sau tipuri), vom utiliza clasa
FileFilter.

Clasa FileFilter este abstractă. Pentru a crea un filtru este necesar să


rescriem două metode ale sale:
⇒ public String getDescription() - trebuie să returneze un şir de
caractere care va fi afişat de lista File of Type, listă conţinută de cutiile
Open şi Save.
⇒ public boolean accept(File f) - metodă care returnează true
pentru un fişier care, fie are o extensie dorită, fie este de tip folder, altfel
returnează false. Dacă metoda returnează true, fişierul este aflat de
cutiile Open/Save, altfel acesta nu este afişat.

Exemplul 8.30. Programul de mai jos este un editor


primitiv de fişiere text. El nu conţine în meniu decât două
opţiuni: Open şi Save. Oricare dintre ele are ca efect
afişarea cutiilor respective şi salvarea sau deschiderea cu
afişare a unui fişier cu una din extensiile .java şi .txt.
Afişarea fişierului se face cu ajutorul unei componente de
tip JTextArea.
import java.io.*;
import java.util.*;
import java.awt.*; Figura 8.31. Rezultat
Capitolul 8. Programare vizuală 343

import java.awt.event.*;
import javax.swing.*;
class Filtre extends javax.swing.filechooser.FileFilter {
public boolean accept(File f) {
if (f.isDirectory()) {return true;}
String nume_fis = f.getName();
return nume_fis.endsWith(".java") || nume_fis.endsWith(".txt");
}
public String getDescription() {
return "*.java" + " "+"*.txt";}
}
class Fer extends JFrame implements ActionListener
{ JTextArea t;
public Fer(String titlu) {
super(titlu); setSize(200,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
x.setLayout(new GridLayout());
JMenuBar bara = new JMenuBar();
JMenu meniu1 = new JMenu("File"); bara.add(meniu1);
JMenuItem item11 = new JMenuItem("Open");
item11.addActionListener(this); meniu1.add(item11);
JMenuItem item12 = new JMenuItem("Save");
item12.addActionListener(this); meniu1.add(item12);
setJMenuBar(bara);
t=new JTextArea(); t.setLineWrap(true);
JScrollPane panel = new JScrollPane(t);
panel.setVerticalScrollBarPolicy
(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
panel.setHorizontalScrollBarPolicy
(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
x.add(panel); setVisible(true);
}
void scriuFisier(String nume) throws IOException
{FileOutputStream f=new FileOutputStream(nume);
PrintStream fchar=new PrintStream (f);
StringTokenizer tok=new StringTokenizer(t.getText(),"\n");
while (tok.hasMoreTokens()) fchar.println(tok.nextToken());
fchar.close();
}
void citFisier(String nume) throws IOException
{ FileInputStream f=new FileInputStream(nume);
InputStreamReader fchar=new InputStreamReader (f);
BufferedReader buf = new BufferedReader(fchar);
t.setText("");
String linie;
while ((linie=buf.readLine() )!=null)
t.append(linie+"\n");
}
344 Manual de Informatică pentru clasa a XII-a

public void actionPerformed (ActionEvent e)


{ if( e.getActionCommand().compareTo("Open")==0)
{ JFileChooser c_op = new JFileChooser();
c_op.addChoosableFileFilter(new Filtre());
int valRet = c_op.showOpenDialog(this);
if (valRet==0)
{ File f=c_op.getSelectedFile();
{ try { citFisier(f.getPath()); }
catch (Exception excp) {}
}
}
}
else
{ JFileChooser c_save = new JFileChooser();
c_save.addChoosableFileFilter(new Filtre());
int valRet = c_save.showSaveDialog(this);
if (valRet==0)
{ File f=c_save.getSelectedFile();
{ try { scriuFisier(f.getPath()); }
catch (Exception excp) {} }
}
}
}
}
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Fereastra din care pot introduce textul"); }
}

8.2.11. Componente de tip JColorChooser

În programarea vizuală culorile au un rol fundamental. Pentru a uşura


selectarea culorilor, Java pune la dispoziţia programatorilor clasa JColorChooser.
În linii mari, această clasă permite afişarea unui panou prin care se selectează
uşor culorile (fie direct, fie folosind sistemul RGB, fie folosind sistemul HSL). Iată
cele mai importante metode ale acestei clase:
⇒ JColorChooser() - constructor. În panoul culorilor este automat selectată
culoarea albă;
⇒ JColorChooser(Color c) - constructor. În panoul culorilor este
automat selectată culoarea transmisă ca parametru;
⇒ static Color showColorDialog (Component parinte, String mes,
Color c) - lansează, modal, o cutie de dialog care conţine panoul culorilor.
După cum observaţi, metoda returnează culoarea selectată (dacă se apasă
butonul OK, iar dacă se apasă Cancel se returnează null). Parametrii sunt:
parinte (fereastra părinte), mes (mesaj ce se afişează pe bara de titlu a
cutiei) şi c (culoarea iniţial setată în cutie). Utilizarea acestei metode este cel
mai simplu mecanism prin care utilizatorul poate selecta culoarea.
Capitolul 8. Programare vizuală 345

⇒ Color getColor() - returnează culoarea selectată în cutie.

Exemplul 8.31. Din fereastra principală,


la apăsarea unui buton se afişează o cutie
de dialog specifică pentru selectarea
culorii. Culoarea selectată va fi culoarea
de fond a ferestrei principale.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Fer extends JFrame
implements ActionListener {
Container x;
public Fer(String titlu) {
super(titlu);
setSize(200,100);
x=getContentPane(); Figura 8.32. Cutia de dialog
x.setLayout(new FlowLayout ());
JButton A=new JButton("Alta culoare");
x.add(A); A.addActionListener(this); setVisible(true);
}
public void actionPerformed (ActionEvent e)
{ Color c=JColorChooser.showDialog
(this, "Alege culoarea",Color.red);
if (c!=null) x.setBackground(c);
}
}
public class pv1 {
public static void main(String args[]) {
Fer fp=new Fer("Schimbarea culorii ferestrei");
fp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); }
}

8.2.12. Componente de tip JToolBar (bară de unelte)

O astfel de componentă creează o “bară cu unelte”. Pe ea se aşează


numeroase alte componente, întocmai ca pe un panel. De regulă se găseşte în
partea de sus a ferestrei, dar întotdeauna sub meniu.
Clasa JToolBar conţine următoarele metode mai importante:
⇒ JToolBar() - constructor, creează o bară de unelte poziţionată orizontal;
⇒ JToolBar(int orientare) - creează o bară de unelte orientată fie
orizontal, orientare va avea valoarea JToolBar.HORIZONTAL, fie
vertical, orientare va avea valoarea JToolBar.VERTICAL. Diferenţa
de orientare afectează modul în care sunt aşezate pe ea diferitele
componente (pe orizontal sau pe vertical).
346 Manual de Informatică pentru clasa a XII-a

⇒ Component add(Component comp) - adaugă o componentă;


⇒ void addSeparator() - adaugă un separator (spaţiu liber) între
componente.
Exemplul 8.32. Mai jos puteţi observa
programul care afişează o fereastră
cu o bară de unelte şi în rest, un panel
(componentă de tip JPanel):
import java.awt.*;
import javax.swing.*; Figura 8.33. Rezultat

class Fer extends JFrame


{ public Fer(String titlu) {
super(titlu); setSize(600,800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
JToolBar bara=new JToolBar();
bara.setBackground(Color.red);
bara.setLayout(new FlowLayout(FlowLayout.LEFT));
JPanel panel=new JPanel();
panel.setBackground(Color.yellow);
JComboBox lista=new JComboBox ();
x.setLayout(new BorderLayout());
x.add(bara,BorderLayout.NORTH);
x.add(panel,BorderLayout.CENTER);
JButton A=new JButton("buton 1"); bara.add(A);
A.setPreferredSize(new Dimension (70,30));
JButton B=new JButton("buton 2");
B.setPreferredSize(new Dimension (70,30)); bara.add(B);
bara.addSeparator();
lista.addItem("Optiunea 1");
lista.addItem("Optiunea 2");
bara.add(lista);
lista.setPreferredSize(new Dimension (100,30));
setVisible(true);
}
}
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Bara cu unelte");
fp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}

Observaţii !
1. Pentru a poziţiona bara orizontal se preferă gestionarul GridLayout şi bara
se aşează în nord.
Capitolul 8. Programare vizuală 347

2. În aceste condiţii, panelul s-a aranjat în centru. Cum celelalte trei componente
lipsesc, componenta din centru ocupă toată linia din mijloc, iar linia din mijloc
ocupă şi partea de sud!
3. Pentru bară se preferă gestionarul FlowLayout (FlowLayout.LEFT) care
aranjează componentele pe bară de la dreapta la stânga, dar aliniate stânga!
4. Pentru a ne asigura că butoanele şi lista au aceeaşi înălţime, am preferat
dimensionarea lor prin setPreferredSize().
5. Între cele două butoane şi listă a fost introdus un separator. Observaţi-l în
imaginea de pe pagina anterioară!

8.2.13. Componente de tip JTable

Cu ajutorul componentelor de acest tip se creează tabele. În continuare


prezentăm cele mai importante metode ale acestui tip.
⇒ JTable(Object[][] celule, object[] cap_t) - constructor.
Parametrul celule este o matrice de referinţe către obiectele afişate de
celulele tabelului, iar cap_t este un vector de referinţe către obiectele
afişate de capul de tabel. Numărul coloanelor matricei de referinţe celule
trebuie să coincidă cu numărul elementelor vectorului de referinţe cap_t şi
reprezintă numărul coloanelor din tabel.
Înainte de a da primul exemplu de tabel, trebuie precizat că această
componentă se plasează, de obicei, pe o componentă de tip JScrollPane.
⇒ public void setPreferredScrollableViewportSize(Dimension dim)
are rolul de a preciza dimensiunea tabelului şi faptul că acesta trebuie să
conţină o bara de scroll verticală (dacă tabelul are suficiente linii astfel încât
să nu încapă în totalitate în spaţiul generat de dim).
Exemplul 8.33. Tabelul alăturat a fost
obţinut cu secvenţa de mai jos:
class Fer extends JFrame
{ public Fer(String titlu) { Figura 8.34. Tabelul rezultat
super(titlu); setSize(600,800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Object[][] date = { {"x(0,0)", "x(0,1)","x(0,2)"},
{"x(1,0)", "x(1,1)","x(1,2)"} };
String[] cap_tabel={"Coloana 1","Coloana 2","Coloana 3"};
Container x=getContentPane();
x.setLayout(new FlowLayout());
JTable table = new JTable(date, cap_tabel);
JScrollPane panel = new JScrollPane(table);
table.setPreferredScrollableViewportSize(new Dimension(200,30));
x.add(panel);setVisible(true);
}
}
348 Manual de Informatică pentru clasa a XII-a

Observaţie ! Dacă dorim, putem inversa ordinea coloanelor în tabel prin drag and
drop. Încercaţi!
Tabelul este de fapt format din două componente: tabelul propriu-zis (de tip
JTable) şi capul de tabel (de tip JTableHeader).

⇒ JTableHeader getTableHeader() - metoda returnează o referinţă


către capul de tabel.
Imediat ce creăm un tabel ne punem problema culorilor de fond şi de scriere,
atât pentru capul de tabel cât şi pentru tabelul propriu-zis. Dacă ambele sunt
componente, atunci putem utiliza metodele clasei JComponent:
setBackground(), setForeground() şi setColor().
Exemplul 8.34. Adăugaţi exemplului anterior secvenţa de mai jos şi veţi obţine
efectul scontat!
// pentru tabel
table.setFont(new Font("Arial",Font.ITALIC, 10));
table.setBackground(Color.GREEN);
table.setForeground(Color.RED);
// pentru capul de tabel
JTableHeader cap= table.getTableHeader();
cap.setFont(new Font("Arial",Font.BOLD, 12));
cap.setBackground(Color.YELLOW);
cap.setForeground(Color.RED);

 Observaţi faptul că fiecare celulă a tabelului este editabilă. Aceasta


înseamnă că dacă executăm clic pe celula respectivă, ea se comportă ca un
edit oarecare. De aici, rezultă că un tabel poate fi folosit şi pentru
introducerea datelor, nu doar pentru afişarea lor!
⇒ Object getValueAt(int linie, int coloana) întoarce o referinţă
către obiectul memorat de celula respectivă;
⇒ void setValueAt(Object ref, int linie, int coloana) -
memorează referinţa către obiect în linia şi coloana dată de indicii transmişi.
⇒ JTable(int n_linii, int n_coloane) - este un alt constructor al
tabelului, în care se creează un tabel cu n_linii şi n_coloane. Liniile
sunt numerotate începând de la 0. De asemenea, coloanele sunt
numerotate începând de la 0.

Exemplul 8.35. Programul următor creează un tabel fără date cu 2 linii şi 4


coloane. Utilizatorul introduce date în fiecare celulă a tabelului. La apăsarea
butonului se afişează, în fereastra CMD, valorile reţinute de fiecare celulă. Observaţi
că numele coloanelor a fost dat automat.

Figura 8.35.
Tabelul rezultat
Capitolul 8. Programare vizuală 349

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.event.*;
class Fer extends JFrame implements ActionListener
{
JTable table;
public Fer(String titlu) {
super(titlu);setSize(600,800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
x.setLayout(new FlowLayout());
table = new JTable(3, 4);
JScrollPane panel = new JScrollPane(table);
table.setPreferredScrollableViewportSize
(new Dimension(200, 30));
x.add(panel);
JButton A=new JButton("Afiseaza"); x.add(A);
A.addActionListener(this);
setVisible(true);
}
public void actionPerformed (ActionEvent e)
{ if (table.getCellEditor() != null)
table.getCellEditor().stopCellEditing();
for (int i=0;i<2;i++)
for (int j=0;j<4;j++)
System.out.println(i+" "+j+" "+table.getValueAt(i,j));
}
}
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Tabel");
}
}

Să urmărim metoda actionPerformed(). Ce rost are acel if? Atunci


când se scriu datele într-o celulă, până nu s-a trecut la celula următoare (clic pe
suprafaţa ei), data conţinută de ea nu este memorată şi prin urmare, la afişare va
apărea null (obiectul null). Pentru a evita aceasta, s-a utilizat metoda
getCellEditor() a clasei JTable.

⇒ TableCellEditor getCellEditor() - metoda returnează o referinţă


către un obiect dacă o celulă a tabelului este sub editare şi null în caz
contrar. TableCellEditor este o interfaţă care, evident, este
implementată. Fără a intra în amănunte, interfaţa conţine antetul metodei
stopCellEditing(), metodă care are rolul de a stopa editarea şi, prin
urmare, de memorare a tuturor datelor introduse în tabel.
350 Manual de Informatică pentru clasa a XII-a

În continuare, vedem cum putem proiecta capul de tabel. Clasa JTable


conţine metodele:

⇒ TableColumnModel getColumnModel(). TableColumnModel este o


interfaţă implementată de o anumită clasă (DefaultTableColumnModel).
Prin urmare, putem utiliza metodele clasei pornind de la referinţa întoarsă de
metodă. Cu ajutorul lor proiectăm capul de tabel.

⇒ TableColumn getColumn(int index) - returnează o referinţă către


un obiect TableColumn. Un astfel de obiect conţine toate atributele unei
coloane a tabelului. Iată câteva metode, mai importante ale acestui obiect:
 void setHeaderValue(Object ob) - setează obiectul afişat de
coloana respectivă (numele coloanei).
 setPreferredWidth(int lat) - setează lăţimea coloanei.

 setResizable(boolean v); - în mod normal, marginile unei coloane


se pot deplasa astfel încât lăţimea coloanei poate fi stabilită şi de utilizator.
Dacă metoda primeşte ca parametru valoarea false, marginile nu mai pot fi
stabilite de utilizator.
Exemplul 8.36. Secvenţa de mai jos ne arată
cum putem construi un tabel precum cel alăturat,
care conţine numele coloanelor, dar în care,
primei coloane nu i se poate modifica lăţimea
(implicit, şi celeilalte coloane).
table = new JTable(6, 2); Figura 8.36.
TableColumnModel mColoane=table.getColumnModel(); Tabelul rezultat
TableColumn coloana=mColoane.getColumn(0);
coloana.setHeaderValue("Coloana 1");
coloana.setPreferredWidth(150);
coloana.setResizable(false);
coloana=mColoane.getColumn(1);
coloana.setHeaderValue("Coloana 2");
JScrollPane panel = new JScrollPane(table);
table.setPreferredScrollableViewportSize
(new Dimension(200,80));

Alte metode ale clasei JTable:


⇒ void setGridColor(Color c) - setează culoarea liniilor care separă
celulele tabelului.
⇒ void setRowHeight(int inalt) - setează înălţimea liniilor tabelului
(în pixeli).
⇒ void setSelectionBackground(Color c) - setează culoarea liniei
selectate (atunci când se execută clic pe o celulă, se selectează întreaga
linie).
Capitolul 8. Programare vizuală 351

⇒ void setSelectionForeground(Color c) - setează culoarea cu


care se scrie în linia selectată (mai puţin celula în care se editează).
⇒ setIntercellSpacing(Dimension dim) - setează spaţiile între linii
şi coloane. Aceasta nu afectează liniile separatoare dintre celule (vecine), ci
numai spaţiul dintre părţile lor editabile. Primul parametru pentru dim este
pentru linii, al doilea parametru este pentru coloane.
⇒ void setShowHorizontalLines(boolean v) - dacă parametrul este
false, atunci nu mai sunt trasate liniile orizontale ale tabelului.
⇒ setShowGrid(boolean v) - dacă parametrul este false, atunci nu
mai sunt trasate liniile orizontale şi verticale ale tabelului.

8.3. Obiecte grafice. Clasa Graphics

8.3.1. Afişarea imaginilor

Pentru a afişa o imagine aflată într-un fişier, vom scrie o clasă care extinde
clasa Canvas. Obiectele clasei Canvas conţin o metodă numită
paint(Graphics ecr). Această metodă este apelată automat atunci când
componenta respectivă este afişată şi are rolul de a desena componenta.
Observaţi că metoda paint() primeşte ca parametru o referinţă către un obiect al
clasei Graphics şi, pornind de la ea, putem apela toate metodele acestei clase,
cu ajutorul cărora putem afişa imaginea, putem scrie în mod grafic sau desena.
În programul următor, clasa care construieşte componenta ce afişează
imaginea se numeşte Imagine. Clasa Imagine conţine:

1. O referinţă către un obiect de tip Image. Un astfel de obiect poate reţine o


imagine citită. Referinţa este utilizată în metoda paint() pentru a afişa imaginea
respectivă.
2. Un constructor care citeşte imaginea stabileşte mărimea componentei
(setSize()) şi culoarea de fundal (setBackground()). Pentru citirea imaginii
se utilizează metoda clasei Toolkit numită getImage():

⇒ Image getImage(String fisier), unde parametrul reprezintă calea


către fişierul respectiv.
3. Metoda paint() (redefinită, pentru a avea acces). Metoda “desenează”
imaginea şi foloseşte metoda drawImage() a clasei Graphics):

⇒ drawImage(image im, int a, int b, int latime, int


inaltime, this), unde:
352 Manual de Informatică pentru clasa a XII-a

 a,b - coordonatele relative (faţă de colţul din stânga-sus al componentei


care afişează imaginea; în exemplu Imagine) ale colţului din stânga sus
al dreptunghiului care conţine imaginea.
 latime, inaltime - lăţimea şi înălţimea dreptunghiului care conţine
imaginea.
 this - obiectul curent (cel al clasei Imagine). Nu tratăm semnificaţia
generală a acestui parametru.

Observaţii !

 Metoda poate redimensiona imaginea citită (o măreşte sau o micşorează)


prin valorile transmise pentru latime şi inaltime.
 Fişierul imagine se găseşte în Bin (folder-ul curent), dar îi putem ataşa o
cale.
 Exemplul următor conţine o componentă care afişează desenul în centrul ei.
Desigur, imaginea putea acoperi întreaga suprafaţă a componentei Imagine,
dar din considerente didactice, pentru a distinge întreaga suprafaţă unde am
fi putut desena, am preferat să folosim setBackground().

Exemplul 8.37. Programul de mai jos construieşte o


fereastră care afişează o imagine:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Imagine extends Canvas
{ Image im;
Imagine()
{ Toolkit ec=Toolkit.getDefaultToolkit(); Figura 8.37.
im=ec.getImage("calculator.jpg"); Fereastra obţinută
setSize(300,300);
setBackground(Color.YELLOW);
}
public void paint (Graphics ecr)
{ ecr.drawImage(im,50,50,200,200,this); }
}
class Fer extends JFrame
{ Imagine p=new Imagine();
public Fer(String titlu) {
super(titlu);setSize(150,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container x=getContentPane();
x.setLayout(new FlowLayout ());
x.add(p);
setVisible(true);
}
}
Capitolul 8. Programare vizuală 353

public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Imagine"); }
}

8.3.2. Cum scriem ?

Înainte de parcurgerea acestui paragraf, revedeţi 8.3.1., “Afişarea


imaginilor”. Aţi putut observa acolo că metoda Paint primeşte ca referinţă un
obiect al clasei Graphics. Putem utiliza metodele acestui obiect pentru a desena
ceva sau pentru a încărca o imagine care se găseşte într-un fişier. Cele mai
importante metode ale acestei clase sunt:

⇒ void setFont (Font f) - setează obiectul pentru ca scrierea grafică să


se realizeze cu un anumit font;

⇒ void setColor(Color c) - setează culoarea de scriere (desenare);

⇒ drawString(String str, int x, int y) - scrie pe ecran un şir de


caractere. Şirul este scris cu font-ul şi culoarea setate la un moment dat.
Parametrii x şi y reprezintă coordonatele colţului din stânga sus al şirului de
caractere afişat.
Exemplul 8.38. Iată cum arată metoda
Paint() pentru a putea scrie două şiruri
de caractere cu font-uri şi culori diferite:
Figura 8.38. Rezultat
public void paint (Graphics ecr)
{ Font f=new Font("Arial",Font.ITALIC+Font.BOLD, 11);
ecr.setFont(f);
ecr.setColor(Color.red);
ecr.drawString("Un exemplu de scriere",20, 30);
ecr.setColor(Color.black);
Font f1=new Font("CourierNew",Font.BOLD, 14);
ecr.setFont(f1);
ecr.drawString("Scriu cu alta culoare si alt font",20,50);
}

8.3.3. Cum desenăm ?

⇒ drawLine(int x1, int y1, int x2, int y2) - desenează o linie
(segment) între punctele de coordonate (x1,y1) şi (x2,y2).

⇒ drawRect(int x,int y,int latime,int inaltime) - desenează


un dreptunghi pentru care colţul din stânga sus are coordonatele (x,y) şi
de lăţime şi înălţime date.
354 Manual de Informatică pentru clasa a XII-a

⇒ drawRoundRect(int x,int y,int latime,


lat
int inaltime,int lat,int inal) -
inal
desenează un dreptunghi care are colţurile
rotunjite, (vedeţi figura alăturată).

Figura 8.39. Dreptunghi


cu colţurile rontunjite

⇒ void fillRect(int x, int y, int latime, int inaltime), la


fel ca drawRect(), numai că dreptunghiul este colorat în interior.

⇒ void fillRoundRect(int x,int y,int latime,int inaltime,


int lat,int inal) - la fel ca drawRoundRect(), numai că dreptun-
ghiul rotunjit este colorat în interior.

⇒ void drawPolygon(int[] X, int[] Y, int nr) - desenează un


poligon care are nr vârfuri. Coordonatele x ale punctelor se găsesc în
vectorul X, iar coordonatele y ale punctelor se găsesc în vectorul Y. Practic,
primul punct are coordonatele (X[0],Y[0]), al doilea punct are
coordonatele (X[1],Y[1]), ş.a.m.d. În final, pentru a obţine poligonul se
unesc printr-un segment primul şi ultimul punct. Poligonul este oarecare,
deci poate fi şi neconvex.

Exemplul 8.39. Analizaţi secvenţa de mai jos:


ecr.setColor(Color.black);
int[] X= {10, 100,25, 80};
int[] Y= {10, 100,75, 30};
ecr.drawPolygon(X, Y, 4);

⇒ void fillPolygon(int[] X, int[] Y, int nr) - la fel ca mai


sus, numai că poligonul este colorat în interior.

⇒ void drawPolyline(int[] X, int[] Y, int nr) - la fel ca mai


sus, numai că nu se mai uneşte primul punct cu ultimul punct. Astfel se
obţine o succesiune de segmente.

⇒ void drawOval(int x, int y, int latime, int inaltime) -


desenează un oval. Coordonatele x şi y sunt ale colţului din stânga sus al
dreptunghiului circumscris ovalului, iar latime şi inaltime sunt lăţimea şi
înălţimea acelui dreptunghi.

⇒ fillOval(int x, int y, int latime, int inaltime) - la fel ca


mai sus, numai că ovalul este colorat în interior.
Capitolul 8. Programare vizuală 355

⇒ drawArc(int x, int y, int latime, int inaltime, int u1,


int u2) - trasează un arc. Arcul este o porţiune dintr-un oval şi primii 4
parametri sunt ai ovalului căruia îi aparţine arcul. Ultimii doi parametri sunt:
unghiul de unde porneşte arcul şi numărul de grade al arcului. Unghiurile
sunt date în grade.

90

180 0

Figura 8.40. Un cerc şi


gradele sale 270

⇒ fillArc(int x, int y, int latime, int inaltime, int u1,


int u2) - la fel ca drawArc, numai că se consideră sectorul (nu numai
arcul) şi acesta este colorat. De exemplu, în cazul în care latime şi
inaltime reţin aceeaşi valoare, ovalul este de fapt un cerc. În acest caz
avem un sector de cerc.

⇒ drawImage(image im, int a, int b, int latime, int


inaltime, this), unde:
 a,b sunt coordonatele relative (faţă de componenta creată, vezi
setSize()) ale colţului din stânga-sus al dreptunghiului care conţine
imaginea.
 latime, inaltime - lăţimea şi înălţimea dreptunghiului care conţine
imaginea.
 this - obiectul curent (cel al clasei Imagine). Nu tratăm semnificaţia
generală a acestui parametru.

Observaţie ! Metoda a mai fost folosită atunci când am afişat o imagine!


356 Manual de Informatică pentru clasa a XII-a

8.4. Accesarea şi prelucrarea datelor

8.4.1. Citiri şi scrieri utilizând dispozitive standard şi fişiere

În Java, fişierele sunt abordate pornind de la noţiunea de flux. Prin flux vom
înţelege o cale pe care o urmează datele pentru a ajunge de la sursă la destinaţie.
Putem imagina un flux ca o şosea pe care circulă maşini. Astfel, în Java, datele ar
fi maşinile care circulă pe şosea.
Există două tipuri de fluxuri:
A) Fluxuri de intrare - de la sursă (un fişier), către destinaţie (programul), unde
datele sunt prelucrate:

program fişier
Sursa Destinatie
Figura 8.41. Schema fluxului de intrare

B) Fluxuri de ieşire - de la sursă (programul) către destinaţie (fişier), unde se


reţin rezultatele:

fişier program
Sursa Destinatie
Figura 8.42. Schema fluxului de ieşire
Observaţie ! Clasele pe care le studiem în acest paragraf se găsesc în pachetul
java.IO.

Pentru a lucra cu fişiere text, vom utiliza fluxuri de caractere.


A) Fluxuri de intrare - se folosesc pentru citirea fişierelor text.

Pentru a transforma un flux de octeţi într-un flux de caractere, vom utiliza


constructorul clasei InputStreamReader (care extinde clasa Reader):
⇒ public InputStreamReader(InputStream in)
Întrucât clasa FileInputStream extinde clasa InputStream, parametrul in (de
tip InputSTream) poate fi o referinţă către un obiect al clasei FileInputStream.

Pentru a putea lucra cu uşurinţă cu caracterele, vom utiliza clasa


BufferedReader care permite ataşarea fluxului de caractere al unei memorii,
numită buffer. Practic, buffer-ul permite memorarea mai multor caractere citite,
care urmează să fie prelucrate. Constructorul clasei BufferedReader este:

⇒ public BufferedReader(Reader in1).


Capitolul 8. Programare vizuală 357

Întrucât clasa InputStreamReader extinde clasa Reader, parametrul in1 poate


fi o referinţă către un obiect al clasei InputStreamReader.

Clasa BufferedReader conţine metoda readLine() care citeşte din


fişier (flux) o întreagă linie de caractere:

⇒ public String readLine()


throws IOException

Acestea fiind spuse, puteţi analiza programul de mai jos care afişează toate
liniile unui fişier text.
Exemplul 8.40. Dacă creaţi cu NOTEPAD un fişier cu mai multe linii, numit in.txt,
programul îl afişează:
import java.io.*;
public class f {
public static void main (String[ ] args) throws IOException
{ FileInputStream f=new FileInputStream("in.txt");
InputStreamReader fchar=new InputStreamReader (f);
BufferedReader buf = new BufferedReader(fchar);
String linie;
while ((linie=buf.readLine())!=null)
System.out.println(linie);
fchar.close();
}
}

B) Fluxuri de ieşire - se folosesc pentru scrierea fişierelor text.

Clasa FileOutputStream creează un flux de ieşire către un fişier al cărui nume


este transmis ca parametru. Ea extinde clasa OutputStream şi are constructorul:
public FileOutputStream(String nume)
throws FileNotFoundException

Clasa PrintStream conţine mai multe metode print şi println care


funcţionează exact ca System.out.print() şi System.out.print(). Practic,
valoarea care este scrisă în fişier este mai întâi convertită către tipul String, aşa
cum suntem deja obişnuiţi. Clasa este înzestrată cu constructorul:
public PrintStream(OutputStream out)

Exemplul 8.41. Programul de mai jos creează un fişier text (numit out.txt) care
conţine 3 linii, iar fiecare linie conţine câte un şir de caractere:
import java.io.*;
public class f {
public static void main (String[ ] args) throws IOException
{ FileOutputStream f=new FileOutputStream("out.txt");
PrintStream fchar=new PrintStream (f);
fchar.println("O linie");
358 Manual de Informatică pentru clasa a XII-a

fchar.println("Alta linie");
fchar.print("A treia linie");
fchar.close();
}
}

8.4.2. Instalarea soft-ului pentru lucrul cu bazele de date

Java are implementat un mecanism excepţional de lucru cu bazele de date.


Pe lângă faptul că, aşa cum ştim, Java poate rula pe orice sistem de operare,
există posibilitatea ca, prin utilizarea acestui limbaj să putem lucra cu orice bază de
date care are la bază SQL.

Limbajul Java conţine o interfaţă standard numită JDBC (Java DataBase


Connectivity), care oferă accesul la bazele de date accesabile prin SQL.
Clasele şi interfeţele (în sens OOP) care alcătuiesc JDBC se găsesc în pachetul
java.sql. Cu ajutorul acestei interfeţe, dintr-un program Java, se pot transmite
comenzi SQL către baza de date.

Pentru a accesa o bază de date construită cu un anumit SGBD este necesar


să încărcăm clasa care conţine metodele de acces la acel tip de baze de date. În
această carte ne referim la bazele de date realizate în MySQL, prin urmare, va fi
necesară încărcarea clasei care conţine metodele de acces la bazele de date
MySQL. Numele acestei clase este com.mysql.jdbc.Driver.

Clasa respectivă nu este conţinută în mediul de dezvoltare Java. Pentru a o


folosi ea trebuie download-ată. Căutaţi pe internet arhiva mysql-connector-
java-3.1.6. După download-are, dezarhivaţi-o într-un folder cu nume la alegerea
dvs. În exemplu, acest folder este fdex. Pentru a avea acces la ea, calea către
acest folder trebuie trecută în variabila de mediu CLASSPATH (aceasta poate
conţine mai multe căi separate prin ;). Variabila CLASSPATH poate fi accesată din
Start, Settings, Control Panel, System, Advanced, Environment
Variables, dublu-clic pe CLASSPATH. În edit-ul afişat, treceţi calea către ce aţi
download-at, în exemplu C:/fdex/mysql-connector-java-3.1.6. Revedeţi
modul în care am instalat Java pentru că şi acolo am utilizat variabila CLASSPATH.

8.4.3. Lucrul cu baze de date

Acum, că am instalat software-ul necesar, putem prezenta modul în care


lucrăm cu bazele date MySQL. Tot ce prezentăm aici, poate fi observat în
programul aflat la sfârşitul acestui paragraf.
Capitolul 8. Programare vizuală 359

1. Încărcarea clasei care accesează bazele de date. Pentru MySQL, această


clasă este com.mysql.jdbc.Driver. Pentru aceasta vom utiliza o metodă a
clasei Class: forName(String nume_clasa). Dacă operaţia eşuează, inseamnă
că nu am rezolvat corect problema instalării soft-ului, tratată în paragraful anterior.
2. Conectarea la MySQL se realizează cu metoda de mai jos a clasei
DriverManager. Ea are trei parametri, adresa URL acolo unde lucrează MySQL,
numelele utilizatorului (user) şi parola de acces (password). În cazul nostru, ne
conectăm la bazele de date aflate pe propriul calculator, deci adresa URL are un
format specific: jdbc:mysql://localhost/?". Foarte important ! În cazul nostru,
conectarea nu se poate realiza dacă nu este pornit programul EasyPHP.
Connection getConnection
(String url, String user, String password)

Pentru a efectua o operaţie cu bazele de date, cu comenzi SQL, mai precis cele din
MySQL, mai întâi, trebuie să creăm un obiect Statement care transmite comanda
către MySQL (SGBD, în general). Aceasta se realizează cu ajutorul metodei
Statement createStatement() a interfeţei Connection (nu uitaţi că am
încărcat clasa care implementează interfeţele din JDBC).

Pornind de la acest obiect, se pot aplica metode specifice care transmit comenzi
MySQL. În acest manual, vom utiliza două astfel de metode în care şirul primit ca
parametru este o instrucţiune (comanda SQL).
a) int executeUpdate(String sql) - trimite o comandă de punere la zi a
bazei de date. Se foloseşte pentru instrucţiuni MySQL precum CREATE
DATABASE, USE, CREATE TABLE, INSERT

b) ResultSet executeQuery (String sql) - trimite o comandă de


interogare a bazei de date. Imaginaţi rezultatul sub forma unui vector în care
fiecare componentă reţine un rând al rezultatului interogării. Metoda boolean
next() returnează următoarea componentă din vector. Dacă nu s-a ajuns la
sfârşit, se returnează true.

Informaţiile de pe coloane, asociate unui rând al interogării pot fi accesate cu


ajutorul metodei:
String getString (String nume_camp).

În cele ce urmează vom exemplifica câteva operaţii executate în baza de


date şi existente în programul de mai jos.
3. Crearea unei baze de date
...executeUpdate ("CREATE DATABASE baza_de_date");

4. Accesul la o bază de date


...executeUpdate ("USE baza_de_date");
360 Manual de Informatică pentru clasa a XII-a

5. Crearea unui tabel


instr.executeUpdate
("CREATE TABLE tbl (camp1 char(10), camp2 int(4))");

6. Popularea cu date a unui tabel. Observaţi că apostrofurile sunt trecute sub


forma de cod escape:
instr.executeUpdate
("INSERT INTO tbl (camp1,camp2) VALUES(\'valoare1\', 100)");

7. Afişarea unui tabel (interogare)


rez.executeQuery(" SELECT * from tbl");
while (rez.next())
System.out.println(rez.getString("camp1")+
" "+rez.getString("camp2"));

În afara celor prezentate, este nevoie să ştim doar MySQL. Oricum, noţiunile
prezentate aici nu trebuie reţinute decât în principiu, pentru că oricând se poate
consulta o documentaţie. Esenţial este să ştiţi să consultaţi o documentaţie şi s-o
aplicaţi în programele pe care le realizaţi.

Iată şi programul care creează o bază de date, în ea formează un tabel pe care îl


populează cu două linii. În final, se afişează cele două linii ale tabelului:
import java.sql.*;
import java.io.*;
public class test
{ static Connection cnc=null;
static Statement instr=null;
static ResultSet rez=null;
static String URL="jdbc:mysql://localhost/?";
static String USER="root";
static String PAROLA="parolamea";
public static void main(String[] args)
{
// incarcarea clasei care acceseaza baza de date
try { Class.forName("com.mysql.jdbc.Driver").newInstance();
System.out.println("OK ");
}
catch (Exception ex)
{ System.out.println ("Nu gasesc clasa");}

// Conectarea la MySQL
try { cnc=DriverManager.getConnection(URL, USER, PAROLA );
System.out.println ("M-am conectat la MySQL");
}
catch (SQLException ex)
{ System.out.println ("Nu m-am conectat la MySQL "); }
Capitolul 8. Programare vizuală 361

// Crearea unei baze de date


try {
instr= cnc.createStatement();
instr.executeUpdate ( "CREATE DATABASE baza_de_date" );
System.out.println ("am creat baza de date");
}
catch (SQLException e)
{ System.out.println ("nu am creat baza de date"); }
// Accesul la o baza de date
try { instr= cnc.createStatement();
instr.executeUpdate ( "USE baza_de_date" );
System.out.println ("utilizez baza de date");
}
catch (SQLException e)
{ System.out.println ("nu utilizez baza de date");}
// Crearea unui tabel in baza de date
try {
instr= cnc.createStatement();
instr.executeUpdate
("CREATE TABLE tbl (camp1 char(10), camp2 int(4))");
System.out.println ("am creat tabelul");
}
catch (SQLException e)
{System.out.println ("nu am creat tabelul");}
// Popularea unui tabel cu date
try { instr= cnc.createStatement();
instr.executeUpdate
("INSERT INTO tbl (camp1,camp2) VALUES(\'valoare1\', 100)");
instr.executeUpdate
("INSERT INTO tbl (camp1,camp2) VALUES(\'valoare2\', 15)");
System.out.println("Date adaugate");
}
catch (SQLException e)
{ System.out.println ("nu inserare"); }
// Interogare de afisare a unui tabel
try { instr= cnc.createStatement();
rez=instr.executeQuery(" SELECT * from tbl");
while (rez.next())
System.out.println(rez.getString("camp1")+
" "+rez.getString("camp2"));
}
catch (SQLException e) {}
}
}
362 Manual de Informatică pentru clasa a XII-a

Întrebare. Care este modalitatea prin care putem afişa elegant rezultatele
interogării unei baze de date?

Răspuns. Să nu uităm că am studiat o componentă care permite afişarea elegantă


a unui tabel şi anume componenta de tip JTable. În continuare, prezentăm un
program care afişează datele din tabelul tbl al bazei de date construite în cadrul
exemplului anterior:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.event.*;
import java.sql.*;
import java.io.*;
Figura 8.43. Fereastra
class Fer extends JFrame programului propus
{ static Connection cnc=null;
static Statement instr=null;
static ResultSet rez=null;
static String URL="jdbc:mysql://localhost/?";
static String USER="root";
static String PAROLA="parolamea";
static String nr_linii;
static Object[][] linii_date;
public Fer(String titlu) {
super(titlu);
setSize(300,200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// incarcarea clasei care acceseaza baza de date
try
{Class.forName("com.mysql.jdbc.Driver").newInstance();}
catch (Exception ex)
{System.out.println ("Nu gasesc clasa");}
// Conectarea la MySQL
try {cnc=DriverManager.getConnection(URL, USER, PAROLA);}
catch (SQLException ex)
{System.out.println ("Nu m-am conectat la MySQL ");}
//Accesul la o baza de date
try { instr= cnc.createStatement();
instr.executeUpdate ( "USE baza_de_date" );
// gasesc numarul de linii din tabel
rez=instr.executeQuery(" SELECT COUNT(*) AS numar
FROM tbl;");
rez.next();
nr_linii=rez.getString("numar");
// masivul care retine liniile care vor fi afisate
linii_date=new Object[Integer.parseInt(nr_linii)][2];
int i=0;
rez=instr.executeQuery(" SELECT * from tbl");
Capitolul 8. Programare vizuală 363

while (rez.next())
{ linii_date[i][0]=rez.getString("camp1");
linii_date[i][1]=rez.getString("camp2"); i++; }
}
catch (SQLException e)
{System.out.println("erori in utilizarea bazei de date");}
String[] cap_tabel = {"Camp 1", "Camp 2"};
Container x=getContentPane();
x.setLayout(new FlowLayout());
JTable table = new JTable(linii_date, cap_tabel);
JScrollPane panel = new JScrollPane(table);
table.setPreferredScrollableViewportSize
(new Dimension(200, 30));
x.add(panel); setVisible(true);
}
}
public class baza {
public static void main(String args[]) {
Fer fp=new Fer("Tabel"); }
}
Exerciţiu ! Nu uitaţi că în celulele unei componente de tip JTable utilizatorul
poate introduce date (celulele sunt editabile). Scrieţi un program care actualizează
o bază de date pornind de la datele introduse de utilizator într-un tabel.
Observaţie ! Cu programele Java care rulează pe calculatorul nostru se poate
lucra cu bazele de date care se află pe server! Este ceva...

1. Stabiliţi corespondenţa dintre elementele din stânga şi cele din dreapta:


1) gestionar de poziţionare; a) ataşează componente;
2) container; b) răspunde la evenimente;
3) ascultător de evenimente. c) poziţionează componentele.

2. Stabiliţi corespondenţa dintre coloanele din stânga şi cele din dreapta:


1) JPanel; a) mesaj lămuritor;
2) JButton; b) dă o comandă;
3) JTextField; c) mai multe şiruri;
4) JLabel; d) selectează o singură opţiune;
5) JComboBox; e) grupează mai multe componente;
6) JTextArea; f) pentru selecţii multiple;
7) JcheckBox. g) citeşte un şir de caractere.
364 Manual de Informatică pentru clasa a XII-a

3. Scrieţi un program în care o fereastră afişează un buton. La apăsarea


butonului, programul va afişa în fereastra CMD rezoluţia ecranului.
4. Scrieţi un program în care o fereastră afişează două butoane: Buton 1 şi
Buton 2. Ştiind că metoda boolean isEnabled() a clasei JComponent
returnează true dacă butonul este activ şi false, în caz contrar. Faceţi în aşa fel
încât, la apăsarea primului buton, dacă al doilea buton este activ să devină inactiv
şi invers, dacă este inactiv să devină activ.

Figura 8.44. Fereastra propusă

Indicaţie ! Pentru a face un buton activ/inactiv se foloseşte metoda


setEnabled(true/false).

5. Cum se poate ca o fereastră să afişeze cinci


butoane, precum cea de mai jos?

Figura 8.45.
Fereastra propusă

6. Se ştie că pentru a citi o parolă se utilizează o


componentă de tip JPasswordField (clasă care are ca superclasă pe
JTextField). Se ştie de asemenea, că pentru o componentă de tip
JPasswordField, metoda getText() este depreciată şi în locul ei se utilizează
metoda: char[] getPassword(). Se cere ca programul dvs. să citească o
parolă şi să afişeze OK dacă parola introdusă este şirul “Mama” şi NO, în caz
contrar.

Figura 8.46. Exemplu

7. Realizaţi un program în care într-un edit să se poată


introduce numere prin apăsarea unor butoane, ca
alăturat. Extindeţi apoi programul pentru simularea unui
calculator de buzunar.

Figura 8.47. Exemplu

8. Să se scrie un program care conţine trei metode prin care se determină dacă
un număr natural n citit este prim sau nu. Prima dintre ele testează toţi divizorii
numărului de la 2 la n-1, a doua divizorii de la 2 la n / 2 , a treia de la 2 la n.
Capitolul 8. Programare vizuală 365

Pentru citirea numărului, fereastra va conţine o etichetă şi un edit, pentru


selectarea algoritmului se va utiliza o listă, iar după introducerea numărului şi
selectarea algoritmului, un buton va declanşa prelucrarea corespunzătoare.
9. Programul dvs. va efectua o copie a unui fişier text. Numele fişierului care se
copiază va fi introdus într-un edit, iar numele fişierului destinaţie în alt edit.
10. Scrieţi un program care generează un fişier text cu n numere naturale.
Valoarea lui n va fi introdusă cu ajutorul unui edit.

11. Scrieţi un program care creează, pornind de la fişierul anterior, un altul care
conţine aceleaşi numere, dar sortate crescător. Se vor implementa mai mulţi
algoritmi de sortare, iar selecţia celui care va sorta fişierul se va face cu ajutorul
unei liste aflată pe fereastra principală.
12. Scrieţi un program care citeşte două numere reale. Programul va putea afişa
suma, diferenţa, produsul şi câtul lor. Operaţia care se efectuează se va selecta
dintr-un meniu. Rezultatul va fi afişat cu ajutorul unor cutii de dialog predefinite.
13. Creaţi un fişier text în care fiecare linie să conţină numele unei persoane şi
vârsta ei. Datele se introduc secvenţial. Pentru a le introduce, o fereastră va avea
ataşate două edit-uri (unul pentru nume şi altul pentru vârstă) şi un buton. La
apăsarea butonului se va efectua validarea datelor (alfabetic pentru nume şi un
număr natural între 1 şi 99 pentru vârstă).

14. Adăugaţi o listă ferestrei de la problema precedentă din care să se poată


selecta mai multe opţiuni, în urma cărora programul va putea afişa:
a) media vârstelor persoanelor a căror date au fost trecute în fişier;
b) numărul de persoane care au datele trecute în fişier.
15. Scrieţi un program care afişează şi actualizează fişierul creat la problema 13.
Pentru a realiza operaţiile propuse se va utiliza o componentă de tip JTextArea,
iar operaţiile Open, Save şi Save As se vor selecta dintr-un meniu.

16. Scrieţi un program care generează un fişier text care conţine cel puţin
10.000 numere naturale aleatoare. Apoi, scrieţi un alt program care sortează
fişierul prin utilizarea mai multor metode de sortare. Metoda de sortare se va
selecta dintr-o listă. La fiecare sortare, se va estima timpul rămas prin utilizarea
unei componente de tip JProgressBar.

17. Scrieţi un program în care o componentă de tip JTextArea afişează un text


preluat dintr-un fişier text dat. Se cere să se seteze font-ul şi mărimea lui prin
selectarea lor din două liste.
18. Scrieţi un program în care se creează şi se actualizează un fişier text. Textul
se introduce cu ajutorul unei componente de tip JTextArea. Pentru deschiderea
fişierului şi salvarea lui, se utilizează cutii de dialog de tip Open / Save apelabile
dintr-un meniu.
366 Manual de Informatică pentru clasa a XII-a

19. Completaţi programul anterior astfel încât culoarea suprafeţei componentei de


tip JTextArea să poată fi selectată cu ajutorul unei componente de tip
JColorChooser, apelabilă cu ajutorul unui buton aflat pe bara de unelte. De
asemenea, fontul va fi selectat dintr-o listă, iar mărimea lui cu ajutorul unei
componente de tip JSpinner, ambele aflate pe bara cu unelte (componentă de tip
JToolBar).

20. Realizaţi un scurt referat despre tipul de aplicaţie Java numit “applet”.

(pentru verificare, rezolvările se găsesc la pag. 384)

Următoarele aplicaţii se vor realiza în colective formate din câte 5 elevi.


Fiecare problemă rezolvată va fi însoţită de documentaţie. După ce o echipă
rezolvă o problemă, predă documentaţia unei alte echipe, care pe baza ei va
prezenta aplicaţia în faţa clasei. Este esenţial ca documentaţia să fie clară, astfel
încât pe baza ei oricine să poată rula aplicaţia.
O echipă poate fi alcătuită din:
- 1 proiectant al bazelor de date (dacă este cazul);
- 1 designer;
- 3 programatori.
1. “X şi 0”. Toată lumea cunoaşte acest joc, asta e sigur! Realizaţi o interfaţă
grafică prin care să poată fi jucat de către două persoane. Ca idee:
• trebuie să aveţi o comandă care să permită resetarea jocului;
• să se indice momentul în care unul dintre jucători a câştigat runda;
• alternativ, să se afişeze numele jucătorului care este la mutare;
• să fie disponibil un top al celor mai “iscusiţi” utilizatori, etc.
2. “Dame”. Scrieţi un program care afişează toate soluţiile pentru problema celor n
dame. În exemplu, se consideră n=8. După afişarea unei soluţii, pentru a fi afişată
următoarea soluţie, se va apăsa un buton. Pentru afişare, veţi utiliza o componentă
de tip JTable.

3. Refaceţi proiectele de la finalul părţii a doua, realizând interfeţe grafice în Java


care să permită accesul la informaţiile reţinute în bazele de date corespunzătoare.

4. Alegeţi o bază de date pe care a-ţi studiat-o pe parcursul acestui manual şi


realizaţi o aplicaţie completă, care să permită accesul fie prin intermediul
Internetului, fie printr-un program implementat în Java.
ANEXA 1
Instalarea programelor Apache, PHP şi MySQL

Vom instala programele amintite pe calculatorul nostru, având, astfel,


posibilitatea să le studiem fară să fim conectaţi la Internet. În ipoteza în care am
învăţat să le folosim şi dorim să construim un site web, atunci vom închiria spaţiu
pe server şi acolo vom transfera script-urile realizate pe propriul calculator.
Toate programele amintite se găsesc în pachetul “EasyPHP“, iar instalarea
lor se reduce la instalarea lui, care este, de altfel, gratuit. Pachetul conţine:
Apache, PHP, MySQL şi PhpMyAdmin (ultimul conţine script-uri PHP prin care se
facilitează lucrul cu MySQL). Adresa de unde poate fi descărcat pachetul este:
“http://www.easyphp.org/telechargements.php3“.

1. Se download-ează un executabil care, apelat, va instala programele din pachet


(alegeţi opţiunile implicite). Executabilul download-at de noi este ”easyphp1-
8_setup.exe”. În urma rulării acestuia, se creează în Programa Files folder-ul
”EasyPHP1-8” care conţine programele din pachet.
2. Pentru a configura PhpMyAdmin se procedează astfel:
2.1. În folder-ul ”EasyPHP1-8” se găseşte directorul ”phpmyadmin”. Acesta se
copiază în folder-ul ”www” (tot din ”EasyPHP1-8”).
2.2. În ”phpmyadmin” se găseşte fişierul ”config.inc.php”. Se execută dublu
clic asupra sa şi în acest fel, datorită extensiei sale, este apelat browser-ul
(Internet Explorer) care îl deschide. Pentru că dorim să-l modificăm, trebuie
să vizualizăm sursa sa (fişierul aşa cum este, nu interpretat de către browser). Prin
urmare, din meniul browser-ului vom selecta View şi Source. Astfel, va fi apelat
programul Notepad care afişează sursa.
2.2.1. Cu opţiunea Find, căutaţi linia cfg['Servers'][$i]['auth_type'].
Observaţi că după acest şir de caractere găsiţi =”config”. În loc de =”config”
veţi scrie =”cookie”.
2.2.2. Căutaţi şirul $cfg['blowfish_secret']. După acest şir se găseşte
=””. Înlocuiţi =”” cu un şir de caractere la alegerea dvs., de exemplu =”vlad”.
2.2.3. Salvaţi modificările.
2.2.4. Apelaţi adresa ”http://localhost/phpmyadmin”. În acest fel este
apelat fişierul index din directorul ”phpmyadmin” (”index.php”). Trebuie să apară
ce vedeţi în figura următoare:
368 Manual de Informatică pentru clasa a XII-a

Numele de utilizator este


”root”. Fără a introduce
parola, apăsaţi butonul
Autentificare. Se va
afişa ce vedeţi alăturat:

Figura A1.1. Pagina de


autentificare pentru
phpmyadmin

2.2.5. Execuaţi dublu-clic pe link-ul Schimbare parola şi adăugaţi parola


dorită (vezi Fig. A1.3).

Figura A1.2. Pagina de administrare phpMyAdmin

Din acest moment, phpMyadmin se


poate apela prin
”http://localhost/phpmyadmin”.
Desigur, de fiecare dată se va
intoduce parola pe care aţi hotarât
să o aveţi.

Figura A1.3. Pagina de schimbare a parolei


Observaţii !
1) De acum, am instalat pe calculatorul nostru software-ul de server.
2) Programele amintite pot fi instalate şi separat, dar mult mai complicat. Având în
vedere scopul nostru exclusiv didactic, pachetul EasyPHP este soluţia ideală.
3) Pentru a utiliza acest software, introduceţi fişierul index în subfolder-ul ”www”
al pachetului şi apelaţi-l din browser prin ”http://localhost”. Indexul poate
avea extensia html sau php. Înainte de a efectua astfel de apeluri, trebuie lansat
programul EasyPHP. Deschiderea lui se va face din meniul Start/Programs.
ANEXA 2
Dezvoltarea profesională în domeniul IT

„Un om este suma acţiunilor sale, a ceea ce a făcut şi a ceea ce poate face”
Mahatma Gandhi

Pe parcursul acestei anexe veţi învăţa următoarele:

 care sunt etapele planificării carierei

 cum să vă evaluaţi aptitudinile şi interesele

 cum să aflaţi care sunt meseriile care vi se potrivesc

 cum să scrieţi un curriculum vitae

 cum să vă pregătiţi pentru un interviu de angajare

Te afli în faţa unui pas important din viaţa ta, acela în care eşti pus să decizi,
dacă încă nu ai făcut-o, un drum spre viitoarea ta carieră.
Stabilirea planurilor pentru viitor este o sarcină dificilă în societatea noastră.
Procesul de autocunoaştere îţi dezvăluie alternativele de succes, îţi extinde paleta
opţiunilor. Aşa poţi avea convingerea că te afli pe drumul cel bun.

Principalii paşi pe care trebuie să îi aveţi în vedere pentru a avea succes în


planificarea viitoarei voastre cariere sunt, pe scurt, următorii:

1. Identificarea principalelor dumneavoastră aptitudini şi interese.

2. Identificarea meseriilor de interes.

3. Evaluarea posibilelor cariere.

4. Crearea curriculumului vitae şi a portofoliului personal.

5. Pregătirea şi susţinerea interviului de angajare.

6. Stabilirea unui plan de dezvoltare profesională.


370 Manual de Informatică pentru clasa a XII-a

A2.1. Evaluarea aptitudinilor şi intereselor

În domeniul IT, ca în orice domeniu de activitate de altfel, există atât de


multe ocupaţii şi posibile cariere, încât îţi poţi pune întrebarea "cum să-mi aleg
oare cariera care mi se potriveşte cel mai bine?"
În cele ce urmează, veţi învăţa cum să identificaţi acele meserii în care
abilităţile voastre să fie importante şi care să se potrivească cel mai bine cu
preferinţele dvs.
Oricine ştie cât de importante sunt abilităţile în obţinerea sau păstrarea unui
serviciu. Angajatorii urmăresc în CV-ul tău abilităţile relevante pentru postul
solicitat. Ei vor cere detalii despre aceste abilităţi în timpul interviului.
Dar nu numai atât. Nu este destul să ai anumite abilităţi, trebuie să îţi şi placă
să le foloseşti. De exemplu, poţi avea foarte bune abilităţi de comunicare dar totuşi
nu-ţi face mare plăcere să vorbeşti în public sau în faţa unor persoane necunoscute.
Există un adevăr destul de greu de acceptat de mulţi oameni, pe care-l
realizează doar atunci când este deja târziu... Dacă ceea ce facem nu ni se
potriveşte, oricât de mult ne străduim şi oricât de mare ar fi salariul, nu vom putea fi
decât un profesionist mediocru, lipsit de satisfacţie profesională.

A2.2. Identificarea meseriilor de interes

Acum este timpul să începeţi munca de explorare. Este momentul să


adunaţi informaţii din cât mai multe surse de informaţii posibile şi să aflaţi
denumirile posibilelor meserii, care sunt cerinţele pentru aceste meserii şi orice alte
informaţii de acest gen.
Care sunt sursele de informare? Există multe posibilităţi de informare, precum:
 Ziare şi site-uri web – anunţurile de angajare din ziare şi de pe internet
pot fi o sursă importantă de informare. În acest mod, puteţi afla care sunt
cele mai cerute meserii de pe piaţă, care sunt cerinţele pe care angajatorii
le solicită viitorilor angajaţi, etc. Nu uitaţi însă că ceea ce este acum "la
modă" pe piaţă s-ar putea ca în 4-5 ani, când probabil veţi intra pe piaţa
muncii, să nu mai fie tot atât de căutat.
 Agenţiile de plasare a forţei de muncă – angajaţii acestor agenţii vă pot
consilia în căutarea unui loc de muncă potrivit calificărilor şi deprinderilor
voastre. Tot aici puteţi afla informaţii utile despre tendinţa de pe piaţă sau
despre cererea de forţă de muncă.
 Persoane care lucrează în domeniu – probabil că pe cele mai bune
informaţii despre o meserie le aflaţi de la persoane care au această
meserie. Veţi cunoaşte de la aceştia nu doar cerinţele meseriei, dar puteţi
Anexa 2. Dezvoltarea profesională în domeniul IT 371

afla multe date despre mediul în care lucrează, despre programul de lucru,
şi multe alte aspecte utile în luarea unei decizii. De multe ori ceea ce ne
imaginăm noi că înseamnă o meserie nu se potriveşte deloc cu realitatea.
Dacă putem intra în contact direct cu oamenii care lucrează în domeniu
sau dacă putem vizita locul acestora de muncă, ne poate fi de mare ajutor.
 Angajarea temporară pe timpul vacanţelor şcolare, în domenii cât mai
apropiate de meseriile pe care le dorim, ar putea să vă ajute să vă daţi
seama mai bine dacă aceste meserii vi se potrivesc cu adevărat.
În plus experienţa acumulată în acest fel poate fi foarte valoroasă mai
târziu, atunci când veţi scrie un curriculum vitae. Aici putem include şi
munca de voluntariat, care este de multe ori privită cu ochi foarte buni de
către angajatori.

1. Folosind orice sursă de informaţie de care dispuneţi, căutaţi 5 meserii din


domeniul IT care v-ar putea trezi interesul şi scrieţi denumirile acestora pe caiet
sau pe o foaie de hârtie.
2. Pentru una dintre aceste meserii, căutaţi o descriere cât mai detaliată a sa.
Notaţi 5 calităţi cerute de această meserie.
3. Care sunt sarcinile şi responsabilităţile meseriei selectate?
4. Care este nivelul de pregătire necesar pentru meseria selectată la punctul 2?
5. Care sunt condiţiile de muncă ale acestei meserii (număr de ore zilnice de
muncă, cerinţe fizice ale postului, nivelul de stres, etc.) ?
6. Care sunt posibilităţile de avansare în carieră dintr-un astfel de post? Puteţi
folosi pentru a rezolva această sarcină de lucru următoarele adrese web:
http://www23.hrdc-drhc.gc.ca/ch/e/docs/ch_welcome.asp
http://hotjobs.yahoo.com
http://www.careeroink.com/career-reference/
http://www.go.ise.ro/

A2.3. Evaluarea posibilelor cariere

Aţi reuşit probabil să vă faceţi o idee despre carierele din domeniul IT pe


care le-aţi putea urma şi care sunt cerinţele pentru fiecare dintre acestea. Pe de
altă parte, aţi realizat un inventar a ceea ce ştiţi şi doriţi să faceţi.
Acum veţi afla cum să comparaţi ceea ce oferiţi voi şi ceea ce vi se cere
pe piaţa muncii. Veţi vedea care sunt modalităţile prin care vă puteţi da seama
dacă o meserie este potrivită pentru voi sau nu.
372 Manual de Informatică pentru clasa a XII-a

Înainte de a trece la treabă, dorim să mai precizăm câţiva factori de care


trebuie să ţineţi cont în alegerea unei meserii. Nu este suficient să fiţi bine pregătit
pentru o meserie, să aveţi destule calităţi pentru aceasta, să vă placă să folosiţi
abilităţile solicitate. Trebuie să luaţi în calcul şi următorii patru factori importanţi:

• Tendinţa pieţei muncii – diferitele fenomene economice şi sociale, pot


influenţa în timp cererea de forţă de muncă. De exemplu, dacă înainte de
1989, inginerii erau la mare căutare, imediat după revoluţie aceştia au intrat
oarecum în umbră, mulţi dintre ei fiind nevoiţi să se reprofileze. Deşi acum
este foarte căutată o anumită meserie, peste câţiva ani s-ar putea să fie
dificil să găseşti un loc de muncă în meseria respectivă. De aceea, când
alegi o meserie, trebuie să studiezi statisticile şi să afli care vor fi probabil
meseriile căutate peste câţiva ani.

• Lucrul în aer liber – unele persoane preferă să lucreze în aer liber, alţii din
potrivă preferă munca în interior, ca de exemplu într-un birou, în spital,
într-un laborator, etc.

• Munca fizică – vă place şi puteţi desfăşura muncă fizică grea?

• Condiţii periculoase de muncă – mulţi oameni suferă accidente la locul de


muncă. Multe meserii presupun un anumit grad de periculozitate. Întrebarea
este dacă sunteţi dispuşi să vă asumaţi astfel de riscuri sau preferaţi un loc
de muncă cu condiţii sigure?

A2.4. Scrierea unui curriculum vitae

Scrierea unui curriculum vitae poate fi o muncă dificilă pentru cei care nu
sunt familiarizaţi cu acest tip de document, dar există o serie de tehnici care fac
această muncă mai uşoară.
Scopul acestui document este să convingă angajatorul că ar trebui să te
invite la un interviu. Este într-un anumit sens o formă de publicitate, prin care
încerci să atragi atenţia, să stârneşti interesul, să descri abilităţile şi realizările tale
cele mai deosebite şi să invitţi angajatorul să te contacteze.
E foarte important ca un curriculum vitae să fie cât mai concis, angajatorul
nu va petrece foarte multă vreme citindu-l. Acest document va arăta angajatorului
cine eşti, ce şti, ce poţi face, şi care sunt realizările tale.
Prima impresie lăsată de către curriculum vitae este foarte importantă. El
trebuie să fie bine organizat, uşor de citit (spre exemplu, utilizaţi fontul Arial sau
Times New Roman, de mărime 12 pt) şi corect din punct de vedere gramatical.
Observaţie ! Dacă adaugi şi date calendaristice, ordinea acestora va fi cea invers
cronologică.
Anexa 2. Dezvoltarea profesională în domeniul IT 373

Secţiunile importante ale unui curriculum vitae sunt:


 Date personale – nume complet, adresă, număr de telefon, adresă de
e-mail, adresa paginii de web (dacă există).
Observaţie ! Dacă nu aveţi o adresă de e-mail, este momentul să vă creaţi una
acum! Aveţi însă grijă la id-ul ales. Acesta trebuie să fie unul serios, profesional.
 Obiectivul de carieră/obiectivul pentru poziţia solicitată
 Abilităţi speciale şi calificări corespunzătoare obiectivului ales
o referiţi-vă aici la abilităţile descoperite în prima secţiune (A2.1);
o limbi străine cunoscute;
o abilităţi de lucru cu calculatorul;
o certificări obţinute;
o dacă nu ai experienţă relevantă, accentuează aptitudinile pe care
le-ai dezvoltat în termeni de relaţii interpersonale, organizaţionale
sau cunoştinţele referitoare la aspectele postului la care aspiri.
 Educaţie – vei menţiona aici şcolile şi calificările obţinute. Nu este necesar
să treci în CV şcoala primară şi gimnaziul absolvit, decât dacă au fost
instituţii prestigioase. Menţionează numele şcolii absolvite, diploma
obţinută, data şi, dacă doreşti, poţi scrie şi specializarea obţinută (ex.
Bucureşti, Diploma Bacalaureat, Liceul "Ion Neculce", 1999). Numele
diplomelor obţinute nu se abreviază. Toate etapele educaţionale vor fi
scrise în ordine inversă absolvirii lor (cea mai recentă fiind prima).
O sub-secţiune este cea a cursurilor care au relevanţă în raport cu locul de
muncă solicitat.
Proiecte - în această sub-secţiune pot fi scrise proiectele relevante, la care
ai participat.
 Experienţă IT&C - vor fi menţionate atât cunoştinţele teoretice, cât şi cele
practice.
 Experienţa profesională - posturi ocupate până în momentul de faţă,
poziţia ocupată, perioada, responsabilităţi pe care le-ai avut.
Veţi menţiona aici cercetările la care ai participat, certificări obţinute,
premiile şi bursele obţinute (veţi menţiona numele premiului şi numele
instituţiei care a acordat premiul şi data).
 Activităţi de voluntariat, implicare în cadrul comunităţii, asociaţii la
care sunteţi membri
 Articole/cărţi publicate
 Alte activităţi şi interese – activităţi extracurriculare, hobbyuri, etc.
374 Manual de Informatică pentru clasa a XII-a

Din ce în ce mai mult în întreaga Europă, dar şi la noi în ţară, este folosit
formatul european al CV-ului. Formatul european este utilizat, în mod special,
pentru locuri de muncă cu standarde superioare pentru angajaţi.

1. Redactaţi CV-ul personal, folosind formatul european pe care îl puteţi descărca


de pe internet de la adresa: ”http://www.go.ise.ro/uchazeni/cv_eu.rtf”.
2. Descoperiţi greşelile tipice la redactarea unui CV, folosind adresele web:
”http://www.cdm.uwaterloo.ca/restest.asp” şi
”http://www.cdm.uwaterloo.ca/restest2.asp”.
3. Încercaţi să depistaţi şi să corectaţi în CV-ul vostru eventualele greşeli, după
modelul anterior.

A2.5. Pregătirea şi susţinerea interviului


Dacă ai fost invitat pentru un interviu, acesta reprezintă un prim succes. CV-ul
pe care l-ai trimis a stârnit interesul instituţiei/firmei respective pentru persoana ta. Dar,
de acum începe o altă competiţie pe care, de asemenea, trebuie să o câştigi.
Prima condiţie pentru a te prezenta cât mai bine este să nu te gândeşti la
ceilalţi candidaţi, oricât de mulţi ar fi aceştia. Poţi fi singurul care participă la
interviu sau poţi fi unul din mai mulţi candidaţi şi să câştigi.
Pregătirea pentru interviu constă în a învăţa să porţi o conversaţie cu
angajatorul şi să răspunzi la anumite întrebări. Scopul tău este să-l convingi pe
acesta că tu eşti persoana cea mai potrivită pentru postul respectiv, că ai abilităţile
şi deprinderile necesare.
Încearcă să te gândeşti că interviul este de fapt o conversaţie între doi
parteneri egal interesaţi de această conversaţie. Amândoi aveţi informaţii impor-
tante de expus şi de aflat.
Iată câteva sugestii de care ar fi bine să ţii cont în pregătirea pentru interviu:
• Adoptă o ţinută corespunzătoare, curată şi îngrijită. Statisticile spun că
70% din mesajul pe care îl transmiţi este exclusiv vizual. Alege să transmiţi
un mesaj elegant prin ţinuta ta.
Pentru femei, cea mai potrivită este o ţinută clasică, sobră, simplă, dar de
bun-gust. Taiorul şi fusta sau pantalonul pot fi o variantă adecvată de
îmbrăcăminte pentru interviu. Nu exagera cu accesoriile. Nu purta
lănţişoare sau brăţări zgomotoase, încărcate de pietre preţioase sau tot
felul de medalioane. Încearcă să fii cât mai discretă, dar cu haine de
calitate. Nu abuzaţi cu machiajul şi folosiţi doar o bază care să vă acopere
micile imperfecţiuni, nu folosiţi culori tari la fardul de pleoape sau de obraz.
Rujul trebuie să fie cât mai discret, cu un contur foarte fin.
Anexa 2. Dezvoltarea profesională în domeniul IT 375

Bărbaţii pot opta oricând pentru un costum clasic, bine croit, evitând, pe cât se
poate culorile închise precum negru sau bleu-marin. Indiferent cât de cald ar fi
afară, prezintă-te la interviu cu o cămaşă cu mânecă lungă şi cravată.

• Dezvoltă-ţi capacitatea de comunicare.

• Pregăteşte pentru interviu un dosar pe care să îl ai la tine şi care să conţină:


o Date despre companie (rapoarte anuale, materiale privind vânzările, etc).
o Câteva copii suplimentare ale CV-ului şi ale scrisorilor de recomandare.
o O listă cu 10-15 întrebări pe care le poţi pune în timpul interviului şi
care se bazează pe datele pe care le ai despre companie.
o Un pix, foi şi orice alte lucruri care crezi că îţi pot fi utile (acte de studii,
foi matricole, etc.).

• În ziua dinaintea interviului sună la firmă pentru a confirma întâlnirea. Fi


sigur că şti unde trebuie să ajungi şi fă în aşa fel încât să ajungi cu 10
minute înainte de ora fixată. Ia în calcul orice situaţie care poate duce la o
eventuală întârziere şi evit-o. Încearcă să nu ajungi în ultimul moment,
agitat şi transpirat.
• Verifică-ţi ţinuta înainte de interviu. Verifică-ţi hainele, imaginea generală,
aranjează-ţi părul. Exersează zâmbetul!
• Ai grijă la limbajul corpului. Acesta poate da indicii cu privire la starea ta de
spirit. Nu evita contactul vizual cu intervievatorul, dar nu îl fixa cu privirea.
Contactul vizual e una dintre cele mai puternice forme de comunicare,
dovedind încredere şi putere. Nu fă mişcări bruşte, nu-ţi încrucişa braţele. Nu
acoperi faţa cu mâinile, ţine-ţi mâinile departe de faţă.
• Demonstrează entuziasm şi interes sincer.
• Subliniază-ţi abilităţile şi capacităţile. Descrie valoarea ta şi beneficiile pe
care le oferi. Arată cum poţi tu contribui la: 1) creşterea vânzărilor,
2) reducerea costurilor, 3) îmbunătăţirea productivităţii, 4) rezolvarea
problemelor organizatorice.
• Ia notiţe în timpul interviului. Te poţi folosi de aceste notiţe mai târziu, în
timpul interviului. Dacă nu eşti sigur, poţi cere permisiunea mai întâi.
• Lasă intervievatorul să aducă în discuţie problema salariului. Odată
propusă o sumă, aceasta poate fi negociată.
• Fii pregătit să răspunzi la toate întrebările, chiar şi la cele incomode.
Înainte de interviu, pregăteşte un răspuns pentru fiecare întrebare care ar
putea fi o problemă pentru tine şi exersează acest răspuns până vei fi sigur
pe el. Majoritatea întrebărilor care pot apărea în cadrul unui interviu pot fi
prevăzute. În consecinţă, poţi să-ţi pregăteşti din timp răspunsurile.

• Întotdeauna, în următoarele 24 de ore de după interviu, trimite o scrisoare


de mulţumire. Aceasta te poate detaşa de ceilalţi candidaţi.
376 Manual de Informatică pentru clasa a XII-a

Exemple de întrebări frecvente la interviurile pentru angajare:

 Cum aţi descrie cariera dumneavoastră de până acum?


 Care era activitatea dvs. la locul de muncă anterior?
 Ce vă plăcea (nu vă plăcea) la această activitate?
 Care au fost elementele noi pe care le-aţi învăţat acolo?
 De ce aţi părăsit locul de muncă anterior ? (atenţie - nu fiţi prea critic la
adresa fostului şef)
 Descrie-ne şeful tău.
 Descrie-te pe tine însuţi.
 De ce te interesează locul acesta de muncă?
 Cum te-ar descrie prietenii tăi?
 Aţi mai fost şi la alte interviuri?
 Ce ştiţi despre firma noastră? De ce aţi ales-o? (merită să ştiţi ceva despre
firmă – informaţi-vă din timp)
 Ce v-ar plăcea să obţineţi în muncă (în carieră)? Cum vă vedeţi (ce v-ar
plăcea să faceţi) peste 5 (10) ani?
 Care vă sunt punctele forte (slabe), la ce sunteţi bun (mai puţin bun)?
 Care sunt cunoştinţele şi aptitudinile pe care le-aţi aplica la noul loc de
muncă?
 De ce ar trebui să vă încredinţăm dvs. acest loc de muncă? Ce beneficiu
ne-aţi aduce?
 Ce tip de muncă vă face să fiţi încrezător?
 Sunteţi dispus să lucraţi peste programul normal?
 Sunteţi capabil şi dispus să lucraţi ocazional cu un volum mare de muncă?
 Ştiţi să vă odihniţi sau să vă relaxaţi?
 Cum vă petreceţi vacanţele? Care sunt interesele de timp liber?
 Vă place sportul?
 Care este starea sănătăţii dumneavoastră?
 Aveţi ceva întrebări?

Fii tu însuţi !
Fii cinstit !
Fii pozitiv !
ANEXA 3
Caractere HTML

Înainte de prezentarea tabelelor, inserăm textul de mai jos, pentru că au fost


folosite normele W3C ("http://www.w3.org"):
"Portions © International Organization for Standardization 1986
Permission to copy in any form is granted for use with conforming
SGML systems and applications as defined in ISO 8879, provided this
notice is included in all copies."

A3.1. Caractere ISO 8859-1

&#161 ¡ &#191 ¿
&#162 ¢ &#192 À
&#163 £ &#193 Á
&#164 ¤ &#194 Â
&#165 ¥ &#195 Ã
&#166 ¦ &#196 Ä
&#167 § &#197 Å
&#168 ¨ &#198 Æ
&#169 © &#199 Ç
&#170 ª &#200 È
&#171 « &#201 É
&#172 ¬ &#202 Ê
&#173 despărţire în silabe &#203 Ë
&#174 ® &#204 Ì
&#175 ¯ &#205 Í
&#176 ° &#206 Î
&#177 ± &#207 Ï
&#178 ² &#208 Ð
&#179 ³ &#209 Ñ
&#180 ´ &#210 Ò
&#181 µ &#211 Ó
&#182 ¶ &#212 Ô
&#183 · &#213 Õ
&#184 ¸ &#214 Ö
&#185 ¹ &#215 ×
&#186 º &#216 Ø
&#187 » &#217 Ù
&#188 ¼ &#218 Ú
&#189 ½ &#219 Û
378 Manual de Informatică pentru clasa a XII-a

&#190 ¾ &#220 Ü
&#221 Ý &#238 î
&#222 Þ &#239 ï
&#223 ß &#240 ð
&#224 à &#241 ñ
&#225 á &#242 ò
&#226 â &#243 ó
&#227 Ý &#244 ô
&#228 ä &#245 õ
&#229 å &#246 ö
&#230 æ &#247 ÷
&#231 ç &#248 ø
&#232 è &#249 ù
&#233 é &#250 ú
&#234 ê &#251 û
&#235 ë &#252 ü
&#236 ì &#253 ý
&#237 í &#254 þ
&#160 spaţiu incorporat &#255 ÿ
&#258 ~ &#259 `
&#350 { &#351 [
&#354 } &#355 ]

A3.2. Litere greceşti şi semne matematice

&#913 Α &#923 Λ
&#914 Β &#924 Μ
&#915 Γ &#925 Ν
&#916 Δ &#926 Ξ
&#917 Ε &#927 Ο
&#918 Ζ &#928 Π
&#919 Η &#929 Ρ
&#920 Θ &#931 Σ
&#921 Ι &#932 Τ
&#922 Κ &#933 Υ
&#934 Φ &#8230 …
&#935 Χ &#8242 ′
&#936 Ψ &#8243 ″
&#937 Ω &#8254 ‾
&#945 α &#8260 ⁄
&#946 β &#8482 ™
&#947 γ &#8592 ←
&#948 δ &#8593 ↑
&#949 ε &#8594 →
&#950 ζ &#8595 ↓
Anexa 3. Caractere HTML 379

&#951 η &#8596 ↔
&#952 θ &#8706 ∂
&#953 ι &#8719 ∏
&#954 κ &#8721 ∑
&#955 λ &#8722 −
&#956 μ &#8730 √
&#957 ν &#8734 ∞
&#958 ξ &#8745 ∩
&#959 ο &#8747 ∫
&#960 π &#8776 ≈
&#961 ρ &#8800 ≠
&#962 ς &#8801 ≡
&#963 σ &#8804 ≤
&#964 τ &#8805 ≥
&#965 υ &#9674 ◊
&#966 φ &#9824 ♠
&#967 χ &#9827 ♣
&#968 ψ &#9829 ♥
&#969 ω &#9830 ♦
&#8226 •

A3.3. Semne speciale

&#34 " &#8211 –


&#38 & &#8212 —
&#60 < &#8216 ‘
&#62 > &#8217 ’
&#338 Œ &#8218 ‚
&#339 œ &#8220 “
&#352 Š &#8221 ”
&#353 š &#8222 „
&#376 Ÿ &#8224 †
&#710 ˆ &#8225 ‡
&#732 ˜ &#8240 ‰
&#8204 &#8249 ‹
&#8205 &#8250 ›
&#8206 &#8364 €
&#8207
Indicaţii / Răspunsuri
Partea I. Baze de date
1.1.
Barem de corectare şi notare pentru testul 1:
Răspunsurile corecte sunt: 1-b, 2-c, 3-b, 4-d, 5-b, 6-c
6 x 1.5 = 9p
Oficiu 1p
Total 10 p
Barem de notare pentru testul 2:
1. 3 x 0,2 = 0,6 p
2. 8 relaţii x 0,30 p = 2,4 p (0,15 puncte pentru cardinalitatea relaţiei şi 0,15
puncte pentru opţionalitate)
3. 2 x 2 p = 4 p (pentru fiecare relaţie se acordă 4x0,15p=0,60 p; pentru
opţionalitatea relaţiilor, 4x0,15p=0.60 p pentru cardinalitatea relaţiilor, 0,3 p
pentru alegerea entităţii de intersecţie, 0,3 p pentru atributele entităţii de
intersecţie, 0,2 p pentru UID).
4. 2 x 0.5 = 1 p
Oficiu 2p
Total 10 p

1.3.
Barem de corectare şi notare pentru testul de autoevaluare:
Răspunsurile corecte sunt:
1-c, 2-b, 3-b, 4-a.
Răspunsul corect pentru punctul 5
este prezentat în figura alăturată:
Se acordă:
1.5 p x 4 (pentru întrebările 1, 2, 3, 4)
2 p (pentru întrebarea 5)
Oficiu 2 p
Total 10 p
Indicaţii / Rezolvări 381

Partea a II-a. Programare WEB

Capitolul 2.
Rezolvările problemelor propuse:
1.
1.1.
SELECT nume_m FROM materiale
WHERE depozit=’Depozit 2’;
1.2.
SELECT depozit FROM materiale
WHERE nume_m LIKE ‘%Material 3%’;
1.3.
SELECT SUM(cantitate*pret_u)
AS valoare_totsla_materiale
FROM materiale;
1.4.
SELECT depozit,
SUM(cantitate*pret_u)
AS valoare_totala FROM
materiale GROUP BY depozit;
1.5.
UPDATE materiale
SET pret_u=1.1 pret_u
WHERE nume_m=’material 1’;
1.6.
DELETE from materiale
WHERE nume_m=’material 3’;
2.
2.1.
SELECT nume FROM imprumuturi
WHERE nume LIKE ‘%Banca 1%’;
2.2.
SELECT banca, SUM(suma) AS suma_imprumutata FROM imprumuturi
GROUP BY banca;
2.3.
SELECT nume, COUNT(suma) AS nr_imprumuturi FROM imprumuturi
GROUP BY nume;
2.4. Pentru simplitate, descompunem problema în mai multe subprobleme. Ideea
este de a crea un tabel de manevră, să-l numim ”pers”, care să reţină pentru
fiecare persoană totalul sumei pe care a împrumutat-o.

a) Creăm tabelul de manevră ”pers”:


382 Manual de Informatică pentru clasa a XII-a

CREATE TABLE pers AS


SELECT nume, SUM(suma) AS suma_imprumutata
FROM imprumuturi GROUP BY nume;
b) Selectăm răspunsul la problemă, pornind de la tabelul ”pers”:
SELECT nume, suma_imprumutata AS suma_maxima FROM pers
WHERE suma_imprumutata=(SELECT MAX(suma_imprumutata) FROM
pers);
c) Întrucât nu mai este necesar, tabelul de manevră pers este şters.
DROP TABLE pers;
2.5.
a) Rezolvare cu subinterogare:
SELECT DISTINCT nume FROM imprumuturi
WHERE banca IN
(SELECT banca FROM imprumuturi WHERE nume=’Ionescu Grigore’);
b) Rezolvare utilizând mecanismul auto-uniunii:
SELECT DISTINCT B.nume
FROM imprumuturi AS A INNER JOIN imprumuturi AS B
ON A.banca=B.banca AND A.nume=’Ionescu Grigore’;
3.
3.1.
SELECT nume,
COUNT(tip_p) AS nr_proprietati
FROM proprietari, proprietati
WHERE cod=cod_proprietar
GROUP BY cod_proprietar;
3.2
SELECT nume FROM proprietari
WHERE cod NOT IN
(SELECT cod_proprietar FROM proprietati)
3.3.
SELECT cod_proprietar FROM proprietati
WHERE cod_proprietar NOT IN
(SELECT cod FROM proprietari);

3.4.
SELECT nume, SUM(valoare) AS valoare_proprietati
FROM proprietari, proprietati
WHERE cod=cod_proprietar
GROUP BY cod_proprietar
ORDER BY valoare_proprietati DESC;
4
4.1.
SELECT B.nume FROM
baieti AS A, fete AS B, prieteni AS L
Indicaţii / Rezolvări 383

WHERE
A.nume=”mihai’ AND
A.varsta=18 AND
A.cod=L.cod_b AND
L.cod_f=B.cod;
4.2.
SELECT nume FROM fete
WHERE
cod NOT IN (SELECT cod_f FROM prieteni);
4.3.
SELECT nume,
COUNT(cod_f) AS nr_prietene
FROM baieti, prieteni
WHERE cod=cod_b
GROUP BY cod_b;
4.4.
SELECT nume, COUNT(cod_b) AS nr_prieteni
FROM fete,prieteni
WHERE cod=cod_f
GROUP BY cod_f
ORDER BY nr_prieteni DESC
LIMIT 1;
4.5.
SELECT AVG(A.varsta) AS medie_varsta_baieti,
AVG (B.varsta) AS medie_varsta_fete
FROM baieti AS A, fete AS B;

Capitolul 3.
Răspunsurile la testele recapitulative:
1. 1-c, 2-d, 3-b, 4-a; 2. 1-b, 2-a; 3. 1-a, 2-b.

Capitolul 5.
Rezolvările problemelor propuse:
1. a) F, b) A, c) A, d) A. 3.b).
6. Fişierul PHP care afişează formularul este:
<HTML><HEAD></HEAD>
<BODY>
<FORM action="http://localhost/testare.php" method="post">
Introduceti valoarea <BR>
<INPUT type="text" name="valoarea"><BR>
<INPUT type="submit" value="GO">
</FORM></BODY></HTML>
384 Manual de Informatică pentru clasa a XII-a

Script-ul este dat mai jos. Observaţi utilizarea lui require_once() care include în
corpul script-ului fişierul care conţine formularul:
<?
$v=$_POST["valoarea"];
if ($v>=1 && $v<=10 )
echo "OK";
else
{echo "Data introdusa este eronata";
require_once( "test_er.php");}
?>
9.
<FORM action="http://localhost/testare.php" method="post">
a11<INPUT type="text" name="a11"><BR>
a12<INPUT type="text" name="a12"><BR>
a21<INPUT type="text" name="a21"><BR>
a22<INPUT type="text" name="a22"><BR>
<INPUT type="submit" value="GO">
</FORM>
<?
$a11=$_POST["a11"]; $a12=$_POST["a12"];
$a21=$_POST["a21"]; $a22=$_POST["a22"];
echo "<TABLE border=5>";
echo " <TR> <TD> $a11 </TD><TD> $a12 </TD></TR>";
echo " <TR> <TD> $a21 </TD><TD> $a22 </TD></TR>";
echo "</TABLE>";
?>

Partea a III-a. Programare orientată pe obiecte şi programare


vizuală în Java

Capitolul 7.
Rezolvările problemelor propuse:
1. a) 2. c) 3. c) o constantă reală care nu se termină cu f, este considerată
automat ca fiind de tipul double. Prin urmare, este apelată automat metoda cu
parametru de tip double. 4. d) Clasa este înzestrată cu doi constructori
(supraîncărcaţi). Este apelat constructorul cu un singur parametru. Data membru a
este iniţializată implicit cu 0. 27. b). 28. a). 29. d). 30. c).

Capitolul 8.
Rezolvările problemelor propuse:
1. 1-c, 2-a, 3-b. 2. 1-e, 2-b, 3-g, 4-a, 5-d, 6-c, 7-f

S-ar putea să vă placă și