Documente Academic
Documente Profesional
Documente Cultură
Manual de
L&S Info-mat
Copyright 2007-2016 L&S INFO-MAT
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
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
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.
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
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Ă.
Cea mai realistă variantă a relaţiei dintre JUCĂTOR şi ECHIPĂ este aşadar:
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
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
5. Care dintre următoarele fraze pot fi citite din schema de mai jos?
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?
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
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
http://www.acm.org/classics/nov95/toc.html
Capitolul 1. Proiectarea bazelor de date 23
Î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
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:
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.
Figura 1.27.
Entitatea propusă
Figura 1.28.
Schema propusă
28 Manual de Informatică pentru clasa a XII-a
• Modelul tabelar – toate datele sunt memorate sub forma unui singur
tabel, un tablou bidimensional de date.
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.
atributul coloana
instanţa linia
Figura 1.31. Maparea entităţilor
titlu Pk *
autor Pk *
data_apariţiei *
format *
nr_pagini *
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:
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
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.
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
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
• Adaugă puţin umor prezentării tale, dacă acest lucru este posibil.
Păstrează treaz interesul auditorului pe parcursul întregii prezentări.
Î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!
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
⇒ 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]
);
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
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.
⇒ Î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
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”
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.
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].
Tip Descriere
FLOAT Ocupă 4 octeţi.
DOUBLE Ocupă 8 octeţi.
56 Manual de Informatică pentru clasa a XII-a
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’
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.
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
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.
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;
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
Operatorii IS NULL, IS NOT NULL testează dacă o valoare este sau nu NULL
(sunt singurii operatori prin care se testează acest lucru)!
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.
CASE v
WHEN v1 THEN val1
[WHEN v2 THEN val2]
...
[WHEN vn THEN valn]
[ELSE valn+1]
END
CASE 2
WHEN 1 THEN ‘unu’
WHEN 2 THEN ‘doi’
WHEN 3 THEN ‘trei’
ELSE ‘alta valoare’
END;
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
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.
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.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.
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
Exemplul 2.19. Se consideră tabelul din Fig. 2.10, numit ”pers”, care cuprinde
numele şi data naşterii pentru două persoane:
În MySQL, aşa cum s-a arătat, există o valoare specială, numită NULL.
Semnificaţia ei este “nicio valoare“.
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.
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.
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’:
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.
Exemplul 2.27. Presupunem că tabelul principal are drept cheie primară câmpul
"Nume":
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,...)
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
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.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.30.
Exemplu de filtrare
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.
B2) Pentru ştergerea unei coloane, chiar dacă conţine date, se utilizează
instrucţiunea:
ALTER TABLE nume_tabel
DROP COLUMN nume_coloana
Exemplul 2.38. Fie tabelele de mai jos, ambele cu aceleaşi coloane, de acelaşi tip:
UPDATE prs
SET oras=’braila’
WHERE nume IN (‘ioana’, ‘florin’); Figura 2.34. Tabelul actualizat
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
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);
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.
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
Figura 2.48.
Rezultatul obţinut
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
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;
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;
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".
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
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);
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
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.
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.
Figura 2.64.
Tabelul “imprumuturi”
Ce este Internet-ul ?
Protocolul TCP / IP
Ce trebuie să ştim despre site-uri ?
Un program FTP
Cum scriem un fişier HTML?
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.
• 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.
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:
î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ă.
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:
⇒ Î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
Server
Cerere Răspuns
Răspuns
Cerere
Cerere Răspuns
Client 3
Client 1
Client 2
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.
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.
Figura 3.2.
Fereastra de introducere a
datelor de identificare
⇒ 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.
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.
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.
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?
<!-- Un comentariu
pe mai multe linii -->
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.
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...
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.
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:
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
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.
<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:
.Stil {font-size:20pt;
color:red;
background:yellow;
font-style:italic;
width=3cm;
height:4 cm;}
<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>
<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
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>.
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  
Mărimea diferă: pentru <H1> titlul este scris utilizând font-ul de dimensiune
maximă, iar pentru <H6> dimensiunea este minimă.
Atenţie !
normal italic
normal small-caps
C) font-weight – poate lua valorile:
normal bold
100 900
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
Limbajul CSS permite stilizarea la nivel de text prin intermediul unor atribute
care sunt detaliate în cele ce urmează.
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>
left right
center justify
Exemplul 4.22. Pentru a obţine indentarea din figura alăturată, am folosit stilul de
mai jos:
P {text-indent:1cm;}
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>
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ă.
Pentru a forma astfel de liste, avem nevoie de câteva elemente HTML care
vor fi detaliate în cele ce urmează.
⇒ 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
B. risca II. risca
C. ajunge III. ajunge
<OL tyle="A"> <OL tyle="I">
Capitolul 4 – HTML, CSS - primele noţiuni 119
⇒ Elementul UL are atributul type. Valorile pe care le poate lua acest atribut,
precum şi modul în care arată lista se observă în continuare:
Observaţii !
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
Conţinut
Ţesătură (padding)
Bordură (border)
Margine (margin)
Observaţii !
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).
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ă
P {font-size:40pt;
color:RGB(12,56,23);}
body {background-repeat:fixed;}
body {background-repeat:scroll;}
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;}
Observaţie ! Pentru grosimea bordurii se mai pot folosi valorile: thin (subţire),
medium (medie) sau thick (groasă).
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>.
Figura 4.35
Figura 4.36. Exemplu de pagină
care conţine o imagine
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.
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
Observaţii !
<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
Figura 4.43.
Exemplu de tabel
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:
⇒ frame - defineşte părţile care vor fi trasate din chenarul care înconjoară
tabelul. Atributul poate lua valorile:
<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
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>
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>.
⇒ Elementul CAPTION are atributul align. Cele patru valori pe care le poate
lua şi efectul lor, le puteţi observa mai jos:
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.
<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. Î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
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.
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>
Termenul este o traducere a celui din limba engleză, “hyperlink”. Din comoditate, este
1
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>
Exemple:
Exemple:
<A href="#top"> in top </A> <BR> (salt în partea de sus a documentului).
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”.
Exemplul 4.52. Un alt fişier HTML conţine o ancoră către fişierul anterior (numit
“lung.html”):
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.
Exemplul 4.53. Pentru a obţine acest efect, pentru atributul href se va completa
”mailto”, urmat de “:” şi de adresa de e-mail:
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
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>
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:
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
x2,y2
xn,yn
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.
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
Observaţii !
⇒ 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.
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">
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">
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.
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).
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.
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%"> Avem 2 linii. Prima linie ocupă 30% din
înălţimea ferestrei, iar a doua, 70%.
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:
<FRAME src="c:/test.html">
Sus şi jos marginea este de 100 pixeli, iar în stânga şi dreapta este
de 150 pixeli:
? 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.
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>
<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.
<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>
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
<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.
<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>
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)
<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
<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>
<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>
Exemplul 4.70. Pentru semne speciale (se pot lăsa mai multe spaţii între cuvinte):
• 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:
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.
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. …
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.
Figura 4.90.
Pagina propusă
166 Manual de Informatică pentru clasa a XII-a
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:
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.
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:
Î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
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.
<?php
...
?>
<?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
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>
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".
<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>
<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
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
5.5.1. Constante
5.5.2. Variabile
⇒ În PHP este posibilă şi adresarea indirectă, aşa cum rezultă din exemplele
următoare.
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:
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);
?>
Î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;
<?php
$x=1;
$y=-2;
$z="un sir";
$x=$y=$z;
echo ($x);
?>
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.2. Instrucţiunea IF
if (expresie) instructiune1
else 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
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.
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));
?>
<?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...
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...
Multe dintre funcţiile prezentate le-aţi întâlnit dacă aţi studiat limbajul C/C++.
Tabelul următor le prezintă succint:
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.
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.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";
?>
Î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.
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.
Figura 5.19.
Figura 5.20.
Figura 5.21.
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).
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
Î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
⇒ 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().
<?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();
?>
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.
<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>
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.
5.14. Aplicaţii
Figura 5.28.
Pagina principală
204 Manual de Informatică pentru clasa a XII-a
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";
?>
<?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");
<HTML>
<BODY>
<H1> pagina ce ar trebui afisata
</BODY>
</HTML>
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:
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):
<?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;
?>
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.
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.).
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();
?>
<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();
?>
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>";
?>
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
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!
Î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:
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
Totuşi, programele pe care le vom putea realiza după studiul acestui capitol nu vor utiliza
1
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
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.
class prima {
public static void main(String[] args) {
System.out.println("Acesta este primul program Java");}
}
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ţă…
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
6.5. Comentarii
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.
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]
b) Tipuri reale
Observaţie ! Pentru tipul real float, literalii trebuie urmaţi în mod obligatoriu de
litera f. Excepţie fac literalii care reprezintă valori întregi.
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);
Caracter Semnificaţie
\\ backslash
\n newline
\' apostrof
\” ghilimele
\r carriage return
\t tab
\f salt la pagină nouă
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.8. Operatori
În acest paragraf vor fi prezentaţi operatorii utilizaţi în Java.
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.
Î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).
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
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).
Există trei tipuri de operatori logici care acţionează asupra datelor de tip
boolean:
• ! negare logică;
• && şi logic;
• || sau logic.
Operatorul sau logic (binar) acţionează astfel: dacă cel puţin unul din
operanzi este true, rezultatul este true, altfel rezultatul este false.
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).
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
Î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ă.
• 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: *=, /=, %=, +=, -=, <<=,
>>=, &>, ^=, |=.
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ă.
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.
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ă).
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);
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
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 ;.
Exemplul 6.30. Mai jos, puteţi observa o instrucţiune compusă care subordonează
mai multe instrucţiuni vide.
{
;
;
;
}
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
Forma 1.
if (expresie de tip boolean) instrucţiune1 else instrucţiune2
⇒ 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
⇒ 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");
⇒ 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);
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).
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).
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.
6.10. Masive
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.
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]);
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];
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]);
V 1 2 3 4
0 1 2 3
V1 9 9 9
0 1 2
Figura 6.7. Pasul întâi
V 1 2 3 4
0 1 2 3
V1 9 9 9
0 1 2
Man
V 1 2 3 4
0 1 2 3
V1 9 9 9
0 1 2
Man
V 1 2 3 4
0 1 2 3
V1 9 9 9
0 1 2
Figura 6.10. Ultimul pas
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
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
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.
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.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
⇒ 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
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); }
}
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.
Să analizăm programul:
clasa Complex:
Foarte important !
z
Figura 7.1. x y
256 Manual de Informatică pentru clasa a XII-a
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();
}
}
De reţinut !
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
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.
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.
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;}
class Complex {
double x,y;
Complex (double x)
{ this.x=x; }
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
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;
}
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().
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++.
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:
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; }
}
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
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
Î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.
Exemplul 7.20. Pentru şirul s, din exemplul precedent, instrucţiunea afişează ”n”:
System.out.println(s.charAt(1));
7.8.2.3. Subşiruri
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","***" ));
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
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);
}
⇒ 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");
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);
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");
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ă.
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();
}
}
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
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();
}
}
7.10. Polimorfism
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.
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);
}
}
class Muncitor
{ int ore_lucrate;
Muncitor(int ore_lucrate)
{ this.ore_lucrate=ore_lucrate; }
double salariu()
{ return ore_lucrate * 2; }
}
Observaţii !
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
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();
}
}
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(); }
}
⇒ 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(); }
}
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
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).
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
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 {}
Î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.
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"); }
}
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
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) {}
}
}
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
⇒ 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.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()); }
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]+" "); }
}
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);
}
}
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(); }
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
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.
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.
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.
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.
//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
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);
}
}
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.
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Doua butoane"); }
}
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.
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.
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);
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");
}
}
De reţinut !
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
Figura 8.9.
GridLayout(3,3)
Figura 8.10.
GridLayout(3,3,5,8)
De reţinut !
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.
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);
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
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");
}
}
import java.awt.*;
import java.awt.event.*; Figura 8.23.
import javax.swing.*; Fereastra programului
332 Manual de Informatică pentru clasa a XII-a
⇒ 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
3.2.7. Meniuri
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"); }
}
Î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));
⇒ 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
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Fereastra din care pot introduce textul");}
}
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
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
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ă!
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).
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");
}
}
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:
Observaţii !
public class pv {
public static void main(String args[]) {
Fer fp=new Fer("Imagine"); }
}
⇒ drawLine(int x1, int y1, int x2, int y2) - desenează o linie
(segment) între punctele de coordonate (x1,y1) şi (x2,y2).
90
180 0
Î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
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.
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();
}
}
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();
}
}
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
Î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.
// 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
Întrebare. Care este modalitatea prin care putem afişa elegant rezultatele
interogării unei baze de date?
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...
Figura 8.45.
Fereastra propusă
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
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ă).
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.
20. Realizaţi un scurt referat despre tipul de aplicaţie Java numit “applet”.
„Un om este suma acţiunilor sale, a ceea ce a făcut şi a ceea ce poate face”
Mahatma Gandhi
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.
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.
• 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.
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
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.
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ă.
Fii tu însuţi !
Fii cinstit !
Fii pozitiv !
ANEXA 3
Caractere HTML
¡ ¡ ¿ ¿
¢ ¢ À À
£ £ Á Á
¤ ¤ Â Â
¥ ¥ Ã Ã
¦ ¦ Ä Ä
§ § Å Å
¨ ¨ Æ Æ
© © Ç Ç
ª ª È È
« « É É
¬ ¬ Ê Ê
­ despărţire în silabe Ë Ë
® ® Ì Ì
¯ ¯ Í Í
° ° Î Î
± ± Ï Ï
² ² Ð Ð
³ ³ Ñ Ñ
´ ´ Ò Ò
µ µ Ó Ó
¶ ¶ Ô Ô
· · Õ Õ
¸ ¸ Ö Ö
¹ ¹ × ×
º º Ø Ø
» » Ù Ù
¼ ¼ Ú Ú
½ ½ Û Û
378 Manual de Informatică pentru clasa a XII-a
¾ ¾ Ü Ü
Ý Ý î î
Þ Þ ï ï
ß ß ð ð
à à ñ ñ
á á ò ò
â â ó ó
ã Ý ô ô
ä ä õ õ
å å ö ö
æ æ ÷ ÷
ç ç ø ø
è è ù ù
é é ú ú
ê ê û û
ë ë ü ü
ì ì ý ý
í í þ þ
  spaţiu incorporat ÿ ÿ
Ă ~ ă `
Ş { ş [
Ţ } ţ ]
Α Α Λ Λ
Β Β Μ Μ
Γ Γ Ν Ν
Δ Δ Ξ Ξ
Ε Ε Ο Ο
Ζ Ζ Π Π
Η Η Ρ Ρ
Θ Θ Σ Σ
Ι Ι Τ Τ
Κ Κ Υ Υ
Φ Φ … …
Χ Χ ′ ′
Ψ Ψ ″ ″
Ω Ω ‾ ‾
α α ⁄ ⁄
β β ™ ™
γ γ ← ←
δ δ ↑ ↑
ε ε → →
ζ ζ ↓ ↓
Anexa 3. Caractere HTML 379
η η ↔ ↔
θ θ ∂ ∂
ι ι ∏ ∏
κ κ ∑ ∑
λ λ − −
μ μ √ √
ν ν ∞ ∞
ξ ξ ∩ ∩
ο ο ∫ ∫
π π ≈ ≈
ρ ρ ≠ ≠
ς ς ≡ ≡
σ σ ≤ ≤
τ τ ≥ ≥
υ υ ◊ ◊
φ φ ♠ ♠
χ χ ♣ ♣
ψ ψ ♥ ♥
ω ω ♦ ♦
• •
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
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.
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>";
?>
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