Documente Academic
Documente Profesional
Documente Cultură
004.43
lector dr.ing. Liviu ŞERBĂNESCU
Editor şef:
prof. univ. dr. MIHAI POSTOLACHE
Universitatea ”Politehnica” din Bucureşti
Referenţi ştiinţifici:
prof. univ. dr. ing. ANGELICA BACIVAROV
Universitatea ”Politehnica” din Bucureşti
conf. univ. dr. ing. CIPRIAN LUPU
Universitatea ”Politehnica” din Bucureşti
I.Introducere............................................................................................ 10
1.Baze de date şi sisteme de gestiune a bazelor de date...................................10
2.Structura PostgreSQL. Interfaţa pgAdmin3.......................................................11
2.1.Structura PostgreSQL............................................................................................... 11
2.2.Interfaţa pgAdmin3.................................................................................................. 13
3.Mediul CodeLite pentru dezvoltarea aplicaţiilor în C/C++..............................14
II.Limbajul SQL........................................................................................ 17
1.Tabele persistente şi tabele temporare.............................................................17
1.1.Crearea tabelelor...................................................................................................... 17
1.2.Ştergerea tabelelor................................................................................................... 19
1.3.Tabele temporare...................................................................................................... 19
2.Operaţii de editare ce implică un singur tabel..................................................20
2.1.Adăugarea înregistrărilor într-un tabel..................................................................20
2.2.Tipuri de date frecvent utilizate..............................................................................21
2.3.Adăugarea mai multor înregistrări dintr-un alt tabel..........................................21
2.4.Importul datelor în tabel.......................................................................................... 22
2.5.Actualizarea datelor dintr-un tabel........................................................................23
2.6.Ştergerea înregistrărilor dintr-un tabel..................................................................24
3.Operaţii de interogare ce implică un singur tabel............................................24
3.1.Preluarea datelor din tabel......................................................................................25
3.2.Căutarea parţială în şirurile de caractere..............................................................26
3.3.Funcţii de agregare................................................................................................... 26
3.4.Operatorul CAST....................................................................................................... 28
3.5.Expresii condiţionale................................................................................................. 28
3.6.Comenzi SQL ce nu implică tabele..........................................................................29
4.Tipuri de asocieri între înregistrările unor tabele.............................................29
4.1.Asocierea de tip unu la unu (1:1).............................................................................30
4.2.Asocierea de tip unu la mai mulţi (1:N)..................................................................30
4.3.Asocierea de tip mulţi la mulţi (M:N)......................................................................31
4.4.Crearea cheilor primare şi a cheilor externe..........................................................31
4.5.Asigurarea integrităţii referenţiale........................................................................31
5.Operaţii de editare cu mai multe tabele.............................................................32
5.1.Actualizarea datelor din tabele prin utilizarea unor date din alte tabele.........32
5.2.Ştergerea înregistrărilor din tabele prin utilizarea unor date din alte tabele...32
6.Operaţii de interogare cu mai multe tabele. Vederi........................................33
6.1.Combinarea interogărilor (UNION, EXCEPT, INTERSECT)...................................33
6.2.Interogarea mai multor tabele................................................................................34
7.Subinterogări...........................................................................................................38
8.Operaţii cu tablouri de date..................................................................................39
8.1.Tablouri unidimensionale......................................................................................... 39
5
8.2.Tablouri multidimensionale.....................................................................................40
8.3.Căutarea în tablouri.................................................................................................. 40
9.Operaţii cu date de tip XML..................................................................................41
10.Funcţii PostgreSQL...............................................................................................42
10.1.Operaţii cu data calendaristică.............................................................................42
10.2.Operaţii cu dată de tip oră, minut, secundă şi miimi de secundă......................43
10.3.Date de tip UUID / GUID......................................................................................... 44
10.4.Funcţii pentru înlocuirea caracterelor. Căutarea cu şi fără diacritice..............44
11.Tranzacţii. Interogări multiserver......................................................................46
12.Teste rezolvate – gestiune bibliotecă...............................................................48
III.Programarea la nivel de server – plpgSQL.................................52
1.Funcţii de tipul SQL.................................................................................................52
1.1.Funcţii de tip SQL ce nu preiau şi nu întorc nimic..................................................52
1.2.Funcţii SQL ce nu preiau nimic şi întorc un set de înregistrări.............................53
1.3.Funcţii SQL cu transfer prin argument şi cu returnare subset de înregistrări. . .54
1.4.Funcţii SQL cu transfer prin argument şi cu returnare de tip boolean...............55
2.Funcţii de tipul plpgSQL.........................................................................................55
3.Declararea variabilelor. Secvenţe de decizie.....................................................56
4.Parametri de intrare şi ieşire.................................................................................56
5.Implementarea notificărilor..................................................................................58
6.Structuri repetitive.................................................................................................59
7.Construcţia dinamică a interogărilor...................................................................61
8.Funcţii de tip trigger...............................................................................................63
9.Definirea de noi tipuri de date şi supraîncărcarea operatorilor SQL............66
10.Teste rezolvate......................................................................................................71
10.1.Funcţie pentru contorizarea timpilor de parcare................................................71
10.2.Calculul debitelor medii zilnice.............................................................................72
IV.Introducere în limbajul C.................................................................73
1.Organizarea programelor......................................................................................73
1.1.Structura unui program în limbajul C/C++.............................................................74
2.Variabile, alocări, tipuri de date, operatori C/C++............................................74
2.1.Noţiunile de variabilă şi constantă.........................................................................74
2.2.Tipuri de alocare a variabilelor................................................................................75
2.3.Tipuri de variabile...................................................................................................... 75
2.4.Operatorii C/C++....................................................................................................... 76
2.5.Teste........................................................................................................................... 77
3.Implementarea structurilor de control...............................................................77
3.1.Implementarea structurii secvenţiale.....................................................................77
3.2.Implementarea structurii de decizie (alternative, de selecţie)............................78
3.3.Implementarea structurilor repetitive (ciclice)......................................................80
4.Tablouri şi pointeri. Aritmetica pointerilor........................................................83
4.1.Alocarea dinamică. Noţiunea de pointer................................................................83
6
4.2.Noţiunea de tablou................................................................................................... 84
4.3.Alocarea dinamică a memoriei................................................................................85
4.4.Aritmetica pointerilor............................................................................................... 88
4.5.Teste........................................................................................................................... 88
5.Funcţii. Aria de vizibilitate a variabilelor.............................................................89
5.1.Noţiunea de funcţie.................................................................................................. 89
5.2.Structura unei funcţii................................................................................................ 90
5.3.Declararea, explicitarea şi apelul funcţiilor...........................................................90
5.4.Domeniul de vizibilitate al variabilelor..................................................................91
6.Transferul parametrilor în cadrul funcţiilor.......................................................92
6.1.Transferul parametrilor prin valoare......................................................................92
6.2.Transferul parametrilor prin adresă.......................................................................93
6.3.Transferul parametrilor prin referinţă...................................................................93
6.4.Funcţii cu număr variabil de argumente................................................................95
7.Structuri de date. Liste...........................................................................................96
7.1.Noţiunea de structură.............................................................................................. 96
7.2.Declaraţii de tip......................................................................................................... 96
7.3.Liste............................................................................................................................. 97
8.Funcţii recursive. Parcurgerea arborilor...........................................................101
9.Funcţii uzuale din bibliotecile C. Lucrul cu fişiere text..................................103
9.1.Operaţii cu şiruri de caractere...............................................................................103
9.2.Operaţii cu funcţii din biblioteca matematică....................................................104
9.3.Operaţii cu fişiere.................................................................................................... 105
10.Implementarea unui analizor sintactic pentru expresii matematice........105
V.Programarea orientată pe obiecte Limbajul C++....................109
1.Clase şi moşteniri..................................................................................................109
1.1.Noţiunea de clasă şi obiect....................................................................................109
1.2.Operatori specifici C++...........................................................................................109
1.3.Noţiunea de moştenire........................................................................................... 110
2.Constructori şi destructori..................................................................................110
2.1.Constructori............................................................................................................. 110
2.2.Destructori............................................................................................................... 111
2.3.Exemple.................................................................................................................... 111
2.4.Exemple privind ordinea de apel a constructorilor şi destructorilor................113
3.Modificatori şi specificatori de acces. Exemple..............................................115
3.1.Modificatori şi specificatori de acces....................................................................115
3.2.Exemplu privind accesul......................................................................................... 116
4.Funcţii de tip friend şi de tip static....................................................................118
4.1.Funcţii de tipul friend............................................................................................. 118
4.2.Exemplu cu funcţie de tip friend...........................................................................118
4.3.Membrii statici......................................................................................................... 119
4.4.Exemplu cu date de tip static şi funcţii de tip static...........................................120
5.Polimorfism, funcţii virtuale...............................................................................121
7
5.1.Obiecte polimorfice................................................................................................121
5.2.Variabile de tip pointer care punctează la clasele derivate..............................121
5.3.Funcţii virtuale........................................................................................................ 121
5.4.Exemple – polimorfism şi clase abstracte............................................................122
6.Moştenirea multiplă.............................................................................................124
6.1.Exemplu pentru moştenire multiplă simplă.........................................................125
6.2.Exemplu privind moştenirea de tip diamant........................................................125
7.Supraîncărcarea operatorilor..............................................................................126
7.1.Restricţii privind supraîncărcarea operatorilor...................................................126
7.2.Sintaxa formei de apel...........................................................................................127
7.3.Exemple privind supraîncărcarea operatorilor....................................................127
8.Fluxuri de intrare/ieşire.......................................................................................133
8.1.Fluxuri de intrare/ieşire şi obiecte standard........................................................133
8.2.Operaţii de intrare/ieşire cu fişiere.......................................................................134
9.Introducere în funcţii şi clase template............................................................135
10.Tratarea excepţiilor............................................................................................137
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor.........138
1.Biblioteca wxWidgets şi dezvoltarea interfeţelor grafice în C++................138
1.1.Structura unei aplicaţii...........................................................................................138
1.2.Gestiunea evenimentelor.......................................................................................141
1.3.Utilizarea claselor generate de template-uri......................................................143
1.4. Exemplu cu primitive grafice şi evenimente.......................................................148
2.Interfaţarea client-server PostgreSQL în limbajul C/C++..............................152
2.1.Descrierea bibliotecii libpq....................................................................................152
2.2.Exemplu privind apelul funcţiilor libpq în cadrul unui cod C standard.............155
2.3.Exemplu privind utilizarea bibliotecii libpq în cadrul wxWidgets.....................156
3.Generarea în limbajul C a rapoartelor în fişiere format PDF........................161
3.1.Introducere în utilizarea bibliotecii libHARU.......................................................161
3.2.Funcţii uzuale oferite de bibliotecă......................................................................161
3.3.Exemplu de construcţie a unui fişier PDF.............................................................164
VII.Dezvoltarea unor module pentru logistica stocurilor.........168
1.Arhitectura aplicaţiei – LogX...............................................................................168
1.1.Structura de bază a aplicaţiei................................................................................168
1.2.Fluxul informaţional............................................................................................... 170
1.3.Structura tabelelor PostgreSQL............................................................................172
2.Dezvoltarea modulelor SQL/plpgSQL...............................................................175
2.1.Dezvoltarea modulelor SQL/plpgSQL pentru editare........................................175
2.2.Dezvoltarea modulelor plpgSQL pentru rapoarte..............................................176
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul.......177
3.1.Fereastra de acces iFACC....................................................................................... 177
3.2.Fereastra ce conţine panoul cu butoane iFPB.....................................................179
3.3.Fereastra de editare intrări (recepţii) iFEI...........................................................181
3.4.Fereastra de editare ieşiri/livrări iFEBP...............................................................185
8
3.5.Fereastra editare/selecţie nomenclator iFNOM.................................................188
3.6.Fereastra pentru rapoarte / selecţie stoc iFSTSEL..............................................191
4.Dezvoltarea interfeţei SQL/plpgSQL – controale grafice.............................197
4.1.Clasa lxCtrl............................................................................................................... 198
4.2.Clasa lxComboBox.................................................................................................. 199
4.3.Clasa lxDPC.............................................................................................................. 199
4.4.Clasa lxEditN........................................................................................................... 200
4.5.Clasa lxEditT............................................................................................................ 201
4.6.Clasa lxGrid.............................................................................................................. 201
5.Integrarea modulelor aplicaţiei LogX...............................................................203
ANEXE...................................................................................................... 206
1.Secvenţe din sintaxa SQL/postgreSQL simplificată.......................................206
2.Principalele tipuri de variabile în limbajul C.....................................................210
3.Operatori C/C++....................................................................................................211
4.Codul sursă SQL pentru aplicaţia LogX.............................................................213
5.Codul sursă pentru biblioteca LX.......................................................................223
6.Codul sursă pentru aplicaţia LogX.....................................................................230
Bibliografie............................................................................................. 254
9
I.Introducere
I. Introducere
Notă: Toate aplicaţiile necesare realizării testelor şi
dezvoltării aplicaţiei din această carte sunt open sources şi de
asemenea sunt de tip cross-platform (rulează pe sisteme
UNIX/Linux, Windows şi MAC). Cartea se limitează la dezvoltarea
aplicaţiilor de tip desktop, aplicaţii ce prezintă un grad de
siguranţă ridicat comparativ cu aplicaţiile de tip WEB.
10
1.Baze de date şi sisteme de gestiune a bazelor de date
11
I.Introducere
12
2.Structura PostgreSQL. Interfaţa pgAdmin3
13
I.Introducere
14
3.Mediul CodeLite pentru dezvoltarea aplicaţiilor în C/C++
15
I.Introducere
16
II.Limbajul SQL
L
Notă: Pentru o înţelegere mai bună, recomand scrierea comenzilor
SQL (din dreptunghiurile cu colţuri rotunjite) în fereastra pentru
execuţia comenzilor SQL din PgAdmin3 şi testarea acestora prin
modificarea datelor şi/sau a structurii comenzilor.
În PostgreSQL schemele, tabelele, coloanele, secvenţele,
vederile, cheile etc. sunt considerate obiecte, fiecare având un
număr unic asociat (OID). Limbajul SQL este “case insensitive” (nu
ţine cont de literă mare sau mică) însă denumirile obiectelor sunt
“case sensitive”. Denumirile obiectelor ce conţin litere mari vor
fi trecute între ghilimele.
17
II.Limbajul SQL
CREATE
CREATE [TEMPORARY|TEMP]
[TEMPORARY|TEMP] TABLE
TABLE
table_name
table_name ([{
([{ column_name
column_name data_type
data_type
[[ column_constraint
column_constraint [[ ...
... ]] ]}])
]}])
Notă: parantezele drepte din expresie indică o expresie opţională,
iar acoladele o secvenţă ce se repetă şi este separată prin
virgulă. De asemenea simbolul “|” semnifică “sau”, iar
column_constraint [ ... ] poate fi:
[[ CONSTRAINT
CONSTRAINT constraint_name
constraint_name ]]
{NOT
{NOT NULL|NULL|UNIQUE
NULL|NULL|UNIQUE index_parameters|
index_parameters|
PRIMARY
PRIMARY KEY
KEY index_parameters
index_parameters || CHECK
CHECK (( expression
expression )}
)}
unde:
• PRIMARY KEY reprezintă cheia primară de ordonare (câmpul sau
câmpurile după care se face ordonarea);
• NOT NULL semnifică faptul că nu se acceptă valori vide (fără
date) pentru câmpul respectiv;
• CHECK permite verificări suplimentare (de exemplu: temp_max<50).
Ex.: Crearea unui tabel cu denumirea parm în cadrul schemei c2,
câmpul data este de tipul dată calendaristică și va fi inițializat
cu data curentă atunci când se adaugă o nouă înregistrare, la fel
se procedează și pentru câmpul moment, câmp ce conţine ora, minutul
secunda și fracţiunea de secundă. Tabelul conține valorile măsurate
dintr-un proces.
CREATE
CREATE TABLE
TABLE pic.parm(data
pic.parm(data date
date DEFAULT
DEFAULT CURRENT_DATE,
CURRENT_DATE,
moment
moment time DEFAULT CURRENT_TIME, modul
time DEFAULT CURRENT_TIME, modul varchar(10),
varchar(10),
pct
pct varchar(50),par
varchar(50),par varchar(15),val
varchar(15),val numeric,um
numeric,um char(10),
char(10),
idx
idx serial
serial PRIMARY
PRIMARY KEY);
KEY);
Notă: Câmpul sau câmpurile care constituie cheia primară nu pot
avea valori NULL
CREATE
CREATE TABLE
TABLE pic.hidro
pic.hidro
(( afluent
afluent character
character varying(80),
varying(80),
temp_min
temp_min integer,
integer, nivel_min
nivel_min int,
int,
temp_max
temp_max integer,
integer, nivel_max
nivel_max int,
int,
precipitatii
precipitatii numeric,
numeric,
datac
datac date,
date,
CONSTRAINT
CONSTRAINT k_hidro
k_hidro PRIMARY
PRIMARY KEY(afluent,
KEY(afluent, datac),
datac),
CONSTRAINT
CONSTRAINT hidro_check
hidro_check CHECK
CHECK (temp_min
(temp_min << temp_max),
temp_max),
CONSTRAINT
CONSTRAINT hidro_precipitatii_check
hidro_precipitatii_check
CHECK
CHECK (precipitatii
(precipitatii >=>= 0::numeric),
0::numeric),
CONSTRAINT
CONSTRAINT hidro_temp_max_check CHECK (temp_max << 50)
hidro_temp_max_check CHECK (temp_max 50)
);
);
Operatorul rezoluţie “::” este utilizat pentru specificarea
tipului unui câmp. Tipul int este acelaşi cu integer.
Cheia primară poate fi constituită din unul sau mai multe câmpuri,
iar declaraţia acesteia are forma:
18
1.Tabele persistente şi tabele temporare
CONSTRAINT
CONSTRAINT nume_cheie_primara
nume_cheie_primara PRIMARY
PRIMARY KEY(câmp1,câmp2,câmp3,..)
KEY(câmp1,câmp2,câmp3,..)
Crearea unui tabel cu structură identică se va realiza prin
instrucţiunile: create table pic.hidro2 as table pic.hidro;
create table pic.hidro2 as table pic.hidro;
Ex.: DROP
DROP TABLE
TABLE IF
IF EXISTS
EXISTS tx1;
tx1;
CREATE
CREATE TEMPORARY
TEMPORARY TABLE
TABLE tx1(a
tx1(a serial,
serial, bb int);
int);
--sau
--sau
DROP
DROP TABLE
TABLE IF
IF EXISTS
EXISTS tx1;
tx1;
CREATE
CREATE TEMP TABLE tx1(a
TEMP TABLE tx1(a serial,
serial, bb int);
int);
Pentru testarea vizibilităţii tabelului temporar se poate
realiza testul următor:
DROP
DROP TABLE
TABLE IF
IF EXISTS
EXISTS tx1;
tx1;
CREATE
CREATE TEMPORARY
TEMPORARY TABLE
TABLE tx1(a
tx1(a serial,
serial, bb int);
int);
--
-- sau
sau CREATE
CREATE TEMP
TEMP TABLE
TABLE tx1(a
tx1(a serial,
serial, bb int);
int);
INSERT
INSERT INTO
INTO tx1(b)
tx1(b) VALUES
VALUES (12),(22),(1),(2);
(12),(22),(1),(2);
SELECT
SELECT ** FROM
FROM tx1;
tx1; SELECT
SELECT USER;--
USER;-- afiseaza
afiseaza utilizatorul
utilizatorul curent
curent
--
-- crează
crează un
un nou
nou utilizator
utilizator bubu
bubu
DROP
DROP ROLE
ROLE IF
IF EXISTS
EXISTS bubu;
bubu; –-–- se
se presupune
presupune că
că există
există acest
acest drept
drept
CREATE
CREATE ROLE
ROLE bubu
bubu PASSWORD
PASSWORD '1234';
'1234';
SET
SET ROLE
ROLE bubu;
bubu; -–-– sau
sau delogare
delogare şişi logare
logare cu
cu noul
noul utilizator
utilizator
SELECT
SELECT USER;
USER; SELECT
SELECT ** FROM
FROM tx1;
tx1; --tabelul
--tabelul tx1
tx1 nunu mai
mai există
există
--
-- delogare
delogare sisi logare
logare cucu vechiul
vechiul utilizator
utilizator sau
sau
SET
SET ROLE
ROLE postgres
postgres –- –- sau
sau utilizatorul
utilizatorul afişat
afişat lala început
început
SELECT
SELECT USER;
USER; SELECT
SELECT ** FROM
FROM tx1;
tx1;
La reconectare, tabelul temporar nu mai există, în momentul
19
II.Limbajul SQL
20
2.Operaţii de editare ce implică un singur tabel
INSERT
INSERT INTO
INTO pic.hidro(afluent,precipitatii,datac,
pic.hidro(afluent,precipitatii,datac, temp_min,temp_max)
temp_min,temp_max)
VALUES
VALUES ('Tuşnad',
('Tuşnad', 0.25,
0.25, '30.12.2007',
'30.12.2007', 4,
4, 8),
8),
('Tuşnad',
('Tuşnad', 0.25,
0.25, '31.12.2007',
'31.12.2007', 5,
5, 8),('Malnaş',
8),('Malnaş', NULL,
NULL, '31.12.2007',3,9),
'31.12.2007',3,9),
('Sebeş',
('Sebeş', 0.11,
0.11, '29.12.2007',4,
'29.12.2007',4, 8),('Sebeş',
8),('Sebeş', 0.11,
0.11, '30.12.2007',3,
'30.12.2007',3, 7);
7);
21
II.Limbajul SQL
22
2.Operaţii de editare ce implică un singur tabel
23
II.Limbajul SQL
--
-- pune
pune valoarea
valoarea 14 14 acolo
acolo unde
unde câmpul
câmpul a2a2 are
are valoarea
valoarea 'C1'
'C1'
update
update pic.t1
pic.t1 SET
SET a3
a3 == 14
14 WHERE
WHERE a2a2 == 'C1';
'C1';
--
-- poate
poate să
să nu
nu fie
fie afectata
afectata nicio
nicio inregistrare
inregistrare sau sau
--
-- pot
pot fi
fi modificate
modificate toate
toate înreg.
înreg.
--
-- ORDONARE
ORDONARE după
după mai
mai multe
multe coloane
coloane
select
select ** from
from pic.t1
pic.t1 order
order byby a1a1 ASC,
ASC, a2
a2 DESC;
DESC;
-- se poate seta si cu valoarea
-- se poate seta si cu valoarea NULL NULL
UPDATE
UPDATE pic.t1
pic.t1 SET
SET a3
a3 == NULL
NULL WHERE
WHERE a2='B1'
a2='B1' AND
AND a3a3 >> 100;
100;
UPDATE pic.t1 SET a3 = 77 WHERE a3
UPDATE pic.t1 SET a3 = 77 WHERE a3 IS NULL; IS NULL;
--
-- adauga
adauga valoarea
valoarea 11 lala toate
toate inregistrarile
inregistrarile al al caror
caror camp
camp a3
a3 conţine
conţine
-- o valoare impară (a3%2 este diferit de zero,
-- o valoare impară (a3%2 este diferit de zero, adica TRUE) adica TRUE)
UPDATE
UPDATE pic.t1
pic.t1 SET
SET a3
a3 == a3
a3 ++ 11 WHERE
WHERE a3
a3 %% 22 <>
<> 0;
0;
-- concatenare
-- concatenare
UPDATE
UPDATE pic.t1
pic.t1 SET
SET a2
a2 == a2
a2 ||
|| '_Q'
'_Q' WHERE a3 <=
WHERE a3 <= 100;
100;
24
3.Operaţii de interogare ce implică un singur tabel
25
II.Limbajul SQL
26
3.Operaţii de interogare ce implică un singur tabel
cadrul SELECT:
• avg(expresie): media aritmetică a expresiei;
• count(expresie): numărul de înregistrări pentru care valoarea expresiei nu este
nulă, de ex. count(*):total înregistrări;
• max(expresie): valoarea maximă pentru expresie;
• min(expresie): valoarea minimă pentru expresie;
• sum(expresie): suma expresiei;
Notă: (expresie) poate fi un câmp sau rezultatul unor operaţii
aplicate mai multor câmpuri
Ex.1:
--
-- SUMA
SUMA
SELECT
SELECT sum(a3)
sum(a3) from
from pic.t1;
pic.t1; select
select sum(a3)
sum(a3) as
as xx from
from pic.t1;
pic.t1;
--MEDIA ARITMETICA
--MEDIA ARITMETICA
select avg(a3) as media from pic.t1;
select avg(a3) as media from pic.t1;
--
-- numărul
numărul total
total de
de înreg.
înreg.
select
select count(*) as nr_t
count(*) as nr_t from
from pic.t1;
pic.t1;
Ex.2:
/*suma
/*suma după
după câmpul
câmpul a2
a2 atunci
atunci când
când acesta
acesta începe
începe cu
cu BB sau
sau b*/
b*/
SELECT
SELECT a2,SUM(a3) AS suma FROM pic.t1 WHERE a2 ILIKE 'b%' GROUP
a2,SUM(a3) AS suma FROM pic.t1 WHERE a2 ILIKE 'b%' GROUP BY
BY a2;
a2;
-- calculeaza media aritmetica ptr. a3 grupata
-- calculeaza media aritmetica ptr. a3 grupata dupa a2 dupa a2
SELECT
SELECT a2,
a2, AVG(a3)
AVG(a3) AS
AS media
media FROM
FROM pic.t1
pic.t1 GROUP
GROUP BY
BY a2;
a2;
-- determina val max ptr. a3 grupata dupa
-- determina val max ptr. a3 grupata dupa a2 a2
SELECT
SELECT a2,
a2, MAX(a3)
MAX(a3) AS
AS maximum
maximum FROM
FROM pic.t1
pic.t1 GROUP
GROUP BY
BY a2;
a2;
-- determina val max ptr a3 ptr. intregul
-- determina val max ptr a3 ptr. intregul tabel tabel
SELECT
SELECT MAX(a3)
MAX(a3) AS
AS maximum2
maximum2 FROM
FROM pic.t1;
pic.t1;
-- calc. numarul de inregistrari
-- calc. numarul de inregistrari
SELECT
SELECT COUNT(*)
COUNT(*) FROM
FROM pic.t1;
pic.t1;
--calc.
--calc. nr.valori identice
nr.valori identice pentru
pentru câmpul
câmpul a2,
a2, grupate
grupate după
după a2
a2
SELECT
SELECT a2,COUNT(a2) as nr_val_identice FROM pic.t1 GROUP BY
a2,COUNT(a2) as nr_val_identice FROM pic.t1 GROUP BY a2;
a2;
Ex.3:
--numărul
--numărul dede locuitori
locuitori din
din fiecare
fiecare regiune
regiune
SELECT
SELECT regiune,
regiune, SUM(nr_locuitori)
SUM(nr_locuitori) as as nrRegLoc
nrRegLoc FROM
FROM pic.t4
pic.t4 GROUP
GROUP BYBY
regiune;
regiune;
/*
/* campurile
campurile din
din GROUP
GROUP BY
BY vor
vor fi
fi campurile
campurile din
din cadrul
cadrul SELECT
SELECT (cu
(cu
exceptia functiilor de agregare)*/
exceptia functiilor de agregare)*/
--afiseaza
--afiseaza DOAR
DOAR regiunile
regiunile ce ce au
au peste
peste 150
150 de
de locuitori
locuitori
SELECT
SELECT regiune, SUM(nr_locuitori) as nrRegLoc FROM
regiune, SUM(nr_locuitori) as nrRegLoc FROM pic.t4
pic.t4 GROUP
GROUP BYBY
regiune
regiune HAVING
HAVING SUM(nr_locuitori)
SUM(nr_locuitori) >> 150;150;
--
-- WHERE
WHERE se
se referă
referă la
la FIECARE
FIECARE înregistrare
înregistrare în în parte
parte
--
-- HAVING
HAVING se
se referă
referă la
la rezultatul
rezultatul unei
unei funcţii
funcţii dede agregare
agregare
--(sum,avg,count,min,max,etc)
--(sum,avg,count,min,max,etc)
SELECT
SELECT localitate
localitate FROM
FROM pic.t4;
pic.t4;
--
-- se va elimina afisarea de
se va elimina afisarea de mai
mai multe
multe ori
ori aa înregistrărilor
înregistrărilor identice
identice
SELECT
SELECT DISTINCT
DISTINCT localitate
localitate FROM
FROM pic.t4;
pic.t4;
--
-- DISTINCT
DISTINCT -- elimină
elimină inregistrările
inregistrările multiple
multiple ---- pastreaza
pastreaza oo singura
singura
inregistrare
inregistrare
27
II.Limbajul SQL
28
3.Operaţii de interogare ce implică un singur tabel
CASE
CASE WHEN
WHEN condition
condition THEN
THEN result
result
Sintaxa simplificată: [WHEN
[WHEN ...]
...]
[ELSE
[ELSE result]
result]
END
END
SELECT
SELECT (temp_min+temp_max)/2.0
(temp_min+temp_max)/2.0 asas temp_medie,
temp_medie,
CASE
CASE WHEN( (temp_min+temp_max)/2.0 )) <=10
WHEN( (temp_min+temp_max)/2.0 <=10 THEN
THEN 'F.RECE'
'F.RECE'
WHEN(
WHEN( ((temp_min+temp_max)/2.0 ) > 10 )AND
((temp_min+temp_max)/2.0 ) > 10 )AND
(((temp_min+temp_max)/2.0
(((temp_min+temp_max)/2.0 )) <15
<15 )) THEN
THEN 'RECE'
'RECE'
WHEN
WHEN ((temp_min+temp_max)/2.0
((temp_min+temp_max)/2.0 )) >> 25
25 THEN
THEN 'CALDA'
'CALDA'
ELSE
ELSE 'NORMALA'
'NORMALA'
END
END AS
AS evaluare
evaluare
FROM
FROM pic.hidro
pic.hidro
Rezultatul expresiei este pus în noul câmp evaluare.
3.6. Comenzi SQL ce nu implică tabele
Sunt prezentate câteva comenzi SQL ce nu implică tabele:
SELECT
SELECT 3;
3; --
-- afişează
afişează 33
SELECT
SELECT 3+2;
3+2; --afişează
--afişează 55
select
select CURRENT_DATE;
CURRENT_DATE; --data
--data curenta
curenta ---- de
de tip
tip date
date
select
select CURRENT_TIME;
CURRENT_TIME; --ora
--ora curenta
curenta --
-- de
de tip
tip time
time
select
select CURRENT_DATE+CURRENT_TIME;
CURRENT_DATE+CURRENT_TIME; -- -- rezultatul
rezultatul este
este dede tip
tip timestamp
timestamp
SELECT
SELECT CURRENT_DATE+1;
CURRENT_DATE+1; -- -- ziua
ziua urmatoare
urmatoare dede tip
tip date
date
SELECT
SELECT CURRENT_DATE-1;
CURRENT_DATE-1; -- -- ziua
ziua anterioara
anterioara
SELECT
SELECT CURRENT_TIME+'2:3'::time;
CURRENT_TIME+'2:3'::time; -- -- peste
peste 22 ore
ore si
si 33 minute
minute (timestamp)
(timestamp)
SELECT
SELECT CURRENT_TIME-'2:3'::time;
CURRENT_TIME-'2:3'::time; -- -- acum
acum 22 ore
ore si
si 33 minute
minute
SELECT
SELECT '2012-05-27'::date
'2012-05-27'::date -- '2:15'::time;
'2:15'::time;
--rezultat
--rezultat timestamp
timestamp ziua
ziua 26.05.2012
26.05.2012 ora
ora 21:45
21:45
SELECT
SELECT '2:23'::time
'2:23'::time -- '1:15'::time;
'1:15'::time; --rezultat
--rezultat de de tip
tip interval
interval
29
II.Limbajul SQL
30
4.Tipuri de asocieri între înregistrările unor tabele
31
II.Limbajul SQL
32
5.Operaţii de editare cu mai multe tabele
DELETE
DELETE FROM
FROM pic.t11
pic.t11 USING
USING pic.t12
pic.t12 WHERE
WHERE t11.a=t12.c
t11.a=t12.c AND
AND t12.d<30;
t12.d<30;
33
II.Limbajul SQL
interogare#1
interogare#1 INTERSECT
INTERSECT [ALL]
[ALL] interogare#2
interogare#2
Prin utilizarea comenzii INTERSECT, vor fi selectate doar
înregistrările comune din cadrul interogărilor, de exemplu:
SELECT
SELECT afluent
afluent FROM
FROM pic.hidro
pic.hidro INTERSECT
INTERSECT
SELECT afluent FROM pic.rauri;
SELECT afluent FROM pic.rauri;
c) DIFERENŢA: diferenţa între două tabele cu aceeaşi structură
(operaţie pe verticală – la nivel de înregistrări)
interogare#1
interogare#1 EXCEPT
EXCEPT [ALL]
[ALL] interogare#2
interogare#2
Prin utilizarea comenzii EXCEPT vor fi selectate doar
înregistrările care se regăsesc în rezultatul primei interogări,
dar care nu se regăsec şi în rezultatul celei de a doua interogări.
SELECT
SELECT afluent
afluent FROM
FROM pic.rauri
pic.rauri
EXCEPT
EXCEPT
SELECT
SELECT afluent
afluent FROM
FROM pic.hidro;
pic.hidro;
SELECT
SELECT a,b
a,b FROM
FROM pic.t11
pic.t11
EXCEPT
EXCEPT
SELECT
SELECT c,d
c,d FROM
FROM pic.t12;
pic.t12;
--
-- t12
t12 except
except t11
t11
select
select c,d
c,d from
from pic.t12
pic.t12
except
except
select
select a,b
a,b from
from pic.t11;
pic.t11;
În toate cazurile, câmpurile din cadrul selecţiilor trebuie
să fie de acelaşi tip, altfel fiind necesară convertirea acestora
la tipul respectiv prin utilizarea operatorului CAST.
Pentru ordonarea rezultatului introducem un alias (în acest
caz se numeşte par) pentru tabelul rezultat.
select
select par.x,par.y
par.x,par.y FROMFROM
(select
(select cc as
as x,d
x,d asas yy from
from pic.t12
pic.t12
except
except
select
select aa as
as x,b
x,b as
as yy from
from pic.t11)
pic.t11) par
par
ORDER
ORDER BY
BY par.x;
par.x;
34
6.Operaţii de interogare cu mai multe tabele. Vederi
35
II.Limbajul SQL
36
6.Operaţii de interogare cu mai multe tabele. Vederi
37
II.Limbajul SQL
7. Subinterogări
Subinterogările permit crearea unui tabel în cadrul unei
interogări. Acestea sunt scrise între paranteze rotunde şi au un
ALIAS.
Subinterogările scalare sunt interogările care întorc un
singur rând şi o singură coloană. Ele se scriu între paranteze
rotunde. În cazul în care subinterogarea întoarce mai multe
înregistrări, vom avea eroare. În cazul în care nu întoarce nicio
înregistrare, valoarea rezultată a interogării este considerată
NULL. În exemplul următor sunt afişaţi toţi afluenţii din tabelul
pic.rauri şi mediile precipitaţilor acolo unde acestea au fost
introduse:
SELECT
SELECT rau,
rau, afluent,
afluent,
(SELECT
(SELECT avg(precipitatii)
avg(precipitatii) FROMFROM pic.hidro
pic.hidro
WHERE
WHERE rauri.afluent
rauri.afluent == hidro.afluent)
hidro.afluent)
AS
AS media
media FROM
FROM pic.rauri;
pic.rauri;
Expresii specifice subinterogărilor:
EXISTS EXISTS (subquery) − întoarce true dacă subinterogarea
EXISTS (subquery)
are ca rezultat cel puţin o înregistrare, altfel întoarce
false;
IN expression
expression IN
IN (subquery)
(subquery) − caz în care subinterogarea
întoarce o singură coloană. Verifică dacă expresia se află
în rezultatul subinterogării sau Row Row constructor
constructor IN
IN (subquery)
(subquery)
− caz în care subinterogarea întoarce acelaşi număr de
coloane ca şi constructorul înregistrare (row constructor).
Notă: Constructorul de înregistrare formează o înregistrare
utilizând cuvântul ROW, de ex.: ROW(12,14,'TEST')
ROW(12,14,'TEST') .
Un alt exemplu:
SELECT
SELECT ROW(3,9,'Malnaş')
ROW(3,9,'Malnaş')
IN(SELECT
IN(SELECT temp_min,temp_max,afluent
temp_min,temp_max,afluent
FROM
FROM pic.hidro)
pic.hidro) AS
AS VERIFICA;
VERIFICA;
NOT IN – asemănătoare cu IN, dar cu rezultatul negat.
ALL expression
expression ALL (subquery) – caz în care subinterogarea
ALL (subquery)
întoarce o singură coloană – verifică dacă expresia
satisface condiţia pentru fiecare înregistrare din
subinterogare sau Row constructor ALL (subquery)
Row constructor ALL (subquery) – caz în care
subinterogarea întoarce acelaşi număr de coloane ca şi
constructorul de înregistrare row constructor.
Ex.: Adaugă în pic.t13, înregistrările din pic.t14 pentru care
valoarea câmpului NU se regăseşte în pic.t13
38
7.Subinterogări
INSERT
INSERT INTO
INTO pic.t13
pic.t13
select
select par1.x,
par1.x, t14.d
t14.d as
as yy FROM
FROM
(SELECT
(SELECT t14.c
t14.c asas xx from
from pic.t14
pic.t14
except
except
select
select t13.a
t13.a asas xx from
from pic.t13
pic.t13 )par1,
)par1,
pic.t14
pic.t14 WHERE
WHERE par1.x == t14.c;
par1.x t14.c;
Ex.: Actualizează valorile b pentru înregistrările a căror valoare
din câmpul a începe cu litera x. Valoarea cu care se înlocuieşte
este suma tuturor valorilor câmpului d din tabelul pic.t14
update
update pic.t13
pic.t13 set
set bb == (select
(select sum(t14.d)
sum(t14.d) from
from pic.t14)
pic.t14)
where
where aa ilike
ilike 'x%';
'x%';
39
II.Limbajul SQL
40
8.Operaţii cu tablouri de date
41
II.Limbajul SQL
42
10.Funcţii PostgreSQL
select
select CURRENT_DATE;
CURRENT_DATE; ---- data
data curentă
curentă
--
-- extrage numărul zilei din săptămână
extrage numărul zilei din săptămână
select
select extract(DOW
extract(DOW from
from current_date);
current_date);
select
select extract(YEAR from
extract(YEAR from current_date);--extrage
current_date);--extrage anulanul
--
-- extrage
extrage luna
luna calendaristică
calendaristică
select
select extract(MONTH
extract(MONTH from
from current_date);
current_date);
select
select extract(DAY
extract(DAY from
from current_date);--
current_date);-- extrage
extrage ziua
ziua
select
select current_date - 22; -- scade din data curentă
current_date - 22; -- scade din data curentă 22
22 de
de zile
zile
select
select current_date
current_date ++ 1000;
1000; --adună
--adună la
la data
data curentă
curentă 1000
1000 de
de zile
zile
Ex.:Să se afişeze în clar numele zilei curente din săptămână (luni,
marţi etc.), apoi pentru ziua de joi să se extindă pentru AM, PM:
select
select CASE
CASE
WHEN
WHEN extract(DOW
extract(DOW from
from current_date)
current_date) == 11 THEN
THEN 'Luni'
'Luni'
WHEN
WHEN extract(DOW
extract(DOW from
from current_date)
current_date) == 22 THEN
THEN 'Marţi'
'Marţi'
WHEN
WHEN extract(DOW
extract(DOW from
from current_date)
current_date) == 33 THEN
THEN 'Miercuri'
'Miercuri'
WHEN
WHEN extract(DOW
extract(DOW from
from current_date)
current_date) == 44 AND
AND
current_time
current_time << '12:00:00.0'
'12:00:00.0' THEN
THEN 'JoiAM'
'JoiAM'
WHEN
WHEN extract(DOW
extract(DOW from
from current_date)
current_date) == 44 AND
AND
current_time >=
current_time >= '09:00:00.0'
'09:00:00.0' THEN
THEN 'JoiPM'
'JoiPM'
WHEN extract(DOW from current_date) = 5 THEN 'Vineri'
WHEN extract(DOW from current_date) = 5 THEN 'Vineri'
WHEN
WHEN extract(DOW
extract(DOW from
from current_date)
current_date) == 66 THEN
THEN 'Sambata'
'Sambata'
WHEN
WHEN extract(DOW from current_date) = 7 THEN 'Duminica'
extract(DOW from current_date) = 7 THEN 'Duminica'
ELSE
ELSE 'Incorect'
'Incorect' END
END AS
AS Ziua;
Ziua;
Ex.:Pentru exemplul cu biblioteca: Să se calculeze câte zile a fost
împrumutată fiecare carte (tabel generat în ultimul exemplu):
SELECT
SELECT cota,
cota,
SUM(
SUM( CASE
CASE WHEN
WHEN data_rest
data_rest IS
IS NOT
NOT NULL
NULL THEN
THEN data_rest-data_impr
data_rest-data_impr
WHEN data_rest IS NULL
WHEN data_rest IS NULL THEN
THEN CURRENT_DATE
CURRENT_DATE -- data_impr
data_impr
END
END )) as
as nr_zile
nr_zile
FROM
FROM biblio.oper
biblio.oper GROUP
GROUP BY
BY cota;
cota;
sau:
SELECT
SELECT cota,SUM(CASE
cota,SUM(CASE WHEN
WHEN data_rest
data_rest IS
IS NULL
NULL THEN
THEN
CURRENT_DATE-data_impr
CURRENT_DATE-data_impr ELSE ELSE data_rest
data_rest -- data_impr
data_impr
END
END )) as
as nr_zile
nr_zile
FROM
FROM biblio.oper
biblio.oper GROUP
GROUP BY
BY cota;
cota;
43
II.Limbajul SQL
select
select current_time;--
current_time;-- afiş.
afiş. ora,min.,sec.
ora,min.,sec. şişi fracţiunea
fracţiunea de de sec.
sec.
select
select cast('05:20:20.0' as time);-- transformă: char[] -> time
cast('05:20:20.0' as time);-- transformă: char[] -> time
select
select current_time
current_time as
as timp1,
timp1, current_time
current_time ++
cast('05:20:20.0'
cast('05:20:20.0' as as time)
time) as
as timp2;
timp2;
select
select current_date
current_date ++ current_time
current_time as
as a;--
a;-- date
date ++ time
time =>
=> timestamp
timestamp
select
select '2009-03-11'::date
'2009-03-11'::date ++ '12:20'::time
'12:20'::time as
as a;
a;
select
select to_date('20.05.1984','dd.mm.yyyy');
to_date('20.05.1984','dd.mm.yyyy');
--
-- util
util ptr.
ptr. preluare
preluare format
format ro/fr/ge
ro/fr/ge
select
select to_date('05/20/1984','mm/dd/yyyy');--
to_date('05/20/1984','mm/dd/yyyy');-- en en
44
10.Funcţii PostgreSQL
SELECT
SELECT ** FROM
FROM pic.t19
pic.t19 WHERE
WHERE translate(c,'ăîşţâ','aista')
translate(c,'ăîşţâ','aista') ='usa';
='usa';
-- 3 înregistrări
-- 3 înregistrări
Dacă se caută cu şi fără diacritice:
SELECT
SELECT ** FROM
FROM pic.t19
pic.t19 WHERE
WHERE translate(c,'ăîşţâ','aista')
translate(c,'ăîşţâ','aista') ='uşa';
='uşa';
--
-- 00 înregistrări
înregistrări
În acest caz, convertim ambii termeni în expresii
independente de diacritice:
SELECT
SELECT ** FROM
FROM pic.t19
pic.t19 WHERE
WHERE translate(c,'ăîşţâ','aista')
translate(c,'ăîşţâ','aista') ==
translate('uşa','ăîşţâ','aista');
translate('uşa','ăîşţâ','aista');
--
-- 33 înregistrări
înregistrări
Dar tot nu sunt luate în considerare şi literele mari.
Pentru a rezolva aceasta:
SELECT
SELECT ** FROM
FROM pic.t19
pic.t19 WHERE
WHERE
translate(t19.c,'ăîşţâĂÎŞŢÂ','aistaAISTA')
translate(t19.c,'ăîşţâĂÎŞŢÂ','aistaAISTA')
== translate('usa','ăîşţâĂÎŞŢÂ','aistaAISTA');
translate('usa','ăîşţâĂÎŞŢÂ','aistaAISTA');
--
-- 33 înregistrări
înregistrări
Pentru a avea o căutare parţială, avem:
SELECT
SELECT ** FROM
FROM pic.t19
pic.t19 WHERE
WHERE translate(t19.c,'ăîşţâ','aista')
translate(t19.c,'ăîşţâ','aista') LIKE
LIKE
translate('uşa','ăîşţâ','aista');
translate('uşa','ăîşţâ','aista');
--
-- 33 înregistrări
înregistrări
Termenul de comparaţie este şirul fără diacritice, cu litere mici.
Pentru:
SELECT
SELECT ** FROM
FROM pic.t19
pic.t19 WHERE
WHERE translate(t19.c,'ăîşţâ','aista')
translate(t19.c,'ăîşţâ','aista') ILIKE
ILIKE
translate('uşa','ăîşţâ','aista');
translate('uşa','ăîşţâ','aista');
--5
--5 înregistrări
înregistrări
Termenul de comparaţie este şirul cu diacritice – litere mici şi
fără diacritice – litere mari.
Iar dacă avem:
SELECT
SELECT ** FROM
FROM pic.t19
pic.t19 WHERE
WHERE translate(t19.c,'ăîşţâĂÎŞŢÂ','aistaAISTA')
translate(t19.c,'ăîşţâĂÎŞŢÂ','aistaAISTA')
LIKE
LIKE translate('uşa','ăîşţâĂÎŞŢÂ','aistaAISTA');
translate('uşa','ăîşţâĂÎŞŢÂ','aistaAISTA');
--3
--3 înregistrări
înregistrări
comparaţia ţine cont de litera mare sau litera mică şi nu de
diacritice.
Cazul general:
SELECT
SELECT ** FROM
FROM pic.t19
pic.t19
WHERE
WHERE translate(t19.c,'ăîşţâĂÎŞŢÂ','aistaAISTA')
translate(t19.c,'ăîşţâĂÎŞŢÂ','aistaAISTA')
ILIKE
ILIKE translate('uşa','ăîşţâĂÎŞŢÂ','aistaAISTA');
translate('uşa','ăîşţâĂÎŞŢÂ','aistaAISTA');
--8
--8 înregistrări
înregistrări
comparaţia NU ţine cont de literă mare sau literă mică ŞI NICI de
45
II.Limbajul SQL
diacritice.
46
11.Tranzacţii. Interogări multiserver
47
II.Limbajul SQL
48
12.Teste rezolvate – gestiune bibliotecă
INSERT
INSERT INTO
INTO biblio.utiliz(cnp,nume,data_n)
biblio.utiliz(cnp,nume,data_n) VALUES
VALUES
('cnp0000000001','Ion','1992-05-21'),
('cnp0000000001','Ion','1992-05-21'), ('cnp0000000002','Vasile',
('cnp0000000002','Vasile',
'1991-04-21'),
'1991-04-21'), ('cnp0000000003','Ion','1996-05-21'),
('cnp0000000003','Ion','1996-05-21'),
('cnp0000000004','Grigore','1982-05-21'),
('cnp0000000004','Grigore','1982-05-21'), ('cnp0000000005','Ion',
('cnp0000000005','Ion',
'1972-09-21'),('cnp0000000006','Geo','1993-09-21'),
'1972-09-21'),('cnp0000000006','Geo','1993-09-21'),
('cnp0000000007','Ionescu','1992-05-21'),
('cnp0000000007','Ionescu','1992-05-21'), ('cnp0000000008','Vlad',
('cnp0000000008','Vlad',
'1999-05-21'),
'1999-05-21'), ('cnp0000000009','Alin','1992-08-21');
('cnp0000000009','Alin','1992-08-21');
INSERT
INSERT INTO
INTO biblio.inv(cota,
biblio.inv(cota, titlu,
titlu, editura,
editura, an_ap,
an_ap, nr_pag
nr_pag )) VALUES
VALUES
('001','T1','ALL',1977,150),('002','T21','Nemira',1977,190),
('001','T1','ALL',1977,150),('002','T21','Nemira',1977,190),
('003','T1','Tehnica',1977,250),('004','T54','Albatros',1977,220),
('003','T1','Tehnica',1977,250),('004','T54','Albatros',1977,220),
('005','T97','Nemira',1977,80),('006','T1','ALL',1977,50),
('005','T97','Nemira',1977,80),('006','T1','ALL',1977,50),
('007','T77','Tehnica',1977,120),('008','T21','Albatros',1987,100);
('007','T77','Tehnica',1977,120),('008','T21','Albatros',1987,100);
INSERT
INSERT INTO
INTO biblio.oper(data_impr,
biblio.oper(data_impr, cnp,
cnp, cota,
cota,
data_rest,
data_rest, nr_zile_termen, oper_impr, oper_rest)
nr_zile_termen, oper_impr, oper_rest) VALUES
VALUES
('2013-01-22','cnp0000000002','001','2013-02-22',55,'X1','X1'),
('2013-01-22','cnp0000000002','001','2013-02-22',55,'X1','X1'),
('2012-12-22','cnp0000000003','003','2013-02-22',17,'X1','X2'),
('2012-12-22','cnp0000000003','003','2013-02-22',17,'X1','X2'),
('2013-01-22','cnp0000000002','002','2013-02-25',55,'X1','X1'),
('2013-01-22','cnp0000000002','002','2013-02-25',55,'X1','X1'),
('2013-01-22','cnp0000000004','001','2013-02-24',5,'X1','X1');
('2013-01-22','cnp0000000004','001','2013-02-24',5,'X1','X1');
INSERT
INSERT INTO
INTO biblio.oper(data_impr,cnp,cota,nr_zile_termen,oper_impr)
biblio.oper(data_impr,cnp,cota,nr_zile_termen,oper_impr)
VALUES
VALUES ('2013-03-22','cnp0000000002','006',17,'X1'),
('2013-03-22','cnp0000000002','006',17,'X1'), ('2012-05-22',
('2012-05-22',
'cnp0000000002','006',127,'X1'),
'cnp0000000002','006',127,'X1'), ('2013-05-22','cnp0000000002','001',
('2013-05-22','cnp0000000002','001',
27,'X1'),('2013-01-21','cnp0000000001','005',117,'X1'),('2012-05-22',
27,'X1'),('2013-01-21','cnp0000000001','005',117,'X1'),('2012-05-22',
'cnp0000000007','002',71,'X2'),
'cnp0000000007','002',71,'X2'), ('2009-05-22','cnp0000000002','006',
('2009-05-22','cnp0000000002','006',
577,'X2'),('2013-05-22','cnp0000000005',
577,'X2'),('2013-05-22','cnp0000000005', '006',7,'X1'),('2012-05-22',
'006',7,'X1'),('2012-05-22',
'cnp0000000005','006',17,'X1'),
'cnp0000000005','006',17,'X1'), ('2012-11-22','cnp0000000002','006',
('2012-11-22','cnp0000000002','006',
57,'X1'),
57,'X1'), ('2013-03-01','cnp0000000002','005',19,'X1');
('2013-03-01','cnp0000000002','005',19,'X1');
Notă: Sunt populate cu date mai întâi tabelele de tip master (sau
părinte), altfel cheia din tabelul slave (sau copil) nu se va
regăsi şi în tabelul părinte.
3 Să se afişeze cotele, titlurile, cnp-urile şi numele persoanelor
pentru toate cărţile împrumutate (au fost sau sunt imprumutate).
SELECT
SELECT oper.cota,inv.titlu,oper.cnp,utiliz.nume
oper.cota,inv.titlu,oper.cnp,utiliz.nume
FROM
FROM biblio.oper,
biblio.oper, biblio.utiliz,
biblio.utiliz, biblio.inv
biblio.inv
WHERE
WHERE oper.cota
oper.cota == inv.cota
inv.cota AND
AND oper.cnp
oper.cnp == utiliz.cnp;
utiliz.cnp;
sau
SELECT
SELECT inv.cota,inv.titlu,utiliz.cnp,utiliz.nume
inv.cota,inv.titlu,utiliz.cnp,utiliz.nume
FROM
FROM biblio.oper,
biblio.oper, biblio.utiliz,
biblio.utiliz, biblio.inv
biblio.inv
WHERE
WHERE oper.cota
oper.cota == inv.cota
inv.cota AND
AND oper.cnp
oper.cnp == utiliz.cnp;
utiliz.cnp;
4. Să se afişeze toate cărţile (cota,titlu,data_impr) împrumutate
de către utilizatorii al căror nume conţine secvenţa 'ion':
49
II.Limbajul SQL
SELECT
SELECT oper.cota,inv.titlu,oper.data_impr,utiliz.nume
oper.cota,inv.titlu,oper.data_impr,utiliz.nume
FROM
FROM biblio.oper,
biblio.oper, biblio.inv,
biblio.inv, biblio.utiliz
biblio.utiliz
WHERE
WHERE oper.cota=inv.cota
oper.cota=inv.cota AND
AND oper.cnp=utiliz.cnp
oper.cnp=utiliz.cnp
AND
AND utiliz.nume
utiliz.nume ilike
ilike '%ion%';
'%ion%';
5. Să se afişeze toate cărţile (cota, titlu) care se află în
bibliotecă în momentul de faţă (ce cărţi mai există pe raft):
select
select inv.cota,inv.titlu
inv.cota,inv.titlu from
from biblio.inv
biblio.inv where
where inv.imprumutata=false;
inv.imprumutata=false;
--sau
--sau
SELECT
SELECT inv.cota,inv.titlu
inv.cota,inv.titlu FROM
FROM biblio.inv
biblio.inv WHERE
WHERE NOT
NOT inv.imprumutata;
inv.imprumutata;
sau (toate cărţile din inv mai puţin cele care se află în oper şi
nu au completat câmpul data pentru restituire):
select
select inv.cota,inv.titlu
inv.cota,inv.titlu FROM
FROM biblio.inv
biblio.inv
EXCEPT
EXCEPT
select
select distinct
distinct inv.cota,inv.titlu
inv.cota,inv.titlu from
from biblio.oper,
biblio.oper, biblio.inv
biblio.inv
WHERE
WHERE oper.cota=inv.cota
oper.cota=inv.cota AND
AND oper.data_rest
oper.data_rest IS
IS NULL;
NULL;
sau prin utilizarea subinterogărilor:
SELECT
SELECT par.cota,
par.cota, inv.titlu
inv.titlu FROM
FROM
(select
(select cota
cota from
from biblio.inv
biblio.inv EXCEPT
EXCEPT select
select distinct
distinct cota
cota
from
from biblio.oper
biblio.oper WHERE
WHERE oper.data_rest
oper.data_rest IS
IS NULL)par,
NULL)par,
biblio.inv
biblio.inv WHERE
WHERE par.cota=inv.cota;
par.cota=inv.cota;
6. Să se afişeze toţi restanţierii (nume,cnp,cota,titlu,data_impr,
nr_zile_depasire):
SELECT
SELECT utiliz.nume,oper.cnp,oper.cota,inv.titlu,data_impr,
utiliz.nume,oper.cnp,oper.cota,inv.titlu,data_impr,
oper.nr_zile_termen,CURRENT_DATE
oper.nr_zile_termen,CURRENT_DATE --
(oper.data_impr+oper.nr_zile_termen)
(oper.data_impr+oper.nr_zile_termen) as as nr_zile_depasire
nr_zile_depasire
FROM
FROM biblio.oper,
biblio.oper, biblio.inv,
biblio.inv, biblio.utiliz
biblio.utiliz
WHERE
WHERE oper.cnp
oper.cnp == utiliz.cnp
utiliz.cnp AND
AND oper.cota
oper.cota == inv.cota
inv.cota
AND
AND oper.data_rest
oper.data_rest ISIS NULL
NULL
AND
AND CURRENT_DATE
CURRENT_DATE >> (oper.data_impr+oper.nr_zile_termen);
(oper.data_impr+oper.nr_zile_termen);
7. Să se afişeze numărul total de pagini citite de utilizatori pe
fiecare an (afişează anul şi numărul total de pagini). Se preia
anul din data împrumutului:
SELECT
SELECT extract(year
extract(year from
from oper.data_impr),
oper.data_impr),
sum(inv.nr_pag)
sum(inv.nr_pag) asas nr_t_pag
nr_t_pag FROM
FROM biblio.oper,
biblio.oper, biblio.inv
biblio.inv
WHERE
WHERE oper.cota
oper.cota == inv.cota
inv.cota
GROUP
GROUP BY
BY extract(year
extract(year from
from oper.data_impr);
oper.data_impr);
8. Să se afişeze numărul total de pagini citite de fiecare
utilizator în fiecare an (afişează anul, nr. total de pagini, nume
utilizator, cnp):
50
12.Teste rezolvate – gestiune bibliotecă
SELECT
SELECT extract(year
extract(year from
from oper.data_impr),
oper.data_impr),
sum(inv.nr_pag)
sum(inv.nr_pag) asas nr_t_pag,utiliz.nume,oper.cnp
nr_t_pag,utiliz.nume,oper.cnp
FROM
FROM biblio.oper,
biblio.oper, biblio.utiliz,
biblio.utiliz, biblio.inv
biblio.inv
WHERE
WHERE oper.cota
oper.cota == inv.cota
inv.cota AND
AND oper.cnp
oper.cnp == utiliz.cnp
utiliz.cnp
GROUP
GROUP BY
BY extract(year
extract(year from
from oper.data_impr),
oper.data_impr), utiliz.nume,
utiliz.nume, oper.cnp
oper.cnp
ORDER
ORDER BY
BY extract(year
extract(year from
from oper.data_impr);
oper.data_impr);
9. Să se afişeze de câte ori a fost împrumutată fiecare carte
(cota, titlu, nr_imprumuturi).
SELECT
SELECT oper.cota,
oper.cota, inv.titlu,count(oper.*)
inv.titlu,count(oper.*) as
as nr_impr
nr_impr
FROM
FROM biblio.oper, biblio.inv WHERE oper.cota
biblio.oper, biblio.inv WHERE oper.cota == inv.cota
inv.cota
GROUP
GROUP BY
BY oper.cota,
oper.cota, inv.titlu;
inv.titlu;
51
III.Programarea la nivel de server – plpgSQL
52
1.Funcţii de tipul SQL
53
III.Programarea la nivel de server – plpgSQL
--Ex.
--Ex. 1(4D)
1(4D) -functie
-functie SQL
SQL ptr.
ptr. afişarea
afişarea conţinutului
conţinutului lui
lui t1
t1 –VARIANTA
–VARIANTA 22
CREATE OR REPLACE function pic.f1_2()
CREATE OR REPLACE function pic.f1_2()
RETURNS
RETURNS SETOF
SETOF RECORD
RECORD AS
AS $$
$$ SELECT
SELECT a1,a2,a3,a4
a1,a2,a3,a4 FROM
FROM pic.t1
pic.t1 $$
$$
LANGUAGE sql;
LANGUAGE sql;
Funcţia f1_2() selectează câmpuri din tabel şi întoarce
înregistrările selectate prin definirea structurii tabelului
selectat. Dacă apelăm “SELECT a1,a2,a3,a4 FROM pic.f1_2()” nu
este cunoscut numele câmpurilor. Apelul funcţiei pic.f1_2()
se poate realiza în două moduri:
--Ex.
--Ex. 1(4A)
1(4A) APEL
APEL pic.f1_2()
pic.f1_2() –VARIANTA
–VARIANTA 22 dede selecţie
selecţie
SELECT
SELECT pic.f1_2();
pic.f1_2(); -- -- rezultat
rezultat pe
pe oo singura
singura coloană
coloană sau
sau
SELECT
SELECT a1,a2,a3,a4
a1,a2,a3,a4 FROM
FROM c1.f3()
c1.f3()
AS
AS (a1
(a1 int,a2
int,a2 int,a3
int,a3 int,a4
int,a4 varchar(20));
varchar(20));
--
-- după
după AS
AS este
este definita
definita structura
structura RECORD
RECORD -- patru
patru coloane
coloane
☑ O altă variantă este dată de definiţia funcţiei pic.f1_3()
în care este specificată structura întoarsă ca fiind
structura tabelului pic.t1:
--Ex.
--Ex. 1(5D):functie
1(5D):functie SQL
SQL ptr.
ptr. afişarea
afişarea conţinutului
conţinutului t1
t1 –VARIANTA
–VARIANTA 33
CREATE
CREATE OR
OR REPLACE
REPLACE function
function pic.f1_3()
pic.f1_3() RETURNS
RETURNS SETOF
SETOF pic.t1
pic.t1 AS
AS
$$
$$ SELECT
SELECT a1,a2,a3,a4
a1,a2,a3,a4 FROM
FROM pic.t1
pic.t1 $$
$$ LANGUAGE
LANGUAGE 'sql';
'sql';
şi exemplul de apel:
--Ex.
--Ex. 1(5A)
1(5A) APEL
APEL pic.f1_3()
pic.f1_3() –VARIANTA
–VARIANTA 33 de
de selecţie
selecţie
SELECT
SELECT c1.ftest4();
c1.ftest4(); ---- afişează
afişează un
un singur
singur câmp
câmp de
de tip
tip structură
structură SAU
SAU
SELECT
SELECT ** FROM
FROM pic.f1_3();--afişeză
pic.f1_3();--afişeză a1,a2,a3,a4
a1,a2,a3,a4 -- sunt
sunt deja
deja definite
definite
SELECT
SELECT a1,a2,a3,a4
a1,a2,a3,a4 FROM
FROM c1.ftest4();
c1.ftest4();
Câmpurile a1, a2, a3 şi a4 sunt afişate distinct, tipul
fiecarui câmp este cunoscut din RETURNS SETOF pic.t1.
1.3. Funcţii SQL cu transfer prin argument şi cu returnare
subset de înregistrări
Dacă dorim să punem un filtru asupra datelor din tabelul
pic.t1 şi să întoarcem doar un subset al înregistrărilor, vom avea:
--Ex.
--Ex. 1.1(6D):fcţ.
1.1(6D):fcţ. SQL
SQL ce
ce preia
preia 22 param.
param. şi
şi întoarce
întoarce unun set
set de
de înreg.
înreg.
CREATE OR REPLACE function c1.f3(b2 int,
CREATE OR REPLACE function c1.f3(b2 int, b3 int)b3 int)
RETURNS
RETURNS SETOF
SETOF RECORD
RECORD AS
AS
$$
$$ SELECT a1,a2,a3,a4 FROM
SELECT a1,a2,a3,a4 FROM c1.t1
c1.t1 WHERE
WHERE a2
a2 >> $1
$1 AND
AND a3
a3 << $2;
$2;
$$
$$ LANGUAGE
LANGUAGE 'sql';
'sql';
şi exemplul de apel:
--Ex.
--Ex. 1.1(6A)
1.1(6A) APEL
APEL pic.f3(int,int)
pic.f3(int,int)
SELECT
SELECT a1,a2,a3,a4
a1,a2,a3,a4 FROM
FROM c1.f3(10,15)
c1.f3(10,15) AS AS
(a1
(a1 int,
int, a2
a2 int,
int, a3
a3 int,
int, a4
a4 varchar(20));
varchar(20));
54
1.Funcţii de tipul SQL
55
III.Programarea la nivel de server – plpgSQL
56
4.Parametri de intrare şi ieşire
57
III.Programarea la nivel de server – plpgSQL
5. Implementarea notificărilor
Uneori sunt necesare informaţii despre valorile variabilelor
în diverse puncte sau sunt necesare informaţii despre anumite stări
din cadrul funcţiei (de exemplu, numărul de înregistrări afectate
de o operaţie SQL de tipul UPDATE sau DELETE), iar aceste informaţii
sunt necesare fără a ieşi din funcţie. În aceste condiţii sunt
utilizate notificările, acestea se transmit de la server către
client.
În exemplul următor sunt adăugate câteva înregistrări
într-un tabel t1, apoi sunt realizate operaţii de adăugare
înregistrări şi actualizare. Se construiesc notificări pentru a
transmite către client numărul de înregistrări adăugate şi numărul
de înregistrări afectate de comanda UPDATE. De asemenea se testează
o expresie şi se transmite o notificare către client.
/*
/* Ex.
Ex. 5(1D):
5(1D): */*/ CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTION
FUNCTION pic.f5_1()
pic.f5_1() RETURNS
RETURNS TEXT
TEXT AS
AS
$$
$$ DECLARE
DECLARE nr_ins
nr_ins int;
int; nr_up
nr_up int;
int; achR
achR text;
text; total
total int;
int;
BEGIN
BEGIN achR:='OK';
achR:='OK'; DROPDROP TABLE
TABLE IF
IF EXISTS
EXISTS pic.t1;
pic.t1;
CREATE
CREATE TABLE
TABLE pic.t1(a
pic.t1(a serial
serial PRIMARY
PRIMARY KEY,
KEY, bb int,
int, cc varchar(10));
varchar(10));
INSERT INTO pic.t1(b,c)
INSERT INTO VALUES (11,'A1'),(21,'B2'),(31,'B3'),(41,'C3');
pic.t1(b,c) VALUES (11,'A1'),(21,'B2'),(31,'B3'),(41,'C3');
GET
GET DIAGNOSTICS
DIAGNOSTICS nr_ins
nr_ins == ROW_COUNT;
ROW_COUNT;
RAISE
RAISE NOTICE
NOTICE 'Au
'Au fost
fost adaugate:
adaugate: %% inregistrari',nr_ins;
inregistrari',nr_ins;
UPDATE
UPDATE pic.t1
pic.t1 SET
SET b=b+2
b=b+2 WHERE
WHERE cc LIKE
LIKE 'B%';
'B%';
GET
GET DIAGNOSTICS
DIAGNOSTICS nr_up
nr_up == ROW_COUNT;
ROW_COUNT; RAISE
RAISE NOTICE
NOTICE 'Au
'Au fost
fost
actualizate:
actualizate: %% inregistrari',nr_up;
inregistrari',nr_up;
SELECT
SELECT SUM(b)
SUM(b) FROM
FROM pic.t1
pic.t1 INTO
INTO total;
total;
IF
IF total
total << 60
60 THEN
THEN achR:='NOK';
achR:='NOK'; ENDEND IF;
IF; RETURN
RETURN achR;
achR;
END
END $$
$$ LANGUAGE
LANGUAGE plpgsql;
plpgsql;
Prin instrucţiunea GET DIAGNOSTICS este preluat conţinutul
variabilei ROW_COUNT din cadrul server-ului, variabilă ce conţine
numărul de înregistrări afectate de ultima comandă SQL.
Instrucţiunea RAISE NOTICE transmite notificarea către
client. În şirul ce urmează este specificat textul transmis către
client, iar în locul simbolurilor “%” din cadrul şirului se vor
transmite valorile variabilelor din finalul instrucţiunii. De
exemplu, dacă avem: “RAISE NOTICE 'A= % ...B=% ...C=%',a,b,c;”, iar
dacă a=10, b='TEST' şi c=15.7, atunci textul afişat va fi: “NOTICE:
A=10 … B=TEST ...C=15.7”.
Notificările pot să apară (în funcţie de configurarea
serverului de baze de date) în fişierele cu istoricul operaţiilor
la nivel de server de baze de date şi pot fi utile pentru
interpretarea anumitor situaţii apărute.
/*Ex.
/*Ex. 5(1A)
5(1A) APEL
APEL pic.f5_1()
pic.f5_1() */
*/ SELECT
SELECT pic.f5_1();
pic.f5_1();
După apelul funcţiei pic.f5_1() în fereastra SQL din
58
5.Implementarea notificărilor
6. Structuri repetitive
O buclă cu instrucţiuni, în plpgSQL are forma:
LOOP
LOOP
--
-- bloc
bloc instructiuni
instructiuni
END
END LOOP;
LOOP;
Ieşirea din buclă se realizează cu instrucţiunea EXIT
(echivalent cu instrucţiunea break din limbajul C), iar revenirea
la începutul buclei (fară executarea restului de instrucţiuni) se
realizează cu instrucţiunea CONTINUE (idem în limbajul C),
utilizarea acestora fiind exemplificată în cele ce urmează.
i:=0;
i:=0; –-
–- iniţializare
iniţializare variabilă
variabilă
LOOP
LOOP –-
–- începutul
începutul buclei
buclei
--
-- instrucţiuni
instrucţiuni
IF
IF i<10
i<10 THEN
THEN CONTINUE;
CONTINUE; END
END IF;
IF;
IF
IF i>100
i>100 THEN
THEN EXIT;
EXIT; END
END IF;
IF;
--
-- instrucţiuni
instrucţiuni înîn care
care varibila
varibila ii are
are valori
valori între
între 10
10 şi
şi 100
100
END
END LOOP;
LOOP; –-
–- sfârşitul
sfârşitul buclei
buclei
Bucla de tip WHILE va avea forma:
WHILE
WHILE
--
-- condiţie
condiţie (expresie
(expresie evaluată
evaluată la
la TRUE
TRUE ---
--- adică
adică diferită
diferită de
de 0)
0)
LOOP
LOOP –-–- începutul
începutul buclei
buclei
--instrucţiuni
--instrucţiuni
END
END LOOP;–-
LOOP;–- sfârşitul
sfârşitul buclei
buclei
iar bucla de tip FOR va avea forma:
FOR
FOR nume
nume IN
IN expresieDomeniu
expresieDomeniu
LOOP
LOOP
--instructiuni
--instructiuni
END
END LOOP;
LOOP;
Pentru bucla de tip FOR putem avea formele:
FOR
FOR ii IN
IN 1..100
1..100
LOOP
LOOP
--
-- ii are
are valori
valori de
de la
la 11 la
la 100
100
END
END LOOP;
LOOP;
sau:
59
III.Programarea la nivel de server – plpgSQL
FOR
FOR rr IN
IN DENUMIRE_TABEL
DENUMIRE_TABEL
--aici
--aici „expresieDomeniu”
„expresieDomeniu” esteeste alcatuit
alcatuit din
din mulţimea
mulţimea liniilor
liniilor tabelului
tabelului
LOOP
LOOP -- r este variabila ce conţine o înregistrare (linie din
-- r este variabila ce conţine o înregistrare (linie din tabel)
tabel)
--
-- rr parcurge
parcurge tot
tot tabelul
tabelul (la
(la fiecare
fiecare ciclu
ciclu preia
preia altă
altă inregistrare)
inregistrare)
–-
–- rr este
este de
de tip
tip RECORD
RECORD
END
END LOOP;
LOOP;
În continuare este prezentat un exemplu de citire dintr-un
tabel. În acest sens, este contruit un tabel t1 în care sunt
adăugate câteva înregistrări.
/*
/* Ex.
Ex. 6(1D):
6(1D): */
*/ DROP
DROP TABLE
TABLE IF
IF EXISTS
EXISTS pic.t1;
pic.t1;
create
create table
table pic.t1(a
pic.t1(a serial
serial PRIMARY
PRIMARY KEY,
KEY, bb int,
int, cc varchar(10));
varchar(10));
INSERT
INSERT INTO
INTO pic.t1(b,c)
pic.t1(b,c) VALUES(10,'A10'),(17,'A17'),(14,'A14'),
VALUES(10,'A10'),(17,'A17'),(14,'A14'),
(13,'A13'),(11,'A11');
(13,'A13'),(11,'A11'); select
select ** from
from pic.t1;
pic.t1;
Funcţia pentru citirea din tabel va fi:
/*
/* Ex.
Ex. 6(1D):
6(1D): */*/
CREATE
CREATE OROR REPLACE
REPLACE FUNCTION
FUNCTION pic.f1()
pic.f1() RETURNS
RETURNS SETOF
SETOF RECORD
RECORD AS
AS
$$
$$ DECLARE
DECLARE rr record;--
record;-- rr este
este de
de tip
tip înregistrare
înregistrare (RECORD)
(RECORD)
BEGIN
BEGIN
FOR
FOR rr IN
IN SELECT
SELECT a,b,c
a,b,c FROM
FROM pic.t1
pic.t1 ---- rr este
este variabila
variabila de
de parcurgere
parcurgere
LOOP
LOOP ---- inceput
inceput buclă
buclă
RETURN
RETURN NEXT
NEXT r;
r; --
-- întoarce
întoarce înregistrare
înregistrare cu cu înregistrare
înregistrare
END
END LOOP;--sfârşit
LOOP;--sfârşit buclă
buclă
END
END $$
$$ LANGUAGE
LANGUAGE plpgsql;
plpgsql;
Bucla se opreşte în momentul în care variabila r devine
NULL, adică atunci când nu mai sunt înregistrări de parcurs. Fără
secvenţa RETURN NEXT r; funcţia nu adaugă în tabelul întors
înregistrarea curentă, practic pentru fiecare apel al instrucţiunii
next este adăugată o înregistrare la tabelul întors. Pentru a apela
funcţia este necesară specificarea structurii câmpurilor rezultate:
/*Ex.
/*Ex. 6(1A)
6(1A) APEL
APEL pic.f6_1()
pic.f6_1() */
*/
select
select a,b,c
a,b,c FROM
FROM pic.f6_1()
pic.f6_1() AS
AS (a
(a int,
int, bb int,
int, cc varchar(10));
varchar(10));
În cadrul buclei prin care sunt întoarse înregistrările, se
pot efectua diverse operaţii. În acest sens, este prezentat un
exemplu de funcţie care afişează numai înregistrările pentru care
valoarea câmpului b este mai mică decât valoarea anterioară pentru
acelaşi câmp:
/*Ex.
/*Ex. 6(2D):*/
6(2D):*/
CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTION
FUNCTION pic.f6_2()
pic.f6_2() RETURNS
RETURNS SETOF
SETOF RECORD
RECORD AS
AS $$
$$
DECLARE
DECLARE rr record;
record; b1
b1 int;
int; –-
–- b1
b1 memoreaza
memoreaza valoarea
valoarea anterioara
anterioara
BEGIN
BEGIN b1:=0;
b1:=0; FOR
FOR rr IN
IN SELECT
SELECT a,b,c
a,b,c FROM
FROM pic.t1
pic.t1
LOOP
LOOP IF IF r.b
r.b << b1
b1 THEN
THEN b1:=r.b;
b1:=r.b; RETURN
RETURN NEXT
NEXT r;r;
ELSE
ELSE b1:=r.b;
b1:=r.b;
END
END IF;
IF;
END
END LOOP;
LOOP;
END
END $$
$$ LANGUAGE
LANGUAGE plpgsql;
plpgsql;
Tabelul parcurs este dat de :"SELECT a,b,c FROM pic.t1".
60
6.Structuri repetitive
Apelul funcţiei:
/*Ex.
/*Ex. 6(2A)
6(2A) APEL
APEL pic.f6_2()
pic.f6_2() */
*/
SELECT
SELECT a,b,c
a,b,c FROM
FROM pic.f6_2()
pic.f6_2() AS
AS (a
(a int,
int, bb int,
int, cc varchar(10));
varchar(10));
În continuare este prezentat un exemplu prin care sunt
înlocuite funcţiile SQL de agregare MIN şi MAX:
/*
/* Ex.
Ex. 6(3D):
6(3D): */*/
CREATE
CREATE OROR REPLACE
REPLACE FUNCTION
FUNCTION pic.f6_3()
pic.f6_3() RETURNS
RETURNS SETOF
SETOF RECORD
RECORD AS
AS
$$
$$ DECLARE
DECLARE rr record;
record; b_min
b_min int;
int; b_max
b_max int;--memorează
int;--memorează val.min
val.min şişi max.
max.
BEGIN
BEGIN b_min:=1000;
b_min:=1000; b_max:=-1000;
b_max:=-1000;
FOR
FOR rr IN
IN SELECT
SELECT a,b,c
a,b,c FROM
FROM pic.t1
pic.t1
LOOP
LOOP if
if r.b
r.b << b_min
b_min THEN
THEN b_min:=r.b;
b_min:=r.b; endend if;
if;
if
if r.b
r.b >=
>= b_max
b_max THEN
THEN b_max:=r.b;
b_max:=r.b; end
end if;
if;
END
END LOOP;
LOOP;
FOR
FOR rr IN
IN SELECT
SELECT a,b,c
a,b,c FROM
FROM pic.t1
pic.t1
LOOP
LOOP IFIF r.b
r.b == b_min
b_min OR
OR r.b
r.b == b_max
b_max THEN
THEN return
return next
next r;
r; END
END IF;
IF;
END
END LOOP;
LOOP;
END
END $$
$$ LANGUAGE
LANGUAGE plpgsql;
plpgsql;
iar apelul:
/*Ex.
/*Ex. 6(3A)
6(3A) APEL
APEL pic.f6_3()
pic.f6_3() */
*/
SELECT
SELECT a,b,c FROM pic.f6_3()
a,b,c FROM pic.f6_3() AS
AS (a
(a int,
int, bb int,
int, cc varchar(10));
varchar(10));
Funcţia f6_3 este echivalentă cu următoarea comandă SQL:
select
select t1.a,t1.b,t1.c
t1.a,t1.b,t1.c FROM
FROM
(SELECT
(SELECT min(b)
min(b) as
as b_min,
b_min, max(b)
max(b) as
as b_max
b_max FROM
FROM pic.t1)
pic.t1) par,
par, pic.t1
pic.t1
WHERE
WHERE t1.b=par.b_min
t1.b=par.b_min OROR t1.b=par.b_max;
t1.b=par.b_max;
61
III.Programarea la nivel de server – plpgSQL
/*Ex.
/*Ex. 7(1D):*/
7(1D):*/
CREATE
CREATE OROR REPLACE
REPLACE FUNCTION
FUNCTION pic.f7_1(a
pic.f7_1(a text)
text) RETURNS
RETURNS int
int as
as
$$
$$ DECLARE
DECLARE rez
rez int;
int; achQ
achQ text;
text;
BEGIN
BEGIN achQ='select
achQ='select '||a;
'||a; EXECUTE
EXECUTE achQ
achQ INTO
INTO rez;
rez; return
return rez;
rez;
END
END $$
$$ language
language plpgsql;
plpgsql;
Instrucţiunea “EXECUTE achQ INTO rez;” execută comanda SQL din
şirul achQ, iar rezultatul este memorat în variabila rez (aici
interogarea întoarce o singură valoare). Exemplu de apel:
/*Ex.
/*Ex. 7(1A)
7(1A) APEL
APEL pic.f7_1()
pic.f7_1() */
*/ SELECT
SELECT pic.f7_1('5+9');
pic.f7_1('5+9');
Un alt exemplu de funcţie cu interogare dinamică şi cu doi
parametri de intrare:
/*Ex.
/*Ex. 7(2D):*/
7(2D):*/
CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTION
FUNCTION pic.f7_2(a
pic.f7_2(a text,
text, bb text)
text) RETURNS
RETURNS int
int AS
AS
$$
$$ DECLARE
DECLARE rez
rez int;
int; achQ
achQ text;
text;
BEGIN
BEGIN achQ
achQ == 'select
'select '' ||
|| aa ||
|| '+'
'+' ||
|| b;
b; EXECUTE
EXECUTE achQ
achQ INTO
INTO rez;
rez;
return
return rez;
rez; END
END $$
$$ language
language plpgsql;
plpgsql;
iar apelul:
/*Ex.
/*Ex. 7(2A)
7(2A) APEL
APEL pic.f7_2()
pic.f7_2() */
*/ SELECT
SELECT pic.f7_2('5','9');
pic.f7_2('5','9');
Un alt exemplu, preia un vector cu şiruri (ultimul element
este NULL) şi întoarce un şir rezultat prin concatenarea
elementelor din cadrul vectorului cu şiruri:
/*Ex.
/*Ex. 7(3D):*/
7(3D):*/
CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTIOn
FUNCTIOn pic.f7_3(_sir_
pic.f7_3(_sir_ text[])
text[]) RETURNS
RETURNS text
text AS
AS
$$
$$ DECLARE
DECLARE ii int;
int; rez
rez text;
text;
BEGIN
BEGIN rez:='';
rez:=''; i:=1;
i:=1;
LOOP
LOOP IF
IF _sir_[i]
_sir_[i] ISIS NULL
NULL THEN
THEN RETURN
RETURN rez;
rez; END
END IF;
IF;
rez := rez || _sir_[i] ||
rez := rez || _sir_[i] || ';'; ';'; i:=i+1;
i:=i+1;
END
END LOOP;
LOOP; END
END $$
$$ LANGUAGE
LANGUAGE 'plpgsql';
'plpgsql';
iar apelul:
/*Ex
/*Ex 7(3A)
7(3A) APEL
APEL pic.f7_3()
pic.f7_3() */
*/
select
select pic.f7_3(ARRAY['UNU','DOI','TREI',NULL])
pic.f7_3(ARRAY['UNU','DOI','TREI',NULL]) as
as rez;
rez;
În continuare este prezentat un exemplu de funcţie ce preia
un şir, îl concatenează cu şirul “test” apoi întoarce şirul
rezultat în urma concatenării:
/*Ex
/*Ex 7(4D):*/
7(4D):*/CREATE
CREATE OR
OR REPLACE FUNCTION pic.f7_4(b
REPLACE FUNCTION pic.f7_4(b text) RETURNS text
text) RETURNS text AS
AS
$$
$$ DECLARE
DECLARE achQ
achQ text;
text; rez
rez text;
text;
BEGIN
BEGIN achQ
achQ ='SELECT
='SELECT '||quote_literal(b)||'||'||quote_literal('
'||quote_literal(b)||'||'||quote_literal(' test'); test');
EXECUTE
EXECUTE achQ
achQ INTO
INTO rez;
rez; RETURN
RETURN rez;END
rez;END $$$$ LANGUAGE
LANGUAGE 'plpgsql';
'plpgsql';
Funcţia quote_literal(b) întoarce valoarea lui b ca şir de
caractere şi nu mai este necesară specificarea acestuia ca şir de
62
7.Construcţia dinamică a interogărilor
63
III.Programarea la nivel de server – plpgSQL
DROP
DROP TABLE
TABLE IF
IF EXISTS
EXISTS pic.t1;
pic.t1;
CREATE
CREATE TABLE pic.t1(datac date,
TABLE pic.t1(datac date, an
an smallint,idx
smallint,idx serial
serial PRIMARY
PRIMARY KEY);
KEY);
Crearea funcţiei de tip trigger:
/*Ex.
/*Ex. 8(1D):*/
8(1D):*/ CREATE
CREATE OROR REPLACE
REPLACE FUNCTION
FUNCTION pic.f8_1()
pic.f8_1()
RETURNS
RETURNS trigger
trigger AS
AS
$$
$$ BEGIN
BEGIN
SELECT
SELECT EXTRACT(
EXTRACT( YEAR
YEAR FROM
FROM NEW.datac)
NEW.datac) INTO
INTO NEW.an;
NEW.an; return
return NEW;
NEW;
END $$ LANGUAGE 'plpgsql';
END $$ LANGUAGE 'plpgsql';
În funcţia de tip triger variabilele NEW şi OLD sunt
predefinite, sunt de tip înregistrare RECORD şi memorează noua,
respectiv vechea valoare a înregistrării afectate. Funcţia triger
poate întoarce şi înregistrarea OLD (vechile valori).
O funcţie de tip triger poate fi ataşată unuia sau mai
multor tabele. Ataşarea funcţiei f8_1() la tabelul t1 pentru
operaţia de UPDATE se realizează prin:
/*Ex.
/*Ex. 8(1T):*/
8(1T):*/ CREATE
CREATE TRIGGER
TRIGGER t8_1_trg
t8_1_trg
BEFORE
BEFORE UPDATE
UPDATE ON
ON pic.t1
pic.t1
FOR
FOR EACH
EACH ROW
ROW
WHEN
WHEN ((OLD.*
((OLD.* IS
IS DISTINCT
DISTINCT FROM
FROM NEW.*))
NEW.*)) EXECUTE
EXECUTE PROCEDURE
PROCEDURE pic.f8_1();
pic.f8_1();
Condiţia “WHEN ((OLD.* IS DISTINCT FROM NEW.*))” are ca efect
limitarea apelului funcţiei triger doar atunci când se modifică un
câmp (noile valori sunt diferite de vechile valori).
În vederea testării se adaugă înregistrări şi apoi se
execută o comandă UPDATE în vederea modificării valorii câmpului
datac dintr-o înregistrare.
/*Ex.
/*Ex. 8(1A)
8(1A) TESTARE
TESTARE pic.f8_1()
pic.f8_1() pentru
pentru pic.t1
pic.t1 */
*/
INSERT
INSERT INTO
INTO pic.t1(datac)
pic.t1(datac)
VALUES('2013-03-15'),('2013-03-17'),('2013-03-19');
VALUES('2013-03-15'),('2013-03-17'),('2013-03-19');
UPDATE
UPDATE pic.t1
pic.t1 SET
SET datac=datac+2
datac=datac+2 WHERE
WHERE datac='2013-03-17';
datac='2013-03-17';
select
select ** from
from pic.t1;
pic.t1;
În urma comenzii UPDATE funcţia triger f8_1() a fost apelată
automat.
Extindem exemplul anterior prin construcţia unui tabel
pic.t2, care pe lângă câmpul datac (data calendaristică) conţine
câmpul cu valoarea veche a anului (înainte de modificare) anul_v şi
câmpul anul_n cu valoarea nouă a anului, după modificare. În
momentul modificării câmpului datac, celelalte două câmpuri anul_v
şi anul_c trebuie să se actualizeze automat. În acest sens,
construim tabelul:
DROP
DROP TABLE
TABLE IF
IF EXISTS
EXISTS pic.t2;
pic.t2; CREATE
CREATE TABLE
TABLE pic.t2(datac
pic.t2(datac date,
date, an_v
an_v
smallint,
smallint, an_n
an_n smallint,idx
smallint,idx serial
serial PRIMARY
PRIMARY KEY);
KEY);
Funcţia triger va fi:
64
8.Funcţii de tip trigger
/*Ex.
/*Ex. 8(2D):*/CREATE
8(2D):*/CREATE OROR REPLACE
REPLACE FUNCTION
FUNCTION pic.f8_2()
pic.f8_2() RETURNS
RETURNS trigger
trigger AS
AS
$$ BEGIN SELECT EXTRACT( YEAR FROM OLD.datac) INTO NEW.an_v;
$$ BEGIN SELECT EXTRACT( YEAR FROM OLD.datac) INTO NEW.an_v;
SELECT
SELECT EXTRACT(
EXTRACT( YEAR
YEAR FROM
FROM NEW.datac)
NEW.datac) INTO
INTO NEW.an_n;
NEW.an_n;
return NEW; END $$ LANGUAGE 'plpgsql';
return NEW; END $$ LANGUAGE 'plpgsql';
Codul pentru ataşarea funcţiei triger f8_2() de tabelul
pic.t2 este:
/*Ex.
/*Ex. 8(2T):*/
8(2T):*/ CREATE
CREATE TRIGGER
TRIGGER t2_trg
t2_trg
BEFORE
BEFORE UPDATE
UPDATE ONON pic.t2
pic.t2 FORFOR EACH
EACH ROW
ROW
WHEN
WHEN ((old.*
((old.* IS
IS DISTINCT
DISTINCT FROM
FROM new.*))
new.*)) EXECUTE
EXECUTE PROCEDURE
PROCEDURE pic.f8_2();
pic.f8_2();
iar pentru testare:
/*Ex.
/*Ex. 8(2A)
8(2A) TESTARE
TESTARE pic.f8_2()
pic.f8_2() pentru
pentru pic.t2
pic.t2 */
*/
INSERT
INSERT INTO
INTO pic.t2(datac)
pic.t2(datac)
VALUES('2013-03-15'),('2013-03-17'),('2013-03-19');
VALUES('2013-03-15'),('2013-03-17'),('2013-03-19');
UPDATE
UPDATE pic.t1
pic.t1 SET
SET datac=datac+5
datac=datac+5 WHERE
WHERE datac='2013-03-17';
datac='2013-03-17';
select
select * from pic.t1 ;select * from pic.t2;
* from pic.t1 ;select * from pic.t2;
Un alt exemplu presupune un tabel pic.t3, cu următoarele
câmpuri: numărul zilei din săptamână nz, denumirea zilei denzi şi
un câmp idx de tip serial. În momentul introducerii numărului
zilei, dacă acesta este între 1 şi 7, se va afişa denumirea
acesteia, altfel numărul zilei rămâne nemodificat:
DROP
DROP TABLE
TABLE IF
IF EXISTS
EXISTS pic.t3;
pic.t3; CREATE
CREATE TABLE
TABLE pic.t3(nz
pic.t3(nz smallint,denzi
smallint,denzi
varchar(15),idx
varchar(15),idx serial
serial PRIMARY
PRIMARY KEY);
KEY);
Funcţia triger pic.f8_3() va avea forma:
/*Ex
/*Ex 8(3D):*/
8(3D):*/ CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTION
FUNCTION pic.f8_3()
pic.f8_3() RETURNS
RETURNS trigger
trigger AS
AS
$$
$$ BEGIN
BEGIN IF
IF NEW.nz=1
NEW.nz=1 THEN
THEN NEW.denzi='Luni';
NEW.denzi='Luni'; END END IF;
IF;
IF
IF NEW.nz=2
NEW.nz=2 THEN
THEN NEW.denzi='Marti';
NEW.denzi='Marti'; END END IF;
IF;
IF
IF NEW.nz=3
NEW.nz=3 THEN
THEN NEW.denzi='Miercuri';
NEW.denzi='Miercuri'; END END IF;
IF;
IF
IF NEW.nz=4
NEW.nz=4 THEN
THEN NEW.denzi='Joi';
NEW.denzi='Joi'; END END IF;
IF;
IF
IF NEW.nz=5
NEW.nz=5 THEN
THEN NEW.denzi='Vineri';
NEW.denzi='Vineri'; END END IF;
IF;
IF
IF NEW.nz=6 THEN NEW.denzi='Sambata'; END
NEW.nz=6 THEN NEW.denzi='Sambata'; END IF;
IF;
IF
IF NEW.nz=7
NEW.nz=7 THEN
THEN NEW.denzi='Duminica';
NEW.denzi='Duminica'; END END IF;
IF;
IF
IF NEW.nz<1
NEW.nz<1 OROR NEW.nz>7
NEW.nz>7 THEN
THEN OLD.denzi=NULL;
OLD.denzi=NULL; return
return OLD;
OLD;
ELSE
ELSE return
return NEW;
NEW; END
END IF;
IF; END
END $$
$$ LANGUAGE
LANGUAGE 'plpgsql';
'plpgsql';
iar comenzile de asociere între funcţia triger şi tabel:
/*Ex.
/*Ex. 8(3T-1):*/
8(3T-1):*/ CREATE
CREATE TRIGGER
TRIGGER t8_3_1_trg
t8_3_1_trg
BEFORE
BEFORE UPDATE ON pic.t3 FOR
UPDATE ON pic.t3 FOR EACH
EACH ROW
ROW
WHEN
WHEN (old.*
(old.* IS
IS DISTINCT
DISTINCT FROM
FROM new.*)
new.*) EXECUTE
EXECUTE PROCEDURE
PROCEDURE pic.f8_3();
pic.f8_3();
În vederea testării, executăm comenzile:
/*Ex.
/*Ex. 8(3A-1)
8(3A-1) TESTARE
TESTARE pic.f8_3()
pic.f8_3() pentru
pentru pic.t3
pic.t3 */
*/
INSERT
INSERT INTO
INTO pic.t3(nz)
pic.t3(nz) VALUES(NULL);
VALUES(NULL); select
select ** from
from pic.t3;
pic.t3;
UPDATE
UPDATE pic.t3
pic.t3 SET
SET nz=2;
nz=2; select
select ** from
from pic.t3;
pic.t3;
UPDATE
UPDATE pic.t3
pic.t3 SET
SET nz=8;
nz=8; select
select ** from
from pic.t3;
pic.t3;
65
III.Programarea la nivel de server – plpgSQL
66
9.Definirea de noi tipuri de date şi supraîncărcarea operatorilor SQL
67
III.Programarea la nivel de server – plpgSQL
a) întoarce valoarea de adevăr TRUE dacă cele două adrese sunt din
aceeaşi ţară:
/*Ex.
/*Ex. 9(1D):*/
9(1D):*/ CREATE
CREATE OROR REPLACE
REPLACE FUNCTION
FUNCTION
pic.op_egal_niv_tara(_a_
pic.op_egal_niv_tara(_a_ adresa01,
adresa01, _b_
_b_ adresa01)
adresa01) RETURNS
RETURNS boolean
boolean AS
AS
$BODY$ BEGIN IF $1.tara = $2.tara OR $1.cod_postal=$2.cod_postal
$BODY$ BEGIN IF $1.tara = $2.tara OR $1.cod_postal=$2.cod_postal
THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF; RETURN
RETURN FALSE;
FALSE; END
END $BODY$
$BODY$ LANGUAGE
LANGUAGE 'plpgsql';
'plpgsql';
b) întoarce valoarea de adevăr TRUE dacă cele două adrese sunt din
acelaşi oraş:
/*Ex.
/*Ex. 9(2D):*/
9(2D):*/ CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTION
FUNCTION
pic.op_egal_niv_oras(_a_
pic.op_egal_niv_oras(_a_ adresa01,
adresa01, _b_
_b_ adresa01)
adresa01) RETURNS
RETURNS boolean
boolean AS
AS
$BODY$
$BODY$ BEGIN
BEGIN IF
IF ($1.tara
($1.tara == $2.tara
$2.tara AND
AND $1.oras=$2.oras)
$1.oras=$2.oras) OROR
$1.cod_postal=$2.cod_postal
$1.cod_postal=$2.cod_postal THEN THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF;
RETURN
RETURN FALSE;
FALSE; END
END $BODY$
$BODY$ LANGUAGE
LANGUAGE 'plpgsql';
'plpgsql';
c) întoarce valoarea de adevăr TRUE dacă cele două adrese sunt pe
aceeaşi stradă:
/*Ex.
/*Ex. 9(3D):*/
9(3D):*/ CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTION
FUNCTION
pic.op_egal_niv_str(_a_
pic.op_egal_niv_str(_a_ adresa01,
adresa01, _b_
_b_ adresa01)
adresa01) RETURNS
RETURNS boolean
boolean AS
AS
$BODY$
$BODY$ BEGIN
BEGIN IF
IF ($1.tara
($1.tara == $2.tara
$2.tara AND
AND $1.oras=$2.oras
$1.oras=$2.oras AND
AND
$1.str=$2.str)
$1.str=$2.str) OROR $1.cod_postal=$2.cod_postal
$1.cod_postal=$2.cod_postal THENTHEN RETURN
RETURN TRUE;END
TRUE;END IF;
IF;
RETURN
RETURN FALSE;
FALSE; END
END $BODY$
$BODY$ LANGUAGE
LANGUAGE 'plpgsql';
'plpgsql';
d) întoarce valoarea de adevăr TRUE dacă cele două adrese sunt
identice:
/*Ex.
/*Ex. 9(4D):*/
9(4D):*/ CREATE
CREATE OROR REPLACE
REPLACE FUNCTION
FUNCTION pic.op_egal_identice(_a_
pic.op_egal_identice(_a_
adresa01,
adresa01, _b_
_b_ adresa01)
adresa01) RETURNS
RETURNS boolean
boolean AS
AS $BODY$
$BODY$ BEGIN
BEGIN
IF
IF ($1.tara
($1.tara == $2.tara
$2.tara AND
AND $1.oras=$2.oras
$1.oras=$2.oras ANDAND $1.str=$2.str
$1.str=$2.str AND
AND
$1.nr=$2.nr)
$1.nr=$2.nr) OROR ($1.cod_postal=$2.cod_postal
($1.cod_postal=$2.cod_postal AND AND $1.nr=$2.nr)
$1.nr=$2.nr)
THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF; RETURN
RETURN FALSE;
FALSE; END
END $BODY$
$BODY$ LANGUAGE
LANGUAGE 'plpgsql';
'plpgsql';
e) este definit operatorul „mai mic” între două date de tip adresa01
în scopul ordonării alfanumerice:
/*Ex
/*Ex 9(5D):*/
9(5D):*/ CREATE
CREATE OROR REPLACE
REPLACE FUNCTION
FUNCTION pic.op_mai_mic(_a_
pic.op_mai_mic(_a_ adresa01,
adresa01,
_b_
_b_ adresa01)
adresa01) RETURNS
RETURNS boolean
boolean AS
AS
$BODY$
$BODY$ BEGIN
BEGIN IFIF $1.tara
$1.tara << $2.tara
$2.tara THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF;
IF
IF $1.tara=$2.tara
$1.tara=$2.tara THENTHEN
if
if $1.oras<$2.oras
$1.oras<$2.oras then
then return
return TRUE;end
TRUE;end if;
if; END
END IF;
IF;
IF
IF $1.tara
$1.tara == $2.tara
$2.tara andand $1.oras=$2.oras
$1.oras=$2.oras THEN
THEN
if
if $1.str
$1.str << $2.str
$2.str then
then return
return TRUE;
TRUE; end
end if;
if; END
END IF;
IF;
IF
IF $1.tara
$1.tara == $2.tara
$2.tara andand $1.oras=$2.oras
$1.oras=$2.oras andand $1.str=$2.str
$1.str=$2.str THEN
THEN
if
if $1.nr
$1.nr << $2.nr
$2.nr then
then return
return TRUE;
TRUE; end
end if;
if; END
END IF;
IF;
RETURN
RETURN FALSE;END
FALSE;END $BODY$
$BODY$ LANGUAGE
LANGUAGE plpgsql;
plpgsql;
f) este definit operatorul „mai mare” între două date de tip
adresa01 în scopul ordonării alfanumerice:
68
9.Definirea de noi tipuri de date şi supraîncărcarea operatorilor SQL
/*Ex.
/*Ex. 9(6D):*/
9(6D):*/ CREATE
CREATE OROR REPLACE
REPLACE FUNCTION
FUNCTION pic.op_mai_mare(_a_
pic.op_mai_mare(_a_
adresa01,
adresa01, _b_ adresa01) RETURNS boolean AS
_b_ adresa01) RETURNS boolean AS
$BODY$
$BODY$ BEGIN
BEGIN IF
IF $1.tara
$1.tara >> $2.tara
$2.tara THEN
THEN RETURN
RETURN TRUE;END
TRUE;END IF;
IF;
IF $1.tara=$2.tara THEN
IF $1.tara=$2.tara THEN
if
if $1.oras>$2.oras
$1.oras>$2.oras thenthen return
return TRUE;end
TRUE;end if;
if; END
END IF;
IF;
IF $1.tara = $2.tara and $1.oras = $2.oras
IF $1.tara = $2.tara and $1.oras = $2.oras THEN THEN
IF
IF $1.str
$1.str >> $2.str
$2.str THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF; END
END IF;
IF;
IF
IF $1.tara = $2.tara and $1.oras = $2.oras and $1.st r= $2.str THEN
$1.tara = $2.tara and $1.oras = $2.oras and $1.st r= $2.str THEN
IF
IF $1.nr
$1.nr >> $2.nr
$2.nr THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF; END END IF;
IF;
RETURN
RETURN FALSE;END
FALSE;END $BODY$
$BODY$ LANGUAGE
LANGUAGE plpgsql;
plpgsql;
g) este definit operatorul “mai mic sau egal” între două date de tip
adresa01 în scopul ordonării alfanumerice:
/*Ex.
/*Ex. 9(7D):*/
9(7D):*/ CREATE
CREATE OROR REPLACE
REPLACE FUNCTION
FUNCTION pic.op_mai_mic_egal(_a_
pic.op_mai_mic_egal(_a_
adresa01,
adresa01, _b_
_b_ adresa01)
adresa01) RETURNS
RETURNS boolean
boolean ASAS
$BODY$
$BODY$ BEGIN
BEGIN IFIF $1.tara
$1.tara <=
<= $2.tara
$2.tara THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF;
IF
IF $1.tara=$2.tara
$1.tara=$2.tara THENTHEN
if
if $1.oras<=$2.oras
$1.oras<=$2.oras then
then RETURN
RETURN TRUE;end
TRUE;end if;END
if;END IF;
IF;
IF
IF $1.tara
$1.tara == $2.tara
$2.tara andand $1.oras
$1.oras == $2.oras
$2.oras THEN
THEN
IF
IF $1.str
$1.str <=
<= $2.str
$2.str THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF; END
END IF;
IF;
IF
IF $1.tara
$1.tara == $2.tara
$2.tara andand $1.oras=$2.oras
$1.oras=$2.oras andand $1.str=$2.str
$1.str=$2.str THEN
THEN
IF
IF $1.nr
$1.nr <=
<= $2.nr
$2.nr THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF; END
END IF;
IF;
RETURN
RETURN FALSE;
FALSE; END
END $BODY$
$BODY$ LANGUAGE
LANGUAGE plpgsql;
plpgsql;
h) este definit operatorul “mai mare sau egal” între două date de
tip adresa01 în scopul ordonării alfanumerice:
/*Ex
/*Ex 9(8D):*/
9(8D):*/ CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTION
FUNCTION pic.op_mai_mare_egal(_a_
pic.op_mai_mare_egal(_a_
adresa01,
adresa01, _b_
_b_ adresa01)
adresa01) RETURNS
RETURNS boolean
boolean ASAS
$BODY$
$BODY$ BEGIN
BEGIN IFIF $1.tara
$1.tara >=
>= $2.tara
$2.tara THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF;
IF
IF $1.tara=$2.tara
$1.tara=$2.tara THEN
THEN
if
if $1.oras>=$2.oras
$1.oras>=$2.oras then
then RETURN
RETURN TRUE;end
TRUE;end if;
if; END
END IF;
IF;
IF
IF $1.tara
$1.tara == $2.tara
$2.tara andand $1.oras
$1.oras == $2.oras
$2.oras THEN
THEN
IF
IF $1.str
$1.str >=
>= $2.str
$2.str THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF; END
END IF;
IF;
IF
IF $1.tara
$1.tara == $2.tara
$2.tara andand $1.oras
$1.oras == $2.oras
$2.oras and
and $1.str
$1.str == $2.str
$2.str THEN
THEN
IF
IF $1.nr
$1.nr >=
>= $2.nr
$2.nr THEN
THEN RETURN
RETURN TRUE;
TRUE; END
END IF;
IF; END
END IF;
IF;
RETURN
RETURN FALSE;
FALSE; END
END $BODY$
$BODY$ LANGUAGE
LANGUAGE plpgsql;
plpgsql;
i) operatorul de indexare (implicit, pentru indexare, SGBD-ul
utilizează o tehnică ce utililizează arbori binari – btree)
69
III.Programarea la nivel de server – plpgSQL
/*Ex.
/*Ex. 9(9D):
9(9D): */*/ CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTION
FUNCTION pic.op_btree(_a_
pic.op_btree(_a_ adresa01,
adresa01,
_b_ adresa01) RETURNS integer AS $BODY$
_b_ adresa01) RETURNS integer AS $BODY$ BEGIN BEGIN
IF
IF $1.tara
$1.tara << $2.tara
$2.tara OROR ($1.tara
($1.tara == $2.tara
$2.tara and
and $1.oras
$1.oras << $2.oras)
$2.oras) OR
OR
($1.tara=$2.tara and $1.oras=$2.oras and $1.str<$2.str)
($1.tara=$2.tara and $1.oras=$2.oras and $1.str<$2.str) OR OR
($1.tara=$2.tara
($1.tara=$2.tara and and $1.oras=$2.oras
$1.oras=$2.oras and and $1.str=$2.str
$1.str=$2.str and
and
$1.nr<$2.nr)
$1.nr<$2.nr) THEN RETURN -1; END
THEN RETURN -1; END IF; IF;
IF
IF $1.tara
$1.tara >> $2.tara
$2.tara OROR ($1.tara
($1.tara == $2.tara
$2.tara and
and $1.oras
$1.oras >> $2.oras)
$2.oras) OR
OR
($1.tara
($1.tara = $2.tara and $1.oras = $2.oras and $1.str > $2.str) OR
= $2.tara and $1.oras = $2.oras and $1.str > $2.str) OR
($1.tara=$2.tara
($1.tara=$2.tara and and $1.oras=$2.oras
$1.oras=$2.oras and and $1.str=$2.str
$1.str=$2.str AND
AND
$1.nr>$2.nr) THEN RETURN 1; END
$1.nr>$2.nr) THEN RETURN 1; END IF; IF;
RETURN
RETURN 0;
0; END;
END; $BODY$
$BODY$ LANGUAGE
LANGUAGE plpgsql
plpgsql ;;
Funcţia operator de indexare întoarce valorile -1, +1 sau 0,
în funcţie de egalitate. Urmează etapa în care asignăm simboluri de
operatori SQL cu funcţiile operator definite mai sus. Astfel sunt
definiţi operatorii:
/*Ex.
/*Ex. 9(1L):*/
9(1L):*/ CREATE
CREATE OPERATOR
OPERATOR ==(
==( PROCEDURE
PROCEDURE == pic.op_egal_niv_tara,
pic.op_egal_niv_tara,
LEFTARG
LEFTARG == adresa01,
adresa01, RIGHTARG
RIGHTARG == adresa01);
adresa01);
/*Ex.
/*Ex. 9(2L):*/
9(2L):*/ CREATE
CREATE OPERATOR
OPERATOR ===(
===( PROCEDURE
PROCEDURE == pic.op_egal_niv_oras,
pic.op_egal_niv_oras,
LEFTARG
LEFTARG == adresa01,
adresa01, RIGHTARG
RIGHTARG == adresa01);
adresa01);
/*Ex.
/*Ex. 9(3L):*/
9(3L):*/ CREATE
CREATE OPERATOR
OPERATOR ====(
====( PROCEDURE
PROCEDURE == pic.op_egal_niv_str,
pic.op_egal_niv_str,
LEFTARG
LEFTARG == adresa01,
adresa01, RIGHTARG
RIGHTARG == adresa01);
adresa01);
/*Ex.
/*Ex. 9(4L):*/
9(4L):*/ CREATE
CREATE OPERATOR
OPERATOR ===*(PROCEDURE
===*(PROCEDURE == pic.op_egal_identice,
pic.op_egal_identice,
LEFTARG
LEFTARG == adresa01,
adresa01, RIGHTARG
RIGHTARG == adresa01);
adresa01);
/*Ex.
/*Ex. 9(5L):*/
9(5L):*/ CREATE
CREATE OPERATOR
OPERATOR <(PROCEDURE
<(PROCEDURE == pic.op_mai_mic,
pic.op_mai_mic,
LEFTARG
LEFTARG == adresa01,
adresa01, RIGHTARG
RIGHTARG == adresa01);
adresa01);
/*Ex.
/*Ex. 9(6L):*/
9(6L):*/ CREATE
CREATE OPERATOR
OPERATOR <=(
<=( PROCEDURE
PROCEDURE == pic.op_mai_mic_egal,
pic.op_mai_mic_egal,
LEFTARG = adresa01, RIGHTARG = adresa01);
LEFTARG = adresa01, RIGHTARG = adresa01);
/*Ex.
/*Ex. 9(7L):*/
9(7L):*/ CREATE
CREATE OPERATOR
OPERATOR >(
>( PROCEDURE
PROCEDURE == pic.op_mai_mare,
pic.op_mai_mare,
LEFTARG
LEFTARG == adresa01,
adresa01, RIGHTARG
RIGHTARG == adresa01);
adresa01);
/*Ex.
/*Ex. 9(8L):*/
9(8L):*/ CREATE
CREATE OPERATOR
OPERATOR >=(
>=( PROCEDURE
PROCEDURE == pic.op_mai_mare_egal,
pic.op_mai_mare_egal,
LEFTARG
LEFTARG == adresa01,
adresa01, RIGHTARG
RIGHTARG == adresa01);
adresa01);
Următoarea etapă constă în crearea clasei de operatori
pentru funcţia de indexare.
/*Ex.
/*Ex. 9(9L):*/
9(9L):*/ CREATE
CREATE OPERATOR
OPERATOR CLASS
CLASS adresa01_operatii
adresa01_operatii DEFAULT
DEFAULT
FOR TYPE adresa01 USING btree
FOR TYPE adresa01 USING btree AS AS
OPERATOR
OPERATOR 11 <,<, OPERATOR
OPERATOR 22 <=,
<=, OPERATOR
OPERATOR 33 ===*,
===*,
OPERATOR 4 >=,
OPERATOR 4 >=, OPERATOR 5 >,
OPERATOR 5 >,
FUNCTION
FUNCTION 11 pic.op_btree(adresa01,
pic.op_btree(adresa01, adresa01);
adresa01);
/*Ex.
/*Ex. 7(10L)*/CREATE
7(10L)*/CREATE OPERATOR
OPERATOR FAMILY
FAMILY adresa01_operatii
adresa01_operatii USING
USING btree;
btree;
Urmează etapa de testare:
70
9.Definirea de noi tipuri de date şi supraîncărcarea operatorilor SQL
/*Ex.
/*Ex. 9(5A)
9(5A) TESTARE
TESTARE pentru
pentru tipul
tipul adresa01
adresa01 */
*/
SELECT
SELECT ** FROM
FROM pic.pers
pic.pers WHERE
WHERE adresa
adresa ==
==
''(''Tara2'',''Reg4'',''Oras3'',''Str1'',5,5006,''-'',''-'')
(''Tara2'',''Reg4'',''Oras3'',''Str1'',5,5006,''-'',''-'')'::adresa01;
'::adresa01;
–-
–- pentru
pentru verificarea
verificarea operatorului
operatorului dede indexare
indexare realizăm
realizăm oo ordonare
ordonare
SELECT
SELECT ** FROM
FROM pic.pers
pic.pers ORDER
ORDER BY
BY adresa;
adresa;
În exemplul de mai sus, în prima interogare s-a testat
operatorul == (egalitate la nivel de ţară), interogarea trebuie să
întoarcă toate înregistrările pentru 'Tara2'. În a doua interogare
este testat operatorul de indexare prin utilizarea ordonării.
Pentru a testa intrarea în funcţia de indexare, se poate
introduce o notificare sau se poate simula o eroare în această
funcţie. De asemenea, se poate testa operatorul de indexare prin
utilizarea câmpului de tip adresa01 în construcţia pentru PRIMARY
KEY.
/*Ex.
/*Ex. 9(6A)TESTARE
9(6A)TESTARE pentru
pentru adresa01
adresa01 */
*/ DROP
DROP TABLE
TABLE IF
IF EXISTS
EXISTS pic.pers2;
pic.pers2;
CREATE
CREATE TABLE
TABLE pic.pers2(nume
pic.pers2(nume varchar(40),adresa
varchar(40),adresa adresa01
adresa01 PRIMARY
PRIMARY KEY);
KEY);
/*Ex.
/*Ex. 9(7A)TESTARE
9(7A)TESTARE pentru
pentru adresa01
adresa01 */
*/
INSERT
INSERT INTO
INTO pic.pers2(nume,adresa)
pic.pers2(nume,adresa) VALUES
VALUES
('Nume5','(''Tara1'',''Reg3'',''Oras4'',''Str1'',5,5005,''-'',''-'')'),
('Nume5','(''Tara1'',''Reg3'',''Oras4'',''Str1'',5,5005,''-'',''-'')'),
('Nume3','(''Tara2'',''Reg4'',''Oras3'',''Str1'',5,5006,''-'',''-'')'),
('Nume3','(''Tara2'',''Reg4'',''Oras3'',''Str1'',5,5006,''-'',''-'')'),
('Nume3','(''Tara2'',''Reg4'',''Oras3'',''Str1'',5,5006,''-'',''-'')'),
('Nume3','(''Tara2'',''Reg4'',''Oras3'',''Str1'',5,5006,''-'',''-'')'),
('Nume8','(''Tara1'',''Reg3'',''Oras2'',''Str1'',5,5003,''-'',''-'')');
('Nume8','(''Tara1'',''Reg3'',''Oras2'',''Str1'',5,5003,''-'',''-'')');
Înregistrările 2 şi 3 sunt identice, ceea ce va genera o
eroare în funcţia btree().
71
III.Programarea la nivel de server – plpgSQL
CREATE
CREATE OR
OR REPLACE
REPLACE FUNCTION
FUNCTION pic.parcare(_nr_inmatr_
pic.parcare(_nr_inmatr_ text,_data_
text,_data_ date
date
DEFAULT
DEFAULT CURRENT_DATE,
CURRENT_DATE, _ora_
_ora_ time
time DEFAULT
DEFAULT CURRENT_TIME)
CURRENT_TIME)
RETURNS
RETURNS interval
interval ASAS $$
$$ DECLARE
DECLARE ff boolean;
boolean; dif
dif interval;
interval;
BEGIN
BEGIN --verificăm
--verificăm dacă
dacă există
există deja
deja maşina
maşina în
în parcare
parcare
SELECT
SELECT EXISTS(SELECT
EXISTS(SELECT ** FROMFROM pic.parc
pic.parc
WHERE
WHERE nr_inmatr
nr_inmatr == _nr_inmatr_
_nr_inmatr_ AND
AND dataout
dataout IS
IS NULL)
NULL) INTO
INTO f;
f;
IF NOT f THEN INSERT INTO pic.parc(datain,orain,nr_inmatr)
IF NOT f THEN INSERT INTO pic.parc(datain,orain,nr_inmatr) VALUES VALUES
(_data_,_ora_,_nr_inmatr_);RETURN
(_data_,_ora_,_nr_inmatr_);RETURN '0'::interval;
'0'::interval; ENDEND IF;--intrare
IF;--intrare nouă
nouă
UPDATE pic.parc SET dataout = _data_, oraout
UPDATE pic.parc SET dataout = _data_, oraout = _ora_ = _ora_
WHERE
WHERE nr_inmatr
nr_inmatr == _nr_inmatr_
_nr_inmatr_ ANDAND dataout
dataout IS
IS NULL;
NULL;
SELECT dataout + oraout - datain - orain FROM pic.parc WHERE
SELECT dataout + oraout - datain - orain FROM pic.parc WHERE nr_inmatr nr_inmatr
== _nr_inmatr_
_nr_inmatr_ AND
AND dataout
dataout == _data_
_data_ AND
AND oraout
oraout == _ora_
_ora_ INTO
INTO dif;
dif;
RETURN dif; END; $$ LANGUAGE 'plpgsql';
RETURN dif; END; $$ LANGUAGE 'plpgsql';
Întodeauna trecem argumentele implicite (cu DEFAULT) după
cele obligatorii.
SELECT
SELECT pic.parcare('BC-45-AAA');
pic.parcare('BC-45-AAA'); SELECT
SELECT ** from
from pic.parc;
pic.parc;
SELECT
SELECT pic.parcare('BC-45-AAA');
pic.parcare('BC-45-AAA'); SELECT
SELECT ** from
from pic.parc;
pic.parc;
72
IV.Introducere în limbajul C
1. Organizarea programelor
La baza oricărei aplicaţii software sau pentru cazurile
simple stă un algoritm (metodă de rezolvare). Acesta preia date din
memoria dinamică a calculatorului (RAM) sau de pe suporturi de
stocare şi le prelucrează. Rezultatul prelucrării (a execuţiei
algoritmilor) este stocat în memoria dinamică şi apoi poate fi
afişat, memorat pe suporturi de stocare a datelor, sau transmis
către alte aplicaţii software.
Codul sursă se scrie cu ajutorul unui editor de texte, acest
editor poate fi unul simplu gen notepad, notepad++, getit sau unul
specializat, înglobat într-un mediu integrat de dezvoltare pentru
software-uri (ex.: TuboC++, BorlandC++, C++Builder, VisualC++,
SymantecC++, DevC++, CodeLite, NetBean, EclipseC++, gt++, gtk++
etc.).
Compilatorul transformă codul sursă în cod obiect, altfel spus:
transformă textul literar în cod maşină – reprezentat de comenzi la
nivel de microprocesor).
Executabil / bibliotecă
Programator (*.exe,aplicaţie,*.dll,*.lib,*.so,*.a,…)
Editare Linkeditare Linkeditare
Editor de text Link-editor
Compilator
Cod sursă Cod obiect Biblioteci statice
(*.c,*.cpp) Compilare (*.obj/*.o) (*.lib/*.a)
Figura IV-1: Etapele pentru obţinerea unei aplicaţii software
În cadrul codului sursă se pot utiliza rutine
(proceduri/funcţii) definite în cadrul unor biblioteci statice
73
IV.Introducere în limbajul C
(*.lib – library sau *.a – archive), caz în care codul utilizat din
bibliotecile statice este încorporat în executabil.
Codul bibliotecilor dinamice (*.dll – dynamic link library
sau *.so – shared objects) este doar apelat în momentul execuţiei
sau al lansării aplicaţiei (diferenţele apar pentru Linux), acesta
nefiind inclus în fişierul executabil sau în biblioteca rezultată.
1.1. Structura unui program în limbajul C/C++
Un program C/C++ cuprinde următoarele elemente pricipale:
✗ operatori (aritmetici, logici etc.);
✗ instrucţiuni (de decizie, de parcurgere a unei bucle etc.);
✗ funcţii (apelate din cadrul bibliotecilor sau definite de
utilizator);
✗ variabile şi constante;
✗ funcţia main().
Textul unui program poate fi scris într-un fişier sau în mai
multe fişiere. Un program va avea o singură funcţie main(),
indiferent dacă este scris într-un singur fişier sau în mai multe
fişiere. Programul compilat şi linkeditat va începe întodeauna prin
lansarea în execuţie a instrucţiunilor şi funcţiilor din cadrul lui
main(). Prin ieşirea din funcţia main() se încheie şi execuţia
programului.
Comentariile sunt reprezentate prin simbolurile:
/*comentariu la nivel de bloc*/ iar //comentariu la nivel de linie.
74
2.Variabile, alocări, tipuri de date, operatori C/C++
75
IV.Introducere în limbajul C
76
2.Variabile, alocări, tipuri de date, operatori C/C++
2.5. Teste
Scrieţi ce se afişează în urma execuţiei următoarelor
instrucţiuni (liniile sunt independente), iar în cazul existenţei
unor erori să se semnalezeze erorile apărute în urma execuţiei şi
sursa acestora:
1. inta = 19; (a %= +3)++; printf(“a=%d”,a);
2. inta = 19; (a%= -3)--; printf(“a=%d”,a);
3. inta = 33; a>>=2;printf(“%d”,a);
4. inta = 10,b; b = (a | 15) & (a ^ 12); printf(“%d”,b);
5. inta = 11, b, c, d; b = (a ^ 11) & (a | 22); c= a ^ 11; d=a | 22;
printf(“b=%d c=%d d=%d”,b,c,d);
6. int a,b = 13; a=(--b)++; printf(“a=%d”,a);
7. int a = 15,b=2;if((a>1)&&(b>=3)) a <<= b; else a >>= b; printf(“a=
%d”,a);
8. int a = 13,b; b = (a ^ 5) & (a | 2); printf(“b=%d”,b);
9 int a = 10; a >>= 2; printf(“a=%d”,a);
10.int a = 10, b, c, d; b=(a^10)&(a|11); c= a^10; d=a|2;
printf(“b=%d c=%d d=%d”,b,c,d);
77
IV.Introducere în limbajul C
78
3.Implementarea structurilor de control
79
IV.Introducere în limbajul C
switch
switch (<expresie>)//Sintaxa:
(<expresie>)//Sintaxa: int
int a=3,b=4;
a=3,b=4; cin>>luna;
cin>>luna;
{{ switch(luna)
switch(luna)
case
case expresie_const_1:
expresie_const_1: instr_1;[break;]
instr_1;[break;] {{ case
case 1:a++;
1:a++; break;
break;
case
case expresie_const_2: instr_2;[break;]
expresie_const_2: instr_2;[break;] case
case 2:{a--;b++;} break;
2:{a--;b++;} break;
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. case
case 3:{a--;b--;}
3:{a--;b--;}
case
case expresie_const_n:
expresie_const_n: instr_n; instr_n; case
case 4:a--;
4:a--;
[[ default:instrucţiune_m;
default:instrucţiune_m; ]] default:{a=0;
default:{a=0; b=0;}
b=0;}
}} }} cout<<”a=”<<a<<”b”<<b;
cout<<”a=”<<a<<”b”<<b;
Ex.:
• pentru luna=1 obţinem a=4, b=4
• pentru luna=2 obţinem a=2, b=5
• pentru luna=3 obţinem a=1, b=3
• pentru luna=4 obţinem a=2, b=4
• pentru luna>4 obţinem a=0, b=0
3.3. Implementarea structurilor repetitive (ciclice)
Există două categorii de
instrucţiuni ciclice: cu test
iniţial şi cu test final.
Structura ciclică cu test iniţial < EXPRESIE_1 >
este implementată prin (de obicei iniţializare
instrucţiunile for şi while, iar contori)
cea cu test final este
implementată prin instrucţiunea
do while.
3.3.1. Implementarea structurilor FALSE
Evaluare
ciclice cu test iniţial – < EXPRESIE_2 >
Instrucţiunea for
Limbajul C are o TRUE
instrucţiune for deosebit de
flexibilă. Instrucţiunea for BLOC_INSTRUCŢIUNI
implementează structura ciclică (blocul instr. for)
cu număr cunoscut de paşi.
Sintaxa:
for( EXPRESIE_1;;EXPRESIE_2
for(EXPRESIE_1 EXPRESIE_2;;EXPRESIE_3
EXPRESIE_3))
BLOC < EXPRESIE_3 >
BLOC INSTRUCŢIUNI;
INSTRUCŢIUNI; (de obicei
int
int aa == 0;
0; incrementare contori)
for(int
for(int i=0;i<100;i++)
i=0;i<100;i++) a++;
a++; Figura IV-4: Diagrama
În continuare este pre- instrucţiunii for
zentat pseudocodul şi un exemplu.
80
3.Implementarea structurilor de control
Evaluare
Evaluare EXPRESIE_1
EXPRESIE_1 int
int i,j,m,n,a,b;
i,j,m,n,a,b; int
ATÂT
ATÂT TIMP
TIMP cât
cât for(i=0;i<n;i++) int a=9;
a=9;
EXPRESIE_2 este TRUE for(i=0;i<n;i++) for(;;)
EXPRESIE_2 este TRUE for(j=0;j<m;j++) for(;;)
REPETĂ for(j=0;j<m;j++) {a--;
REPETĂ {a+=i*j; {a--;
begin {a+=i*j; if(a<5)
begin if(i<j)
if(i<j) b=a;
b=a;
if(a<5)
BLOC_INSTRUCŢIUNI
BLOC_INSTRUCŢIUNI else
break;
break;
Evaluare EXPRESIE_3 else b=-a;
b=-a; }}
Evaluare EXPRESIE_3 }}
end
end
Nu este obligatorie prezenţa expresiilor, ci doar a instruc-
ţiunilor vide. În exemplul de mai sus (dreapta) instrucţiunea for
implementează o buclă infinită, iar în exemplul de mai sus (stânga)
sunt implementate mai multe bucle for imbricate.
81
IV.Introducere în limbajul C
Sintaxa: do
do BLOC_INSTRUCŢIUNI
BLOC_INSTRUCŢIUNI
while(<EXPRESIE>)
while(<EXPRESIE>) BLOC_INSTRUCŢIUNI
Se execută blocul de
instrucţiuni. Se evaluează apoi
<EXPRESIE>. Dacă aceasta are
valoarea de adevăr TRUE, se execută
din nou blocul de instrucţiuni,
altfel se iese din buclă. Se TRUE FALSE
Evaluare
testează din nou valoarea <EXPRESIE>
expresiei. Se repetă execuţia
blocului de instrucţiuni atât timp
cât valoarea de adevăr a expresiei
este TRUE. În cazul instrucţiunii Figura IV-6: Diagrama
do while, corpul ciclului se instrucţiunii do while
execută cel puţin o dată.
3.3.4. Instrucţiunea “break”
82
3.Implementarea structurilor de control
/*Ex.3.3(1):
/*Ex.3.3(1): calculul
calculul valorii
valorii unei
unei integrale
integrale definite
definite dede la
la aa la
la b*/
b*/
#include <stdio.h>
#include <stdio.h>
double
double f1(int
f1(int x)x) {return
{return x*x-5*x+2;}
x*x-5*x+2;} //f1 //f1 este
este un
un ex.
ex. de
de functie
functie
double
double integr(double a, double b, int n) // fct.ce întoarce val.integr.
integr(double a, double b, int n) // fct.ce întoarce val.integr.
{{ //pas
//pas –– inaltimea
inaltimea unuiunui trapez,
trapez, sum-suma
sum-suma partiala
partiala sisi cea
cea finala
finala
//
// aa bb sunt
sunt cele
cele doua
doua valori
valori intre
intre care
care sese calc.
calc. integrala
integrala
double
double q, q, sum,
sum, pas
pas == (b(b -- a)
a) // (n
(n ** 1.0);
1.0);
for(sum
for(sum == 0, 0, qq == aa ++ pas;
pas; qq <=
<= b;b; qq +=
+= pas)
pas)
sum
sum +=+= (( f1(q)
f1(q) ++ f1(q-pas)
f1(q-pas) )) ** pas pas // 2.0;
2.0;
return
return sum;
sum; }}
int
int main()
main()
{double
{double hh == integr(2,8,10000);
integr(2,8,10000); printf("Integrala:
printf("Integrala: %f\n",h);
%f\n",h);
return
return 0;}0;}
83
IV.Introducere în limbajul C
aa == d[1][2][0][3];
d[1][2][0][3];
//
// aa preia
preia valoarea
valoarea unei
unei celule
celule din
din cadrul
cadrul tabloului
tabloului dd
Indecşii încep cu valoarea 0. În memoria RAM tablourile sunt
repezentate prin secvenţe continue. Practic, d va conţine adresa
tabloului (un bloc compact de 5x6x3x4 elemente, ocupând în memorie
5x6x3x4x8 octeţi – double este reprezentat pe 8 octeţi).
În cazul alocării dinamice a tabloului d (double ****d),
primii 3 vectori din imagine conţin adrese şi doar ultimul vector
conţine valorile de tip double.
84
4.Tablouri şi pointeri. Aritmetica pointerilor.
d[4]
d[3] d[3][0] d[3][1] d[3][2] d[3][3] d[3][4] d[3][5]
d[2] d[3][2][0] d[3][2][0][0] d[3][2][0][1] d[3][2][0][2] d[3][2][0][3]
d[1] d[3][2][1]
d[0] d[3][2][2]
Figura IV-7: Referirea la celula d[3][2[0][3] într-un tablou
cu 4 dimensiuni alocat dinamic
Variabila d conţine adresa celulei d[0]. Celula d[3] conţine
adresa vectorului desenat în dreapta acesteia. Celula d[3][2]
conţine adresa vectorului desenat sub această celulă. Celula
d[3][2][0] conţine adresa vectorului desenat în dreapta acesteia.
Ultimul vector din dreapta conţine doar valori de tipul double. În
continuare este prezentat un exemplu de declaraţii de variabile,
inclusiv de tip tablou.
int
int a,
a, *a1,
*a1, a2[4],
a2[4], b1[3][4],
b1[3][4], *b2[5],
*b2[5], **b3;
**b3;
int
int c1[4][7][2], *c2[14][6], **c3[7], ***c4;
c1[4][7][2], *c2[14][6], **c3[7], ***c4;
În acest exemplu, a este o variabilă de tip întreg (conţine
o valoare de tip întreg), a1 este o variabilă pointer la tip
întreg (conţine adresa unde este memorată variabila de tip întreg),
a2 este un tablou unidimensional (vector) cu 4 elemente de tip
întreg, b1 este un tablou bidimensional (matrice) cu 3x4 elemente
de tip întreg, b2 este un vector cu 5 elemente de tip pointer la
întreg, b3 este un pointer la o matrice cu elemente de tip întreg,
c1 este un tablou tridimensional cu elemente de tip întreg şi cu
dimensiunea 4x7x2, c2 este o matrice 14x6 cu elementele de tip
pointer la tip întreg, c3 este un vector cu 7 elemente de tip
pointer la matrice de tip întreg, iar c4 este un pointer la tablou
tridimensional cu elemente de tip întreg. În continuare este
prezentat şi un exemplu de atribuiri cu elemente din cadrul
tablourilor.
aa == a2[1];
a2[1]; aa == b1[0][0];
b1[0][0]; aa == c1[1][0][1];
c1[1][0][1]; a1 a1 == a2;
a2;
a1
a1 = b1[1]; a1 = b2[3]; a1 = c1[1][2]; a1 = c2[1][0];
= b1[1]; a1 = b2[3]; a1 = c1[1][2]; a1 = c2[1][0];
b3
b3 == c2[3];
c2[3]; b3b3 == c3[1];
c3[1];
aa == *a1;
*a1; a = a1[0];
a = a1[0]; aa == b2[2][0];
b2[2][0]; aa == c2[1][0][0];
c2[1][0][0];
c3[2][0][0]
c3[2][0][0] == a; a; a1a1 == &a;
&a; b3[1]
b3[1] == a1;
a1; c4[0]
c4[0] == c3[1];
c3[1];
În urma execuţiei instrucţiunii a=a1[1];, variabila a va avea
aceeaşi valoare ca şi în cazul execuţiei instrucţiunii a=a2[1];.
4.3. Alocarea dinamică a memoriei
Variabilele de tip pointer presupun utilizarea alocării
dinamice pentru memorie, cu excepţia cazurilor când acestea
copiază adresa altor zone de memorie deja alocate. Utilizatorul
85
IV.Introducere în limbajul C
int
int *p;
*p; pp == new
new int[
int[ nn ];
];
sau if( p == NULL ) { printf(„Memorie
if( p == NULL ) { printf(„Memorie insuficienta!”);}
insuficienta!”);}
//......
//......
if(
if( pp )) delete[]
delete[] p;p;
Notă: Operatorul delete se utilizează urmat de [] doar atunci când
variabila a cărei memorie rezervată urmează a fi eliberată este de
tip vector.
În continuare este prezentată o funcţie de alocarea dinamică
a unei matrice cu elemente de tipul double. Funcţia aloca2double
preia numărul de linii şi coloane a matricei ce urmează a fi
alocate dinamic şi întoarce adresa primului vector (echivalentul
adresei celulei d[0] din exemplul de mai sus):
86
4.Tablouri şi pointeri. Aritmetica pointerilor.
/*Ex.[4.1]*/
/*Ex.[4.1]*/ doubledouble **aloca2double(int
**aloca2double(int m,int m,int n)
n)
{double **A; int
{double **A; int k,i; k,i;
AA == (double**)
(double**) malloc(
malloc( mm ** sizeof(double*)
sizeof(double*) ); );
if( !A ) return
if( !A ) return NULL; NULL;
for(
for( kk == 0; 0; kk << m;
m; k++
k++ ))
{{ A[k]
A[k] = (double*) malloc(
= (double*) malloc( nn ** sizeof(double)
sizeof(double) ); );
if(
if( !A!A )) //alocare
//alocare esuata,
esuata, elibereaza
elibereaza memoria
memoria deja
deja alocată
alocată
{{ for( i = 0; i < k; i++ ) free(
for( i = 0; i < k; i++ ) free( A[i] ); A[i] );
free(
free( AA ); ); return
return NULL;
NULL;
}//endif
}//endif
}//endfor
}//endfor
for(
for( kk == 0; 0; kk << m;
m; k++
k++ ))
for(
for( ii == 0;0; ii << n;
n; i++
i++ )) A[k][i]
A[k][i] == 0;
0;
return A;}
return A;}
Funcţia de dealocare pentru matricea alocată dinamic va avea
forma:
/*Ex.[4.2]:*/
/*Ex.[4.2]:*/ voidvoid elib2double(
elib2double( double**A,
double**A, int
int mm ))
{int
{int k;
k;
for(
for( kk == 0;
0; kk << m;
m; k++
k++ )) if(
if( A[k]
A[k] )) free(
free( A[k]
A[k] ););
if(
if( AA )) free(
free( AA );); }}
Funcţia preia adresa matricei şi numărul de linii. În cadrul
contorului k sunt dealocaţi vectorii care au reuşit să fie alocaţi
dinamic. Utilizarea celor două funcţii este redată în exemplul
următor:
/*
/* ExEx #4.3:
#4.3: */*/ #include
#include <stdio.h>
<stdio.h>
#include
#include <stdlib.h>/*\n*/
<stdlib.h>/*\n*/ #include
#include <time.h>/*\n*/
<time.h>/*\n*/ #include
#include <bfd.h>
<bfd.h>
//declarare
//declarare şi şi explicitare
explicitare funcţie
funcţie alocare
alocare dinamică
dinamică --
-- aloca2double
aloca2double
//elibereaza
//elibereaza zona zona dede memorie
memorie alocata
alocata -- -- elib2double
elib2double
double
double **x;
**x; int
int m1m1 == 3,
3, n1
n1 == 4;
4;
srand(
srand( time(NULL)
time(NULL) ); ); //inţializare
//inţializare generare
generare numere
numere aleatoare
aleatoare
xx == aloca2double(
aloca2double( m1, m1, n1
n1 );
); //apel
//apel functie
functie alocare
alocare dinamica
dinamica
//iniţializarea
//iniţializarea variabilei
variabilei alocate
alocate dinamic
dinamic cu
cu valori
valori aleatoare
aleatoare
for(
for( intint ii == 0;
0; ii << m1;
m1; i++
i++ ))
for(
for( int
int jj == 0;
0; jj << n1;
n1; j++
j++ ))
x[i][j]
x[i][j] == rand()
rand() %% 100;//rand()
100;//rand() generează
generează nr.aleatoare:
nr.aleatoare: 1÷2^16
1÷2^16
for(
for( intint ii == 0;
0; ii << m1;
m1; i++
i++ ))
{{ for(
for( int
int jj == 0;0; jj << n1;
n1; j++
j++ )) printf("
printf(" %f%f ",x[i][j]);
",x[i][j]);
printf("\n");
printf("\n");
}}
elib2double(
elib2double( x, x, m1
m1 );); return
return 0;}0;}
Notă: Fie declaraţia int *a;. Alocarea a=new int; este echivalentă
cu alocarea a=new int[1];, adică dacă nu este vector putem considera
că alocăm memorie pentru un vector cu un singur element. Astfel,
aritmetica pointerilor prezentată în cele ce urmează devine mai
simplă.
87
IV.Introducere în limbajul C
4.5. Teste
Scrieţi ce se afişează în urma execuţiei următoarelor
instrucţiuni (liniile sunt independente), iar în cazul existenţei
unor erori, să se semnaleze erorile apărute în urma execuţiei şi
sursa acestora. Executaţi codul şi confruntaţi rezultatele afişate
cu cele scrise.
1. int a[2],b[7]={12,23,34,45,56,67,78};
a[0] = *(&b[2] + 1); a[1] = *b; printf(“a[0]=%d a[1]=%d”,a[0],
a[1]);
2. int a[3],c[4][3]={{10,23,34},{11,22,13},{31,42,33},{14,21,31}};
a[0] = 1 + *(&c[0][1] + 1); a[1] = **(&c[1] + 1); a[2]=**c;
printf(“a[0]=%d a[1]=%d a[2]=%d”,a[0],a[1],a[2]);
3. char *str = "ABCDEF"; str[1] = str[1]+1-'C'; str[3]=str[4]-
(str[3]+1); printf(“%s”,str);
4. int a,b[7]={11,13,15,17,19,21,23}; a = *(&b[6] - 6); printf(“a=
%d”,a);
5. int a,c[4][3]={{11,13,15},{21,23,25},{31,33,35},{41,43,45}};
a = *(c[3] - 1) + *(&c[0][1] - 1); printf(“a=%d”,a);
6. int a[2][3][2]={{{10,12},{13,15},{14,16}},{{50,52},{51,53},{54,
56}}},b; b = ***a + *(a[1][2] - 1) + **(a[0] + 1);
printf(“b=%d”, b);
7. char *str="ABCDEFG"; str[3]='G'-!(str[3]-str[1]); str[4]=!str[3]
88
4.Tablouri şi pointeri. Aritmetica pointerilor.
; printf(“%s”,str);
8. int a,b[7]={11,13,15,17,19,21,23}; a = *(&b[7] - 4); printf(“a=
%d”,a);
9. int a,c[4][3]={{11,13,15},{21,23,25},{31,33,35},{41,43,45}};
a = *(&c[0][0] + 2); printf(“a=%d”,a);
10. int a[2][3][2]={{{10,12},{13,15},{14,16}},{{50,52},{51,53},
{54,56}}}, b; b=***(a+1)+*(a[1][0]+1);printf(“b=%d”,b);
11. int a,c[4][3]={{11,13,15},{21,23,25},{31,33,35},{41,43,45}};
a = **(&c[1] - 1) + *(&c[1][2] - 1); cout<<a;
12. int a[2][3][2]={{{10,12},{13,15},{14,16}},{{50,52},{51,53},
{54,56}}}, b; b=*(**a+1)+*(a[1][2]-1)-**a[0]; printf(“b=%d”,b);
13. char *str="ABCDEFG"; str[0]='D'-str[3]+str[1];str[4]=!str[4];
printf(“%s”,str);
14. int a[2][3][2]={{{10,12},{13,15},{14,16}},{{50,52},
{51,53},54,56}}},b; b = *(**(a + 1) + 1) + *a[1][2] - **a[1];
printf(“b=%d”,b);
15. int a,c[4][3]={{11,13,15},{21,23,25},{31,33,35},{41,43,45}};
a=*(&c[3][2]-2)+**(&c[1]+1);printf(“a=%d”,a);
16. int a[2][3][2]={{{10,12},{13,15},{14,16}},{{50,52},
{51,53},54,56}}},b; b = ***a + **(*a + 1); printf(“b=%d”,b);
89
IV.Introducere în limbajul C
90
5.Funcţii. Aria de vizibilitate a variabilelor
91
IV.Introducere în limbajul C
92
6.Transferul parametrilor în cadrul funcţiilor
93
IV.Introducere în limbajul C
/*Ex.6.3(1)://transfer
/*Ex.6.3(1)://transfer prin prin referinţă
referinţă */
*/ #include
#include <iostream.h>
<iostream.h>
int
int f3(int &a, int &b) {a++; b -= 5; return aa ++ b;
f3(int &a, int &b) {a++; b -= 5; return b; }}
void
void main()
main()
{{ int
int x,y,z;
x,y,z; printf("x=\n");
printf("x=\n"); scanf(“%d”
scanf(“%d” ,&x);
,&x); //ex:3
//ex:3
printf("y=\n");
printf("y=\n"); scanf(“%d”,&y);
scanf(“%d”,&y); //ex:4
//ex:4
zz == f3(x,y);
f3(x,y); printf("z=%d\n",z);
printf("z=%d\n",z); //ex:z=3
//ex:z=3
printf("Dupa
printf("Dupa iesire
iesire din
din f1:x=%d";y=%d,x,y);
f1:x=%d";y=%d,x,y); //ex:x=4;y=-1
//ex:x=4;y=-1
}}
Comparând cele trei moduri de transmitere a parametrilor
către o funcţie, se poate observa:
● La apelul prin valoare, transferul datelor este unidirecţional,
adică valorile se transferă numai de la funcţia apelantă către
cea apelată;
● La apelurile prin adresă şi referinţă, transferul datelor este
bidirecţional, deoarece o modificare a parametrilor funcţiei
determină modificarea parametrilor efectivi (au nume diferite,
dar referă aceleaşi locaţii de memorie);
● La transmiterea parametrilor prin valoare, ca parametri efec-
tivi pot apărea expresii sau nume de variabile;
● La transmiterea parametrilor prin referinţă, ca parametri efec-
tivi nu pot apărea expresii, ci doar nume de variabile;
● La transmiterea parametrilor prin pointeri, ca parametri efec-
tivi pot apărea expresii de pointeri.
În următorul exemplu avem transferul simultan prin cele trei
moduri.
În cazul în care funcţia trebuie să întoarcă mai multe
valori, iar acestea nu pot fi grupate sub o variabilă de tip
pointer (tablouri sau structuri), se poate utiliza transferul prin
referinţă.
/*Ex.6.3(2):Transfer
/*Ex.6.3(2):Transfer mixt mixt */*/ #include
#include <stdio.h>
<stdio.h>
#include
#include <malloc.h>
<malloc.h>
short
short f1(short
f1(short a, a, short
short *b,*b, short
short &c,
&c, short
short d[][2],
d[][2], short
short **e)
**e)
{{ d[0][0]++;
d[0][0]++; d[1][1]++;
d[1][1]++; e[0][0]++;
e[0][0]++; e[1][1]++;
e[1][1]++; //a++;
//a++; (*b)++;
(*b)++; c++;
c++;
return
return aa ++ (*b)
(*b) ++ c;}
c;}
int
int main()
main()
{short
{short x[3][2]
x[3][2] == {{10,20},{30,40},{50,60}},
{{10,20},{30,40},{50,60}}, r, r, **y;
**y;
yy == (short**)
(short**) malloc(
malloc( 33 ** sizeof(short*)
sizeof(short*) ); );
for(int
for(int ii == 0;i
0;i << 3;i++)
3;i++) y[i]=(short*)
y[i]=(short*) malloc(
malloc( 22 ** sizeof(short)
sizeof(short) ); );
for(int
for(int ii == 0;0; ii << 3;
3; i++
i++ ))
for(
for( int
int jj == 0;
0; jj << 2;
2; j++
j++ ))
y[i][j]
y[i][j] == x[i][j];
x[i][j]; //cele
//cele 22 tablouri(x,y)
tablouri(x,y) au au aceleasi
aceleasi valori
valori
rr == f1(
f1( x[0][0],
x[0][0], &x[0][0],
&x[0][0], x[0][0],
x[0][0], x,x, yy );
);
printf(
printf("r=%d
"r=%d x[0][0]=%d
x[0][0]=%d x[1][1]=%d x[2][1]=%d\n"",r,x[0][0],x[1][1],x[2][1])
x[1][1]=%d x[2][1]=%d\n ,r,x[0][0],x[1][1],x[2][1]);;
printf(
printf("y[0][0]=%d
"y[0][0]=%d y[1][1]=%d
y[1][1]=%d y[2][1]=%d\n",
y[2][1]=%d\n", y[0][0],
y[0][0], y[1][1], y[2][1]);;
y[1][1], y[2][1])
return
return 0;}
0;}
94
6.Transferul parametrilor în cadrul funcţiilor
95
IV.Introducere în limbajul C
96
7.Structuri de date. Liste
7.3. Liste
Lista este o colecţie de elemente (celule) înlănţuite ce
formează o structură dinamică, situată în memoria dinamică, în care
toate elementele sunt de acelaşi tip; numărul de elemente este
variabil, chiar nul (listă vidă, pointează la NULL – adică adresa
primei celule din listă este NULL, adică nu există).
Altfel spus, lista este o secvenţă de zero sau mai multe
elemente, numite noduri, toate fiind de acelaşi tip. Spre deo-
sebire, tabloul este o structură statică, situată în memoria
dinamică.
Un nod al listei apare ca o structură recursivă, având o
componentă de tip pointer la structura, reprezentând legătura
(înlănţuirea) spre nodul următor. Fiecare element (celulă/nod) din
cadrul listei înlănţuite are o structură de tipul:
→→ Informaţie
Informaţie utilă;
utilă;
→→ Informaţie
Informaţie de
de înlănţuire
înlănţuire către
către elementul
elementul (celula)
(celula) următor;
următor;
//pentru
//pentru listele
listele dublu
dublu înlănţuite
înlănţuite
→→ Informaţie
Informaţie de
de înlănţuire
înlănţuire către
către elementul
elementul (celula)
(celula) anterior;
anterior;
Dacă în cadrul elementului/celulei/nodului se face referire
doar la elementul/celula/nodul următor atunci avem liste simplu
înlănţuite. Dacă se face şi referire la nodul anterior atunci avem
liste dublu înlănţuite.
Structura unui element/celulă/nod este:
ADRESA ADRESA
DATE
NODULUI NODULUI
NOD
ANTERIOR URMĂTOR
Figura IV-8: Structura unui nod
Înlănţuirea celulelor este prezentată în diagrama:
CAP
LISTĂ
Figura IV-9: Listă dublu înlănţuită
Pentru lucrul cu liste simplu înlănţuite este suficient să
se cunoască adresa capului listei, iar pentru listele dublu
înlănţuite se poate ajunge la orice nod dacă se cunoaşte adresa
unui singur nod din listă, oricare ar fi acesta.
7.3.1. Crearea unei liste dublu înlănţuite
Este necesară alocarea dinamică de memorie pentru orice nod
nou creat. Alocarea se poate face atât cu funcţia malloc, cât şi cu
operatorul new. Ştergerea elementelor din listă trebuie să asigure
şi dealocarea (eliberarea) memoriei corespunzătoare. Aceasta se
realizează cu funcţiia free, respectiv operatorul delete.
97
IV.Introducere în limbajul C
cap
cap == new
new NOD;
NOD; //crearea
//crearea capului
capului listei
listei sau
sau
//
// (cap=(NOD*)
(cap=(NOD*) malloc(sizeof(NOD));)
malloc(sizeof(NOD));)
memset(
memset( cap,
cap, 0,
0, sizeof(NOD)
sizeof(NOD) ); ); /*/* asigură
asigură iniţializarea
iniţializarea cu
cu val.0
val.0
respectiv
respectiv val.
val. NULL
NULL pentru
pentru pointeri
pointeri */
*/
//........................
//........................
//presupunem:
//presupunem: pp ultimul
ultimul nod
nod al
al listei
listei
p1
p1 == new
new NOD;
NOD; memset(cap,
memset(cap, 0, 0, sizeof(NOD)
sizeof(NOD) ); );
p->urm
p->urm == p1;
p1; p1->ant
p1->ant == p;
p; pp == p1;
p1;
Este obligatoriu ca la cele două capete cap->ante şi p->urm
să aibă valoarea NULL (p fiind ultimul nod din listă).
Dacă p->urm == cap şi cap->ante == p, atunci avem listă
circulară.
7.3.2. Parcurgerea unei liste
Presupunem că în acest caz variabila p este un pointer de
tip NOD folosit la parcurgerea listei.
//.......................
//.......................
. for(
for( pp == cap;
cap; p->urm;
p->urm; pp == p->urm
p->urm );
);
Bucla for execută o instrucţiune vidă, identificată prin
semicolon (;). Avansul se opreşte pe ultimul nod;
De exemplu, presupunem că avem o listă ale cărei noduri au
structura:
/*Ex.7.3.2(1)*/
/*Ex.7.3.2(1)*/
typedef
typedef struct
struct NOD2{
NOD2{ int
int id;
id; NOD2
NOD2 *urm,*ant;
*urm,*ant; }NOD2;
}NOD2;
Funcţia pentru crearea unei liste cu n noduri şi care
întoarce primul element al listei va fi:
/*Ex.7.3.2(2):
/*Ex.7.3.2(2): crearea
crearea unei
unei liste
liste cu
cu nn noduri,
noduri, întoarce
întoarce adresa
adresa capului
capului
listei*/
listei*/ NOD2*
NOD2* fc(int
fc(int n) n)
{NOD2
{NOD2 *p,
*p, *p1,
*p1, *caplista;
*caplista; pp == NULL;
NULL;
for(
for( int
int ii == 0;
0; ii << n;
n; i++
i++ ))
{{ p1
p1 == p;
p; pp == (NOD2*)
(NOD2*) malloc
malloc (( sizeof(NOD2)
sizeof(NOD2) ); );
if(
if( !p
!p )) return
return NULL;
NULL; //// eventual
eventual sese va
va realiza
realiza şi
şi dealocarea
dealocarea
memset(
memset( p,p, 0,0, sizeof(NOD2)
sizeof(NOD2) ); );
p->id
p->id == ii ++ 1000;
1000; // // ptr.
ptr. oo viitoare
viitoare identificare
identificare aa nodului
nodului
if(
if( !i
!i )) caplista
caplista == p; p;
else
else {{ p1->urm
p1->urm == p; p; p->ant
p->ant == p1;
p1; }}
}} return
return caplista;
caplista; }}
Dacă dorim să obţinem adresa ultimei celule/nod a/al listei,
utilizăm funcţia următoare:
/*Ex.7.3.2(3):parcurgerea
/*Ex.7.3.2(3):parcurgerea listeilistei cucu poziţionare
poziţionare pe
pe ultimul
ultimul nod
nod
(întoarce
(întoarce adresa
adresa ultimului
ultimului nod
nod din
din cadrul
cadrul listei)*/
listei)*/
NOD2*
NOD2* fp1(
fp1( NOD2
NOD2 *caplista
*caplista ))
{{ NOD2
NOD2 *p;
*p;
for(
for( pp == caplista;
caplista; p->urm;
p->urm; pp == p->urm
p->urm );//p->urm
);//p->urm sau
sau p->urm==NULL
p->urm==NULL
return
return p;}
p;}
98
7.Structuri de date. Liste
99
IV.Introducere în limbajul C
100
7.Structuri de date. Liste
/*Ex.8(1):
/*Ex.8(1): structura
structura arbore
arbore binar*/
binar*/
typedef struct NOD{
typedef struct NOD{
int
int id;
id; //identificator
//identificator nod
nod
NOD
NOD *st,*dr; //adresele
*st,*dr; //adresele nodurilor
nodurilor -- stânga,
stânga, dreapta
dreapta
}NOD;
}NOD;
Pentru început este creat un arbore cu şapte noduri. În
acest sens se alocă şapte adrese la structuri de tip NOD şi apoi se
realizează legăturile între aceste noduri.
/*Ex.8(2):creare
/*Ex.8(2):creare arbore
arbore binar*/
binar*/
NOD*
NOD* creare_arbore(void)
creare_arbore(void)
{NOD
{NOD *p[7];
*p[7]; //alocare
//alocare memorie
memorie
for(
for( int
int ii == 0;
0; ii << 7;
7; i++
i++ ))
{{ p[i]
p[i] == (NOD*)
(NOD*) malloc(
malloc( sizeof(NOD)
sizeof(NOD) );
);
memset(
memset( p[i],0,sizeof(NOD)
p[i],0,sizeof(NOD) ); ); p[i]->id
p[i]->id == ii ++ 1;}
1;}
p[0]->st=p[1];
p[0]->st=p[1]; p[0]->dr=p[2];
p[0]->dr=p[2]; p[2]->st=p[3];
p[2]->st=p[3];
p[2]->dr=p[4];
p[2]->dr=p[4]; p[3]->st=p[5];
p[3]->st=p[5]; p[3]->dr=p[6];
p[3]->dr=p[6];
return
return p[0];
p[0]; }//întoarce
}//întoarce rădăcina
rădăcina arborelui
arborelui
Funcţia de parcurgere a arborelui este o funcţie recursivă
şi se opreşte în momentul în care ajunge la nodurile frunză
(adresele următoare sunt NULL)
/*Ex.8(3):parcurge
/*Ex.8(3):parcurge arbore
arbore binar*/
binar*/
void
void parcurge(NOD
parcurge(NOD *p)*p) //preia
//preia rădăcina
rădăcina arborelui
arborelui curent
curent
{{ printf("-%d-", p->id);
printf("-%d-", p->id);
//if(p->st)
//if(p->st) parcurge(p->st);
parcurge(p->st); //dacă
//dacă începe
începe din
din stânga
stânga
if( p->dr ) parcurge( p->dr
if( p->dr ) parcurge( p->dr ); );
if(
if( p->st
p->st )) parcurge(
parcurge( p->st
p->st );
);
return;}
return;}
101
IV.Introducere în limbajul C
102
8.Funcţii recursive. Parcurgerea arborilor.
103
IV.Introducere în limbajul C
104
9.Funcţii uzuale din bibliotecile C. Lucrul cu fişiere text
105
IV.Introducere în limbajul C
106
10.Implementarea unui analizor sintactic pentru expresii matematice
107
IV.Introducere în limbajul C
/*Ex:10(6):
/*Ex:10(6): apelul
apelul în
în vederea
vederea testării
testării */
*/
#include
#include <stdio.h>
<stdio.h> /*\n*/#include
/*\n*/#include <stdlib.h>/*\n*/#include
<stdlib.h>/*\n*/#include <string.h>
<string.h>
#include
#include <math.h>
<math.h> /*\n*/
/*\n*/ #define
#define MAX
MAX 500
500
double
double analizor1(char*);
analizor1(char*);
/*
/* se
se copiază
copiază explicitările
explicitările pentru
pentru funcţiile:
funcţiile:
idnr(),cauta3(),cautap(),cautfnc(),analizor1()
idnr(),cauta3(),cautap(),cautfnc(),analizor1() */ */
int
int main()
main()
{double
{double x;x; char
char buf[100]="3+5*pow(0.5*4,6.5-4.5)-20*pow(2,2-1.5-1/2)";
buf[100]="3+5*pow(0.5*4,6.5-4.5)-20*pow(2,2-1.5-1/2)";
//scanf("%s",buf);
//scanf("%s",buf);
if((x=analizor1(buf))!=123456789L)
if((x=analizor1(buf))!=123456789L) printf("ŞIR:%s
printf("ŞIR:%s ---
--- D:%f\n",buf,x);
D:%f\n",buf,x);
else printf("Expresie ERONATA!");
else printf("Expresie ERONATA!");
return
return 0;}
0;}
Notă: Analizorul poate fi îmbunătăţit prin eliminarea altor excep-
ţii sau prin adăugarea de noi funcţii sau operatori.
108
V.Programarea orientată pe obiecte Limbajul C++
109
V.Programarea orientată pe obiecte Limbajul C++
2. Constructori şi destructori
2.1. Constructori
Constructorul este o funcţie care are acelaşi nume cu al clasei
(inclusiv case sensitive) – specific C++;
Constructorul se apelează automat la crearea fiecărui obiect al
clasei – creare de tip static, automatic sau dinamic;
O clasă poate avea mai mulţi constructuri, ei se deosebesc prin
numărul şi tipul argumentelor;
110
2.Constructori şi destructori
111
V.Programarea orientată pe obiecte Limbajul C++
112
2.Constructori şi destructori
113
V.Programarea orientată pe obiecte Limbajul C++
int a;
A() { a = 15; strcpy(nob,"N/A"); afis("A-Constr."); }
A(int a1) { a = a1; strcpy(nob,"N/A"); afis("A-Constr."); }
~A() { afis("A-Destr."); }
virtual void print() = 0;
virtual void afis(char* clasa)
{ cout<<"CLASA:"<<clasa<<" Variabila:"<<nob<<endl; }
};
class B : protected virtual A
{protected:
int b;
public:
B(int a1) : A(a1) { b = 0; afis("B-Constr_0"); }
B(char *nob1,int b1):A()
{ b = b1; strcpy(nob,nob1); afis("B-Constr_2");}
~B() { afis("B-Destructor"); }
void print() {cout<<"B::a:"<<a<<endl;}
};
class C : public virtual A
{ int c;
public:
C() : A() { c = 0; afis("C-Constr_0"); }
C(char *nob1, int c1) : A()
{ strcpy(nob, nob1); afis("C-Constr_2"); }
~C() { afis("C-Destructor"); }
};
class D : public B, private C
{ int d; public:
D() : B(1), C() { afis("D-Constr_0"); }
D(char *nob1 ,int d1) : B(d1-4), C()
{ strcpy(A::nob,nob1); afis("D-Constr_2"); }
~D() { afis("D-Destructor"); }
};
int main()
{ D y("y",5);/* verificare posibilitate asignari*/ return 0;}
114
2.Constructori şi destructori
class B2 : protected A1
{int x; char nvar[30]; protected:int yb; public:int t2;
B2() : A1() { strcpy(nvar,"N/A"); x = 0; yb = 0; afis("CONSTR_0"); }
B2(char *nvar1) : A1(nvar1,2,5)
{ strcpy(nvar,nvar1); x = 0; yb = 0; afis("CONSTR_1"); }
B2(char *nvar1,int x1,int yb1):A1(nvar1)
{ strcpy(nvar,nvar1); x = x1; yb = yb1; afis("CONSTR_2"); }
~B2() {afis("DESTRUCTOR");}
void afis(char *sir);
};
115
V.Programarea orientată pe obiecte Limbajul C++
116
3.Modificatori şi specificatori de acces. Exemple
/*Ex.
/*Ex. 3.2(1.2):definirea
3.2(1.2):definirea clasei
clasei B1*/
B1*/ class
class B1
B1 :: public
public AA
{{ short
short bx1;
bx1; protected:
protected: short
short by1;
by1; public:
public: short
short bz1;
bz1;
B1(
B1( short
short bx1_,
bx1_, short
short by1_,
by1_, short
short bz1_,
bz1_, short
short a1_,
a1_, short
short a2_,
a2_, short
short
a3_
a3_ )) :: A(
A( a1_,
a1_, a2_,
a2_, a3_)
a3_) {{ bx1
bx1 == bx1_;
bx1_; by1
by1 == by1_;
by1_; bz1
bz1 == bz1_;
bz1_; }}
short
short sum()
sum() {{ return
return a2a2 ++ a3;
a3; }} };
};
Prin modificatorul de acces public, tot ce este public sau
protected în clasa A va rămâne la fel şi în clasele derivate, iar
datele de tip private din A nu sunt accesibile şi în clasele
derivate.
/*Ex.
/*Ex. 3.2(1.3):definire
3.2(1.3):definire clasăclasă B2*/
B2*/
class
class B2:
B2: protected
protected AA {short
{short bx1;protected:short
bx1;protected:short by1;public:short
by1;public:short bz1;bz1;
B2(
B2( short
short bx1_,
bx1_, short
short by1_,
by1_, short
short bz1_,
bz1_, short
short a1_,
a1_, short
short a2_,
a2_, short
short
a3_
a3_ )) :: A(
A( a1_,
a1_, a2_,
a2_, a3_)
a3_) {{ bx1
bx1 == bx1_;
bx1_; by1
by1 == by1_;
by1_; bz1
bz1 == bz1_;
bz1_; }}
short
short sum()
sum() {{ return
return a2a2 ++ a3;
a3; }} };
};
Prin utilizarea modificatorului de acces protected, tot ce
este de tip public sau protected în clasa A devine de tip
protected în clasa derivată B2.
/*Ex.
/*Ex. 3.2(1.4):definire
3.2(1.4):definire clasăclasă B3*/
B3*/
class
class B3:
B3: private
private AA {short
{short bx1;protected:short
bx1;protected:short by1;public:short
by1;public:short bz1;
bz1;
B3(
B3( short
short bx1_,
bx1_, short
short by1_,
by1_, short
short bz1_,
bz1_, short
short a1_,
a1_, short
short a2_,
a2_, short
short
a3_
a3_ )) :: A(
A( a1_,
a1_, a2_,
a2_, a3_
a3_ )) {{ bx1
bx1 == bx1_;
bx1_; by1
by1 == by1_;
by1_; bz1
bz1 == bz1_;
bz1_; }}
short
short sum()
sum() {{ return
return a2a2 ++ a3;
a3; }} };
};
În acest caz, când modificatorul de acces este de tip
private, tot ce este de tip public sau protected în clasa A devine
de tip private în clasa derivată B3.
/*Ex.
/*Ex. 3.2(1.5):definire
3.2(1.5):definire clasăclasă C1*/
C1*/
class
class C1C1 :: public
public B1
B1 {{
C1(
C1( short
short bx1_,short
bx1_,short by1_,short
by1_,short bz1_,short
bz1_,short a1_,short
a1_,short a2_,
a2_, short
short
a3_
a3_ )) :: B1(
B1( bx1_,
bx1_, by1_,
by1_, bz1_,
bz1_, a1_,
a1_, a2_,
a2_, a3_
a3_ )) {{ }}
short
short sum()
sum() {{ return
return a2 a2 ++ a3;
a3; }} };
};
În acest caz, variabilele a2 şi a3 sunt accesibile în cadrul
clasei C1.
/*Ex.
/*Ex. 3.2(1.6):definirea
3.2(1.6):definirea clasei
clasei C2*/
C2*/
class C2: public B2
class C2: public B2 { {
C2(short
C2(short bx1_,short
bx1_,short by1_,short
by1_,short bz1_,
bz1_, short
short a1_,short
a1_,short a2_,short
a2_,short a3_)
a3_) ::
B2(
B2( bx1_, by1_, bz1_, a1_, a2_, a3_) {}
bx1_, by1_, bz1_, a1_, a2_, a3_) {}
short
short sum()
sum() {{ return
return a2
a2 ++ a3;
a3; }} };
};
De asemenea variabilele a2 şi a3 sunt accesibile în cadrul
clasei C2.
/*Ex.
/*Ex. 3.2(1.7):definire
3.2(1.7):definire clasă
clasă C3*/
C3*/
class
class C3:
C3: public
public B3
B3 {{
C3(
C3( short
short bx1_,short
bx1_,short by1_,short
by1_,short bz1_,short
bz1_,short a1_,short
a1_,short a2_,short
a2_,short a3_)
a3_) ::
B3(
B3( bx1_,
bx1_, by1_,
by1_, bz1_,
bz1_, a1_,
a1_, a2_,
a2_, a3_
a3_ )) {}
{}
/*short
/*short sum(){return
sum(){return a2+a3;}//a2
a2+a3;}//a2 si
si a3
a3 sunt
sunt INACCESIBILE
INACCESIBILE inin C3
C3 !*/
!*/ };
};
Datorită modificatorului de acces al clasei B3 (private),
117
V.Programarea orientată pe obiecte Limbajul C++
118
4.Funcţii de tip friend şi de tip static
119
V.Programarea orientată pe obiecte Limbajul C++
120
4.Funcţii de tip friend şi de tip static
121
V.Programarea orientată pe obiecte Limbajul C++
/*Ex.
/*Ex. 5.4(1.2):definirea
5.4(1.2):definirea clasei
clasei BB */*/
class
class B:
B: public
public AA {{ protected:
protected: int
int y;
y; public:
public: B()
B() :: A(){
A(){ yy == 0;
0; }}
B(int
B(int x1,int
x1,int y1)
y1) :: A(x1){
A(x1){ yy == y1;}
y1;}
void
void afis()
afis() {{ cout<<"B:
cout<<"B: x="<<x<<"
x="<<x<<" y="<<y<<endl;
y="<<y<<endl; }} };};
/*Ex.
/*Ex. 5.4(1.3):definirea
5.4(1.3):definirea clasei
clasei CC */
*/
class
class C: public B { protected: int
C: public B { protected: int z;z; public:
public: C()
C() :: B(){
B(){ zz == 0;
0; }}
C(int
C(int x1,
x1, int
int y1,int
y1,int z1):B(x1,y1)
z1):B(x1,y1) {z=z1;}
{z=z1;}
void
void afis()
afis() {{ cout<<"C:
cout<<"C: x="<<x<<"
x="<<x<<" y="<<y<<"
y="<<y<<" z="<<z<<endl;
z="<<z<<endl; }} }; };
Dacă nu se specifică constructorul pentru clasa de bază, se
preia automat constructorul implicit.
În funcţia int main() se declară un vector cu adrese de
tipul clasei de bază.
122
5.Polimorfism, funcţii virtuale
/*Ex.
/*Ex. 5.4(1.4):implementare
5.4(1.4):implementare polimorfism
polimorfism */ */ #include
#include <iostream>
<iostream>
using
using namespace std;/*Se copiază pe linie nouă 5.4(1.1),(1.2),(1.3)*/
namespace std;/*Se copiază pe linie nouă 5.4(1.1),(1.2),(1.3)*/
int
int main()
main() {{ cout<<"Din
cout<<"Din A"<<endl;
A"<<endl; AA t(1);
t(1); t.afis();
t.afis();
cout<<"Din B"<<endl; B m(5,7); m.afis();
cout<<"Din B"<<endl; B m(5,7); m.afis();
cout<<"Din
cout<<"Din C"<<endl;
C"<<endl; CC s(1,2,3);
s(1,2,3); s.afis();
s.afis();
cout<<"Vector
cout<<"Vector cu 5 adrese de
cu 5 adrese de tipul
tipul A"<<endl;
A"<<endl;
A*
A* w[5];
w[5]; cout<<"B()";
cout<<"B()"; w[0]
w[0] == new
new B();
B(); //(idem
//(idem w[1],w[3],w[4])
w[1],w[3],w[4])
cout<<"B(10,11)
cout<<"B(10,11) ";w[1]=new B(10,11); cout<<"A(30) ";w[2]
";w[1]=new B(10,11); cout<<"A(30) ";w[2] == new
new A(30);
A(30);
cout<<"C()
cout<<"C() ";w[3]=new
";w[3]=new C();cout<<"C(21,22,23)\n";w[4]=new
C();cout<<"C(21,22,23)\n";w[4]=new C(21,22,23);
C(21,22,23);
for(int
for(int i=0;
i=0; i<5;
i<5; i++)
i++) {{ cout<<"
cout<<" i:"<<i<<"--";
i:"<<i<<"--"; w[i]->afis();
w[i]->afis(); }}
return
return 0;
0; }}
La adresa unui obiect de tipul clasei de bază a fost pusă o
adresă a unui obiect de tipul unei clase derivate. Pentru w[0] şi
w[1] apelează funcţia void afis() din cadrul clasei B, pentru w[2]
apelează funcţia void afis() din cadrul clasei A, iar pentru w[3]
şi w[4] apelează funcţia void afis() din cadrul clasei C.
Pentru controalele dintr-o interfaţă grafică, considerăm o
clasă de bază generică TControl, din care sunt derivate clase
generice precum: TEDit, TComboBox, TRadioButtons, TLabel etc.
Fiecare din aceste clase are o metodă/funcţie specifică pentru
desenarea fundalului. Pentru a schimba rapid culoarea de fond, se
defineşte un vector w[] cu adrese la tip TControl. Adresa fiecărui
control se copiază în acest vector, apoi se apelează într-o buclă o
funcţie generică de forma void w[i]―>afisare_fundal(), ce va avea
ca efect apelul fiecărei funcţii specifice (ex.: pentru un obiect
de tip TRadioButtons, se apelează funcţia de afişare fundal speci-
fică clasei TRadioButtons).
5.4.2. Implementare polimorfism pentru afişarea datei calendaristice
Un alt exemplu, permite afişarea datei calendaristice în
funcţie de setările pentru ţară. Clasa de bază permite afişarea
datei calendaristice în formatul general, specific bazelor de date
an-lună-zi.
/*
/* Ex.
Ex. 5.4(2.1):definirea
5.4(2.1):definirea clasei
clasei de
de bază
bază DataC
DataC */
*/
class
class DataC { protected: unsigned short zi, luna,
DataC { protected: unsigned short zi, luna, an;
an; public:
public:
DataC(
DataC( unsigned
unsigned short
short an1,
an1, unsigned
unsigned short
short luna1,
luna1, unsigned
unsigned short
short zi1)
zi1)
{{ an = an1; zi = zi1; luna = luna1; } virtual void
an = an1; zi = zi1; luna = luna1; } virtual void afis() afis()
{cout<<"Format
{cout<<"Format general:"<<an<<"-"<<luna<<"-"<<zi<<endl;}};
general:"<<an<<"-"<<luna<<"-"<<zi<<endl;}};
Clasa derivată pentru reprezentarea datei calendaristice în
format românesc:
/*Ex.
/*Ex. 5.4(2.2):definirea
5.4(2.2):definirea clasei
clasei DataCro*/
DataCro*/
class
class DataCro:
DataCro: public
public DataC
DataC {{ public:
public:
DataCro(
DataCro( unsigned
unsigned short
short an1,
an1, unsigned
unsigned short
short luna1,
luna1, unsigned
unsigned short
short
zi1
zi1 )) :: DataC(
DataC( an1,
an1, luna1,
luna1, zi1
zi1 )) {}
{}
void
void afis()
afis() {{ cout<<"Format
cout<<"Format ro:"<<zi<<"."<<luna<<"."<<an<<endl;
ro:"<<zi<<"."<<luna<<"."<<an<<endl; }} }; };
Clasa derivată pentru reprezentarea datei calendaristice în
123
V.Programarea orientată pe obiecte Limbajul C++
format englez:
/*Ex.
/*Ex. 5.4(2.3):definirea
5.4(2.3):definirea clasei
clasei DataCen*/
DataCen*/
class
class DataCen:
DataCen: public
public DataC
DataC {{ public:
public:
DataCen(
DataCen( unsigned
unsigned short
short an1,
an1, unsigned
unsigned short
short luna1,
luna1, unsigned
unsigned short
short
zi1
zi1 )) :: DataC(
DataC( an1,
an1, luna1,
luna1, zi1
zi1 )) {{ }}
void
void afis()
afis() {{ cout<<"Format
cout<<"Format en:"<<luna<<"/"<<zi<<"/"<<an<<endl;
en:"<<luna<<"/"<<zi<<"/"<<an<<endl; }} }; };
Funcţia int main() ce implementează polimorfismul:
/*Ex.
/*Ex. 5.4(2.4):implementare
5.4(2.4):implementare polimorfism*/
polimorfism*/ #include
#include <iostream>
<iostream>
using
using namespace
namespace std;/*Se
std;/*Se copiază
copiază pepe linie
linie nouă
nouă 5.4(2.1),(2.2),(2.3)*/
5.4(2.1),(2.2),(2.3)*/
int
int main()
main() {{ DataC
DataC *x[3],
*x[3], *c;
*c; DataCro
DataCro *a;*a; DataCen
DataCen *b;
*b;
aa == new
new DataCro(2013,03,11);
DataCro(2013,03,11); bb == new
new DataCen(2011,5,25);
DataCen(2011,5,25);
cc == new
new DataC(2012,1,21);
DataC(2012,1,21); x[0]
x[0] == a;
a; x[1]
x[1] == b;
b; x[2]
x[2] == c;
c;
for(int
for(int i=0;i<3;i++)
i=0;i<3;i++) x[i]->afis();
x[i]->afis(); deletedelete a;delete
a;delete b;delete
b;delete c;
c;
return
return 0;0; }}
5.4.3. Implementare clase abstracte
Clasă abstractă:
/*Ex.
/*Ex. 5.4(3.1):implementare
5.4(3.1):implementare clasă
clasă abstractă*/
abstractă*/ class
class A{
A{ public:
public: int
int i;
i;
A(int
A(int i1){
i1){ ii == i1;
i1; }} A(){i=0;}
A(){i=0;} //sau
//sau unul
unul singur:A(int
singur:A(int i1=0)
i1=0) {i=i1;}
{i=i1;}
virtual
virtual void
void afis1()
afis1() == 0;
0; //functie
//functie virtuala
virtuala pura
pura ---
--- nu
nu are
are corp
corp
virtual
virtual void
void afis2()
afis2() {{ cout<<"A---i2:
cout<<"A---i2: "<<i<<endl;
"<<i<<endl; }} };
};
Clasă derivată:
/*
/* Ex.
Ex. 5.4(3.2):implementare
5.4(3.2):implementare clasă
clasă derivată
derivată */
*/
class
class B: public A { public: B(int i1) :: A(i1){
B: public A { public: B(int i1) A(i1){ }} B()
B() :: A(){
A(){ }}
void
void afis1()
afis1() {{ cout<<"B--i1:
cout<<"B--i1: "<<i<<endl;
"<<i<<endl; }} };
};
Funcţia int main() ce implementează clasa abstractă:
/*Ex.
/*Ex. 5.4(3.3):implementare
5.4(3.3):implementare clasăclasă abstractă*/
abstractă*/ #include
#include <iostream>
<iostream>
using
using namespace
namespace std;
std; /*Se
/*Se copiază
copiază pe
pe linie
linie nouă
nouă Ex
Ex 5.4(3.1),(3.2)*/
5.4(3.1),(3.2)*/
int
int main()
main() {{ /*A
/*A x(5);
x(5); dă
dă eroare
eroare */
*/ BB x(5),y;
x(5),y; x.afis1();
x.afis1(); x.afis2();
x.afis2();
y.afis1();
y.afis1(); y.afis2();
y.afis2(); return
return 0;}
0;}
Se observă faptul că este posibil apelul funcţiei void
afis2() (funcţie ce aparţine clasei A) din cadrul obiectelor x şi
y: x.afis2() şi y.afis2() .
6. Moştenirea multiplă
În cazul în care o clasă moşteneşte proprietăţile mai multor
clase, avem moştenire multiplă, o clasă derivă din mai multe clase
de bază. Sintaxa:
/*Sintaxă
/*Sintaxă moştenire
moştenire multiplă*/
multiplă*/
class
class nume_clasa_derivata :: modificator_acces
nume_clasa_derivata modificator_acces nume_clasă_baza_1
nume_clasă_baza_1
[<,
[<, modificator_acces
modificator_acces nume_clasă_baza_n
nume_clasă_baza_n >]
>]
Constructorul clasei derivate apelează constructorii ambelor
clase de bază în ordinea dată.
124
6.Moştenirea multiplă
125
V.Programarea orientată pe obiecte Limbajul C++
/*Ex.
/*Ex. 6.2.(1.2):implementare
6.2.(1.2):implementare clasăclasă derivată
derivată B*/
B*/
class
class B: public virtual A {protected: int
B: public virtual A {protected: int y;
y; public:
public: B():A(){
B():A(){ yy == 0;}
0;}
B(int
B(int x1,
x1, int
int y1)
y1) :: A(x1)
A(x1) {{ yy == y1;}
y1;}
virtual
virtual void
void afis()
afis() {{ cout<<"B:
cout<<"B: x="<<x<<"
x="<<x<<" y="<<y<<endl;}
y="<<y<<endl;} };};
Prin utilizarea în momentul derivării a opţiunii virtual A,
ne asigurăm că vom avea o singură copie a clasei A pentru obiectele
ce sunt rezultatul instanţierii unei clase ce utilizează moştenirea
multiplă.
/*Ex.
/*Ex. 6.2.(1.3):implementare
6.2.(1.3):implementare clasă clasă derivată
derivată CC */
*/
class
class C:
C: public
public virtual
virtual AA {protected:int
{protected:int z; z; public:C():
public:C(): A(){
A(){ zz == 0;
0; }}
C(int
C(int x1,
x1, int
int z1)
z1) :: A(x1)
A(x1) {{ zz == z1;}
z1;}
virtual
virtual void
void afis()
afis() {{ cout<<"C:
cout<<"C: x="<<x<<"
x="<<x<<" z="<<z<<endl;
z="<<z<<endl; }} };
};
/*Ex.
/*Ex. 6.2.(1.4):implementare
6.2.(1.4):implementare clasăclasă moştenire
moştenire multiplă
multiplă DD */
*/
class
class D: public B, public C {int t; public: D() :: B(),
D: public B, public C {int t; public: D() B(), C()
C() {{ tt == 0;
0; }}
D(int
D(int x1,
x1, int
int y1,
y1, int
int z1,
z1, int
int t1)
t1) :: B(x1,y1),
B(x1,y1), C(x1,z1)
C(x1,z1) {{ t=t1;
t=t1; }}
virtual
virtual void
void afis()
afis()
{cout<<"D:x="<<x<<"
{cout<<"D:x="<<x<<" y="<<y<<"
y="<<y<<" z="<<z<<"
z="<<z<<" t="<<t<<endl;}};
t="<<t<<endl;}};
Apelul clasei D:
/*Ex.
/*Ex. 6.1(1.5):Creare
6.1(1.5):Creare obiecte*/
obiecte*/ #include
#include <iostream>
<iostream>
using
using namespace std;/*Se copiază \n
namespace std;/*Se copiază \n Ex
Ex 6.1(1.1),(1.2),(1.3),(1.4)*/
6.1(1.1),(1.2),(1.3),(1.4)*/
int
int main()
main() {{ DD w1(2,3,4,5);
w1(2,3,4,5); w1.afis();
w1.afis(); return
return 0;}
0;}
Se observă faptul că valoarea 2 transmisă ca şi parametru
pentru membrul x din cadrul clasei A nu se afişează, în schimb se
afişează valoarea -100, corespunzătoare iniţializării membrului x
prin constructorul fără parametrii A().
7. Supraîncărcarea operatorilor
Supraîncărcarea operatorilor (overloading-ul) presupune re-
definirea operatorilor cu ajutorul funcţiei de tipul operator.
7.1. Restricţii privind supraîncărcarea operatorilor
➢ nu pot fi supraîncărcaţi decât operatorii existenţi;
➢ operatorii: " . "," .* "," :: " , " ?: " şi " sizeof " nu pot fi
supraîncărcaţi;
➢ operatorii binari vor fi supraîncărcaţi doar ca operatori binari;
➢ operatorii unari vor fi supraîncărcaţi doar ca operatori unari;
➢ se păstrează precedenţa operatorilor operator (nu există posibi-
litatea de a determina, de exemplu, ca "+" să fie prioritar faţă de
"/");
➢ nu este posibilă definirea unui operator care să ia ca parametri
exclusiv pointeri (exceptând operatorii: = & ,);
➢ nu se poate modifica numărul operanzilor preluaţi de un operator
126
7.Supraîncărcarea operatorilor
127
V.Programarea orientată pe obiecte Limbajul C++
128
7.Supraîncărcarea operatorilor
/*Ex.7.3.1(2.2):apelul
/*Ex.7.3.1(2.2):apelul operatorilor
operatorilor */ */ #include
#include <iostream>
<iostream>
using namespace std; /*copiere Ex7.3.1(2.1)*/
using namespace std; /*copiere Ex7.3.1(2.1)*/
int
int main()
main() {{ Loc2D
Loc2D s(5,6),
s(5,6), t(7,8);
t(7,8); ss +=+= t;
t;
t.afis("t","t:apel
t.afis("t","t:apel normal"); s.afis("s","s:apel normal");
normal"); s.afis("s","s:apel normal");
Loc2D
Loc2D m(5,6),
m(5,6), n(7,8);
n(7,8); mm == operator
operator +=(m,n);
+=(m,n);
n.afis("n",":apel
n.afis("n",":apel explicit");
explicit"); m.afis("m",":apel
m.afis("m",":apel explicit");
explicit");
Loc2D
Loc2D a(1,2),
a(1,2), b(3,4);
b(3,4); bb /=/= a;
a;
a.afis("a",":a-apel
a.afis("a",":a-apel normal");
normal"); b.afis("b",":b-apel
b.afis("b",":b-apel normal");
normal");
Loc2D
Loc2D c(1,2),
c(1,2), d(3,4);
d(3,4); dd == d.operator
d.operator /=(c);
/=(c);
c.afis("c",":c-apel
c.afis("c",":c-apel explicit");
explicit"); d.afis("d",":d-apel
d.afis("d",":d-apel explicit");
explicit");
return
return 0;}
0;}
În continuare este prezentat un exemplu cu operatorul de
asignare/atribuire.
/*Ex.7.3.1(3.1):apelul
/*Ex.7.3.1(3.1):apelul operatorilor
operatorilor */ */
class
class Loc2D{
Loc2D{ int
int x,y;
x,y; public:
public: Loc2D()
Loc2D() {{ x=0;
x=0; y=0;
y=0; }}
Loc2D(int
Loc2D(int x1,
x1, int
int y1)
y1) {{ x=x1;
x=x1; y=y1;
y=y1; }}
void
void afis(char*
afis(char* str1,
str1, char
char *str2)
*str2)
{{ cout<<str1<<".x="<<x<<"
cout<<str1<<".x="<<x<<" ;; "<<str1<<".y="<<y<<"
"<<str1<<".y="<<y<<" ;; "<<str2<<endl;
"<<str2<<endl; }}
Loc2D
Loc2D operator=(Loc2D
operator=(Loc2D t) t) {{ xx == t.x+10;
t.x+10; yy == t.y+10;
t.y+10; return
return *this;
*this; }} };
};
Nu este o simplă copiere a obiectelor, operatorul = este
supraîncărcat pentru a efectua alte operaţii. În lipsa
supraîncărcării operatorul de asignare va copia obiectul din
dreapta în partea stângă.
/*Ex.7.3.1(3.2):apelul
/*Ex.7.3.1(3.2):apelul operatorilor
operatorilor */*/ #include
#include <iostream>
<iostream>
using
using namespace
namespace std;/*copiere
std;/*copiere Ex7.3.1(3.1)*/
Ex7.3.1(3.1)*/ int
int main()
main() {Loc2D
{Loc2D a(4,5),
a(4,5),
b;
b; a.afis("a","initial");
a.afis("a","initial"); b.afis("b","initial");
b.afis("b","initial"); bb == a; a;
b.afis("b","dupa
b.afis("b","dupa atribuire
atribuire -- functie
functie membra
membra aa clasei");
clasei"); return
return 0;
0; }}
În continuare, este prezentat un alt exemplu ce supraîncarcă
operatori de egalitate şi diferit - fiecare întoarce o valoare de
adevăr:
/*Ex.7.3.1(4.1):declararea
/*Ex.7.3.1(4.1):declararea operatorilor
operatorilor == == şi
şi !=
!= */
*/
class
class Loc2D{
Loc2D{ int
int x,y;
x,y; public:Loc2D()
public:Loc2D() {x=0;y=0;}
{x=0;y=0;}
Loc2D(int
Loc2D(int x1,
x1, int
int y1)
y1) {x=x1;y=y1;}
{x=x1;y=y1;} void
void afis(char*
afis(char* str1,
str1, char
char *str2)
*str2)
{cout<<str1<<".x="<<x<<"
{cout<<str1<<".x="<<x<<" ;; "<<str1<<".y="<<y<<"
"<<str1<<".y="<<y<<" ;; "<<str2<<endl;}
"<<str2<<endl;}
bool
bool friend
friend operator
operator !=(Loc2D
!=(Loc2D a,Loc2D
a,Loc2D b);
b); bool
bool operator
operator ==(Loc2D
==(Loc2D b);};
b);};
bool
bool operator
operator !=(Loc2D
!=(Loc2D a,Loc2D
a,Loc2D b)
b) {return
{return ((a.x==b.x)&&(a.y==b.y));}
((a.x==b.x)&&(a.y==b.y));}
bool
bool Loc2D::operator
Loc2D::operator ==(Loc2D
==(Loc2D b)
b) {return
{return ((x==b.x)
((x==b.x) && && (y==b.y));}
(y==b.y));}
Operatorul == întoarce valoarea TRUE dacă cele două obiecte sunt
egale.
129
V.Programarea orientată pe obiecte Limbajul C++
/*Ex.7.3.1(4.2):apelul
/*Ex.7.3.1(4.2):apelul operatorilor
operatorilor */*/ #include
#include <iostream>
<iostream>
using namespace std;/*copiere Ex7.3.1(4.1)*/
using namespace std;/*copiere Ex7.3.1(4.1)*/
int
int main()
main() {Loc2D
{Loc2D s(6,8),t(6,8),m(6,9);
s(6,8),t(6,8),m(6,9);
if(s==t)
if(s==t) cout<<"1. ss ==
cout<<"1. == t"<<endl;
t"<<endl; else
else cout<<"1.
cout<<"1. ss !=
!= t"<<endl;
t"<<endl;
if(s==m)
if(s==m) cout<<"2.
cout<<"2. ss ==
== m"<<endl;
m"<<endl; else
else cout<<"2.
cout<<"2. ss !=
!= m"<<endl;
m"<<endl;
if(s!=t)
if(s!=t) cout<<"3.
cout<<"3. ss !=
!= t"<<endl;
t"<<endl; else
else cout<<"3.
cout<<"3. ss ==
== t"<<endl;
t"<<endl;
if(s!=m)
if(s!=m) cout<<"4.
cout<<"4. ss !=
!= m"<<endl;
m"<<endl; else
else cout<<"4.
cout<<"4. ss ==
== m"<<endl;
m"<<endl;
return
return 0;
0; }}
De asemenea, se poate supraîncărca operatorul de indexare.
Pentru aceasta considerăm o clasă VECT ce conţine un vector cu 5
elemente.
/*Ex.7.3.1(5.1):
/*Ex.7.3.1(5.1): operatorul
operatorul dede indexare
indexare */
*/
class
class VECT
VECT {double
{double a[5];public:VECT()
a[5];public:VECT() {{ for(int
for(int i=0;i<5;i++)
i=0;i<5;i++) a[i]=0;}
a[i]=0;}
VECT(double
VECT(double *a1)
*a1) {{ for(int
for(int i=0;i<5;i++)
i=0;i<5;i++) a[i]=a1[i];
a[i]=a1[i]; }}
~VECT(){
~VECT(){ }} double
double operator[](int
operator[](int i)i)
{if(i==3)
{if(i==3) return
return a[i]+1000;
a[i]+1000; if(i<2)
if(i<2) return
return a[i]-1000;
a[i]-1000; return
return a[i];}};
a[i];}};
Accesarea indexului 3 va întoarce un rezultat mai mare decât
valoarea iniţială cu 1000, iar pentru indecşii strict mai mici
decât 2 va întoarce un rezultat mai mic cu 1000:
/*Ex.7.3.1(5.2):apelul
/*Ex.7.3.1(5.2):apelul operatorului
operatorului de
de indexare
indexare */
*/ #include
#include <iostream>
<iostream>
using namespace std;/*copiere Ex7.3.1(5.1)*/
using namespace std;/*copiere Ex7.3.1(5.1)*/
int
int main(){double
main(){double q[5]={10,20,30,40,50};
q[5]={10,20,30,40,50}; VECT
VECT s(q),e[7];
s(q),e[7];
double s1,s2,s3; s1=s[3]; s2=s[4]; s3=s[1];
double s1,s2,s3; s1=s[3]; s2=s[4]; s3=s[1];
cout<<"s1="<<s1<<"
cout<<"s1="<<s1<<" ;; s2="<<s2<<";
s2="<<s2<<"; s3="<<s3<<endl;
s3="<<s3<<endl; e[4]=s;
e[4]=s;
cout<<"Din
cout<<"Din vector cu obiecte e[4][1]: "<<e[4][1];
vector cu obiecte e[4][1]: "<<e[4][1]; return
return 0;}
0;}
Instrucţiunea s3=s[1]; este echivalentă cu instrucţiunea
s3=s.operator[](1); Accesarea e[4][1] este echivalentă cu apelul
e[4].operator[](1) ( indexul 1 – al doilea index din cadrul celui
de-al cincilea obiect).
7.3.2. Clasă ce conţine o matrice
În continuare este prezentat un exemplu de supraîncărcare a
operatorilor pentru operaţiile cu matrice. În acest sens, declarăm
o clasă Matrice:
/*Ex.7(1.1):definirea
/*Ex.7(1.1):definirea clasei
clasei Matrice
Matrice ce
ce foloseşte
foloseşte supraîncărcarea
supraîncărcarea op*/
op*/
class
class Matrice{
Matrice{ double
double **a;
**a;
int
int m,n;
m,n; //
// dimensiunea
dimensiunea matricei:
matricei: nr.linii
nr.linii xx nr.coloane
nr.coloane
double**
double** aloca(int
aloca(int m2,
m2, int
int n2);
n2);
public:
public: Matrice(int
Matrice(int m1, m1, int
int n1);
n1); //preluare
//preluare dimensiune
dimensiune
Matrice(int
Matrice(int m1,m1, int
int n1,
n1, double
double **a1);
**a1); //preluare
//preluare dim.
dim. matrice+date
matrice+date
Matrice
Matrice operator%(Matrice
operator%(Matrice B); B);
friend
friend Matrice
Matrice operator^(Matrice
operator^(Matrice &A,Matrice
&A,Matrice &B);
&B);
void
void set(int
set(int i,int
i,int j,
j, double
double val);
val);
double
double get(int
get(int i,int
i,int j);
j); //preia
//preia valoarea
valoarea de
de la
la poziţia
poziţia (i,j);
(i,j);
void
void afis();
afis(); };};
130
7.Supraîncărcarea operatorilor
131
V.Programarea orientată pe obiecte Limbajul C++
/*Ex.7(1.5):constructor
/*Ex.7(1.5):constructor cu cu 33 parametri*/
parametri*/
Matrice::Matrice(int
Matrice::Matrice(int m1, int
m1, int n1,
n1, double
double **a1)
**a1)
{{ mm == m1;
m1; nn == n1;
n1; aa == aloca(m,n);
aloca(m,n);
for(
for( int
int i=0;
i=0; i<m;
i<m; i++)
i++)
for(int
for(int j=0;j<n;j++)
j=0;j<n;j++) a[i][j]=a1[i][j];
a[i][j]=a1[i][j];
}}
Sunt definite funcţiile ce asigură încapsularea datelor:
/*Ex.7(1.6):funcţii
/*Ex.7(1.6):funcţii ptr.încapsularea
ptr.încapsularea datelor*/
datelor*/
void
void Matrice::set(int
Matrice::set(int i,
i, int
int j,
j, double
double val)
val)
{{ a[i][j]
a[i][j] == val;
val; }}
double
double Matrice::get(int
Matrice::get(int i,i, int
int j)
j)
{{ return
return a[i][j];
a[i][j]; }}
Este definită funcţia operator% ce asigură supraîncărcarea
operaţiei de adunare a două matrice:
/*Ex.7(1.7):supraîncărcarea
/*Ex.7(1.7):supraîncărcarea operatorului
operatorului %% pentru
pentru adunare*/
adunare*/
Matrice
Matrice Matrice::operator%(Matrice
Matrice::operator%(Matrice B) B)
{{ Matrice
Matrice C(m,n);
C(m,n);
for(int
for(int i=0;i<m;i++)
i=0;i<m;i++)
for(int
for(int j=0;j<n;j++)
j=0;j<n;j++) C.a[i][j]=this->a[i][j]+B.a[i][j]
C.a[i][j]=this->a[i][j]+B.a[i][j]
//sau
//sau C.set(i,j,this->get(i,j)+B.get(i,j));
C.set(i,j,this->get(i,j)+B.get(i,j));
return
return C;
C; }}
Se presupune că matricea B este de dimensiune m x n.
/*Ex.7(1.8):supraîncărcarea
/*Ex.7(1.8):supraîncărcarea ptr. ptr. adunare
adunare –– funcţie
funcţie externă*/
externă*/
Matrice
Matrice operator^(Matrice
operator^(Matrice &A,&A, Matrice
Matrice &B)
&B)
{{ Matrice
Matrice C(
C( A.m,
A.m, A.n
A.n );
);
for(
for( int
int i=0;
i=0; i<A.m;
i<A.m; i++
i++ ))
for(
for( int
int j=0;
j=0; j<A.n;
j<A.n; j++
j++ )) C.set(i,
C.set(i, j,j, A.get(i,j)+B.get(i,j)
A.get(i,j)+B.get(i,j) );
);
return
return C;C; }}
Exemplul complet este:
/*Ex.7(1.9):supraîncărcarea
/*Ex.7(1.9):supraîncărcarea ptr. ptr. adunare
adunare –– funcţie
funcţie externă*/
externă*/
#include
#include <iostream>
<iostream>
using
using namespace
namespace std;
std;
/*Se
/*Se copiază:Ex7(1.1),(1.2),(1.3),(1.4),(1.5),(1.6),(1.7),(1.8)*/
copiază:Ex7(1.1),(1.2),(1.3),(1.4),(1.5),(1.6),(1.7),(1.8)*/
int
int main()
main() //ex.
//ex. de
de utilizare
utilizare ptr.
ptr. oo matrice
matrice 3x2
3x2
{{ double
double **c;
**c; cc == (double**)new
(double**)new double[3];
double[3];
for(int
for(int i=0;
i=0; i<3;
i<3; i++)
i++) c[i]
c[i] == new
new double[2];
double[2];
c[0][0]=5;c[0][1]=4;c[1][0]=25;c[1][1]=24;
c[0][0]=5;c[0][1]=4;c[1][0]=25;c[1][1]=24; c[2][0]=15;
c[2][0]=15; c[2][1]=14;
c[2][1]=14;
Matrice
Matrice X(3,2,c),
X(3,2,c), Y(3,2,c),
Y(3,2,c), Z(3,2);
Z(3,2); //Z=X+Y;
//Z=X+Y;
Z=X%Y;
Z=X%Y; cout<<"X"<<endl;
cout<<"X"<<endl; X.afis();
X.afis(); cout<<"Y"<<endl;
cout<<"Y"<<endl; Y.afis();
Y.afis();
cout<<"Z=X%Y"<<endl;
cout<<"Z=X%Y"<<endl; Z.afis();
Z.afis();
return
return 0;
0; }}
132
8.Fluxuri de intrare/ieşire
8. Fluxuri de intrare/ieşire
133
V.Programarea orientată pe obiecte Limbajul C++
134
8.Fluxuri de intrare/ieşire
135
V.Programarea orientată pe obiecte Limbajul C++
suma_double = DeterminaSuma<double>(s,t);
cout <<"max_int: "<< max_int <<" suma_int: "<<suma_int<< endl;
cout <<"max_long: "<< max_long <<" suma_long: "<<suma_long<< endl;
cout <<"max_double: "<< max_double <<" suma_double: "<<suma_double<<
endl;
return 0;}
136
10.Tratarea excepţiilor
137
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
138
1.Biblioteca wxWidgets şi dezvoltarea interfeţelor grafice în C++
mesaj – wxMessageBox.
/*Ex.2(1-1):*/
/*Ex.2(1-1):*/ class
class primaAplicatie
primaAplicatie :: public
public wxApp
wxApp
{public:virtual
{public:virtual bool
bool OnInit();
OnInit();
void
void apasaButon_1(wxCommandEvent&
apasaButon_1(wxCommandEvent& event){wxMessageBox("
event){wxMessageBox("Mesaj BUTON!");}
Mesaj BUTON! ");}
void
void apasaButon_2(wxCommandEvent&
apasaButon_2(wxCommandEvent& event)
event)
{{ wxFrame
wxFrame *fereastra_2
*fereastra_2 == new
new wxFrame(
wxFrame( NULL,ID_ANY,wxT("Titlu-2"),
NULL,ID_ANY,wxT("Titlu-2"),
wxDefaultPosition,
wxDefaultPosition, wxSize(150,200));
wxSize(150,200));
fereastra_2->SetBackgroundColour(
fereastra_2->SetBackgroundColour( wxColour(
wxColour( 118,
118, 235,
235, 158
158 )) );
);
wxStaticText
wxStaticText *L1
*L1 == new
new wxStaticText(
wxStaticText( fereastra_2,
fereastra_2, wxID_ANY,
wxID_ANY,
_("TESTE"));
_("TESTE")); fereastra_2->Show();}
fereastra_2->Show();} }; };
În cadrul funcţiei void apasaButon_2 (wxCommandEvent& event)
este instanţiată clasa wxFrame, ce realizează construcţia unei
ferestre. Primul patrametru pentru constructorul clasei wxFrame
este NULL, ceea ce semnifică că această fereastră nu este ataşată
unei alte ferestre. Parametrul ID_ANY semnifică faptul că această
fereastră nu are ataşat un identificator (raportat la dezvoltator).
Şirul “Titlu-2" reprezintă titlul ce va fi afişat în bara feres-
trei. Funcţia wxT(“...”) este utilizată pentru conversia şirului de
simboluri unicode într-un obiect de tip wxString (clasa wxString
gestionează şirurile de simboluri/caractere). Nu a fost stabilită o
anumită poziţie a ferestrei şi a fost pusă constanta
wxDefaultPosition. Dimensiunea ferestrei a fost stabilită la 150
pixeli pe orizontală şi 200 de pixeli pe verticală. În acest sens
dimensiunea ferestrei a fost preluată printr-un constructor al
clasei wxSize – wxSize(150,200).
Culoarea pentru fundalul ferestrei a fost stabilită prin
utilizarea celor trei canale RGB (RedGreenBlue), fiecare având
valori cuprinse între 0 şi 255, 0 semnificând lipsa culorii pe
canalul respectiv. Preluarea culorii pentru cele trei canale se
realizează prin constructorul wxColour(118, 235, 158). Funcţia
SetBackgroundColour(wxColour(118, 235, 158)) setează fundalul
ferestrei.
În cadrul metodei void apasaButon_2 (wxCommandEvent& event)
a fost instanţiată o clasă wxStaticText, ce construieşte un control
de tip text – etichetă. Primul parametru din constructorul clasei
identifică ferestra/obiectul căruia îi aparţine, în acest caz
fereastra_2. Al doilea parametru, având valoarea wxID_ANY, arată
faptul că nu există identificator atribuit acestui control.
Scrierea _("TESTE ANSI") este pentru caractere din setul
ASCII, iar wxT("TESTE diacritice:ĂÎŞŢÂ") este pentru codificarea
UNICODE.
Metoda OnInit() este explicitată în 2(2-2). Este instanţiată
clasa wxFrame pentru prima fereastră din cadrul aplicaţiei, apoi
este setată culoarea de fundal pentru fereastră.
În continuare sunt realizate două instanţe ale clasei
wxButton. Pentru fiecare din cei doi constructori primul parametru
139
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
140
1.Biblioteca wxWidgets şi dezvoltarea interfeţelor grafice în C++
/*Ex.2(2-2):*/bool
/*Ex.2(2-2):*/bool primaAplicatie::OnInit()
primaAplicatie::OnInit() {{ wxFrame
wxFrame *fereastra_1;
*fereastra_1;
fereastra_1 = new wxFrame( NULL, -1, wxT("Un titlu-1"),
fereastra_1 = new wxFrame( NULL, -1, wxT("Un titlu-1"),
wxDefaultPosition,
wxDefaultPosition, wxSize(
wxSize( 250,
250, 200)
200) );
);
fereastra_1->SetBackgroundColour(
fereastra_1->SetBackgroundColour( wxColour(
wxColour( 218,
218, 235,
235, 158
158 )) );
);
wxButton
wxButton *b1,*b2;
*b1,*b2; b1=new
b1=new wxButton(
wxButton( fereastra_1,11,wxT("Mesaj
fereastra_1,11,wxT("Mesaj nou!"));
nou!"));
b2
b2 == new
new wxButton(
wxButton( fereastra_1,
fereastra_1, 10,10, wxT("Fereastră
wxT("Fereastră nouă")
nouă") ););
wxBoxSizer
wxBoxSizer *bSizer_1
*bSizer_1 == new
new wxBoxSizer(
wxBoxSizer( wxHORIZONTAL
wxHORIZONTAL );
);
bSizer_1->Add(
bSizer_1->Add( b1, 0, wxALIGN_CENTER|wxALL, 55 );
b1, 0, wxALIGN_CENTER|wxALL, );
bSizer_1->Add(
bSizer_1->Add( b2,b2, 0,
0, wxALIGN_CENTER|wxALL,
wxALIGN_CENTER|wxALL, 55 ); );
fereastra_1->SetSizer(
fereastra_1->SetSizer( bSizer_1
bSizer_1 );); fereastra_1->Layout();
fereastra_1->Layout();
Connect(11,
Connect(11, wxEVT_COMMAND_BUTTON_CLICKED,
wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(primaAplicatie::apasaButon_1)
wxCommandEventHandler(primaAplicatie::apasaButon_1) ); );
Connect(10,
Connect(10, wxEVT_COMMAND_BUTTON_CLICKED,
wxEVT_COMMAND_BUTTON_CLICKED,
wxCommandEventHandler(primaAplicatie::apasaButon_2)
wxCommandEventHandler(primaAplicatie::apasaButon_2) ); );
fereastra_1->Show();
fereastra_1->Show();return
return true;}
true;}
iar exemplul 2(3-1) devine:
/*Ex.2(3-2):*/
/*Ex.2(3-2):*/ #include
#include <wx/wx.h>
<wx/wx.h>
/*Se
/*Se copiază
copiază Ex-2(1-1):*/
Ex-2(1-1):*/ IMPLEMENT_APP(primaAplicatie);
IMPLEMENT_APP(primaAplicatie);
/*Se
/*Se copiază
copiază Ex-2(2-1):*/
Ex-2(2-1):*/
Ultima implementare prezintă avantajul posibilităţii de afi-
şare completă a controalelor pe o varietate mare de rezoluţii de
afişare.
1.2. Gestiunea evenimentelor
În exemplul anterior evenimentul de click al mouse-ului pe
un buton era ataşat unei funcţii. Această legătură se poate realiza
prin funcţia Connect din cadrul metodei OnInit(). Primul parametru
al funcţiei este reprezentat de identificatorul (ales de către noi)
pentru controlul căruia îi aparţin evenimentele. Al doilea
parametru este reprezentat de o constantă ce reprezintă “codul
numeric” al evenimentului, în acest caz wxEVT_COMMAND_BUTTON_CLICKED.
Funcţia wxCommandEventHandler preia ca parametru metoda ce
prelucrează evenimentul (metoda ce trebuie să fie executată la
apariţia evenimentului). Este necesar ca funcţiile ce tratează
evenimentul să preia ca parametru o referinţă la o clasă de tip
eveniment (wxCommandEvent&). Din aceeaşi categoria fac parte şi
clasele wxKeyEvent şi wxMouseEvent, ce sunt specializate pe eveni-
mentele de la tastatură, respectiv de la mouse.
Exemplul anterior, în care evenimentele sunt la nivel de
aplicaţie, îl vom modifica astfel încât evenimentele să fie la
nivel de fereastră. În acest sens avem două variante, una cu
funcţii de conectare între evenimente şi metode la nivel de
constructor de fereastră şi de deconectare la nivelul
destructorului ferestrei şi o altă variantă (nu este singulară) cu
tabele de evenimente.
141
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
142
1.Biblioteca wxWidgets şi dezvoltarea interfeţelor grafice în C++
/*Ex.2(3):*/
/*Ex.2(3):*/ #include
#include <wx/wx.h>
<wx/wx.h>
class
class primaAplicatie
primaAplicatie :: public
public wxApp
wxApp {public:
{public: virtual
virtual bool
bool OnInit();};
OnInit();};
/*Se
/*Se copiază
copiază Ex-2(1-3),
Ex-2(1-3), Ex-2(2-3),
Ex-2(2-3), Ex-2(3-3),
Ex-2(3-3), Ex-2(4-3),:*/
Ex-2(4-3),:*/
IMPLEMENT_APP(primaAplicatie);
IMPLEMENT_APP(primaAplicatie);
bool
bool primaAplicatie::OnInit()
primaAplicatie::OnInit() {{ primaFereastra
primaFereastra *fereastra_1
*fereastra_1 == new
new
primaFereastra();
primaFereastra(); fereastra_1->Show();
fereastra_1->Show(); return
return true;
true; }}
/*Ex.2(2-4):*/
/*Ex.2(2-4):*/ classclass primaFereastra
primaFereastra :: public
public wxFrame
wxFrame
{{ public:wxButton
public:wxButton *b1,*b2;
*b1,*b2;
primaFereastra()
primaFereastra() :: wxFrame(
wxFrame( NULL,
NULL, -1,
-1, wxT("Un
wxT("Un titlu-1"),
titlu-1"),
wxDefaultPosition,
wxDefaultPosition, wxSize(
wxSize( 250,
250, 200)
200) ))
{b1 = new wxButton( this, 11, wxT("Mesaj
{b1 = new wxButton( this, 11, wxT("Mesaj nou!") );nou!") );
b2
b2 == new
new wxButton(
wxButton( this,
this, 10,
10, wxT("Fereastră
wxT("Fereastră nouă")
nouă") );
);
wxBoxSizer
wxBoxSizer *bSizer_1 = new wxBoxSizer( wxHORIZONTAL );
*bSizer_1 = new wxBoxSizer( wxHORIZONTAL );
bSizer_1->Add(
bSizer_1->Add( b1, b1, 0,
0, wxALIGN_CENTER|wxALL,5);
wxALIGN_CENTER|wxALL,5);
bSizer_1->Add(
bSizer_1->Add( b2, b2, 0,
0, wxALIGN_CENTER|wxALL,5);
wxALIGN_CENTER|wxALL,5);
this->SetSizer(
this->SetSizer( bSizer_1
bSizer_1 );this->Layout();
);this->Layout();
this->SetBackgroundColour
this->SetBackgroundColour (wxColour(218,235,158));}
(wxColour(218,235,158));}
void
void apasaButon_1(wxCommandEvent&
apasaButon_1(wxCommandEvent& event)event) {wxMessageBox("Apăsat!");}
{wxMessageBox("Apăsat!");}
void apasaButon_2(wxCommandEvent&
void apasaButon_2(wxCommandEvent& event) event)
{{ adouaFereastra
adouaFereastra *f*f == new
new adouaFereastra();
adouaFereastra(); f->Show();}
f->Show();}
wxDECLARE_EVENT_TABLE();
wxDECLARE_EVENT_TABLE(); };
};
Acelaşi exemplu este refăcut pentru a demonstra utilizarea
tabelelor de evenimente. Exemplul 2(1-4) este identic cu exemplul
2(1-3).
Tabela de evenimente:
/*Ex.2(3-4):*/
/*Ex.2(3-4):*/
wxBEGIN_EVENT_TABLE(primaFereastra,wxFrame)
wxBEGIN_EVENT_TABLE(primaFereastra,wxFrame)
EVT_BUTTON(11,
EVT_BUTTON(11, primaFereastra::apasaButon_1)
primaFereastra::apasaButon_1)
EVT_BUTTON(10,
EVT_BUTTON(10, primaFereastra::apasaButon_2)
primaFereastra::apasaButon_2)
wxEND_EVENT_TABLE()
wxEND_EVENT_TABLE()
/*Ex.2(4):*/
/*Ex.2(4):*/ #include
#include <wx/wx.h>
<wx/wx.h>
class
class primaAplicatie
primaAplicatie :: public
public wxApp
wxApp {public:
{public: virtual
virtual bool
bool OnInit();};
OnInit();};
/*Se copiază Ex-2(1-4), Ex-2(2-4), Ex-2(3-4):*/
/*Se copiază Ex-2(1-4), Ex-2(2-4), Ex-2(3-4):*/
IMPLEMENT_APP(primaAplicatie);
IMPLEMENT_APP(primaAplicatie);
bool
bool primaAplicatie::OnInit()
primaAplicatie::OnInit() {{ primaFereastra
primaFereastra *fereastra_1
*fereastra_1 == new
new
primaFereastra();
primaFereastra(); fereastra_1->Show();
fereastra_1->Show(); return
return true;}
true;}
Există tehnici de gestiune mai eficientă a evenimentelor
(ex. metoda Bind()), însă tehnicile expuse acoperă necesităţile
pentru construcţia unei interfeţe grafice simple.
1.3. Utilizarea claselor generate de template-uri
În zona open source generatoarele pentru interfeţe grafice
sunt limitate, însă consider că fără a utiliza generatoare pentru
interfaţă se pot realiza aplicaţii mult mai performante. Singurul
143
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
144
1.Biblioteca wxWidgets şi dezvoltarea interfeţelor grafice în C++
145
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
146
1.Biblioteca wxWidgets şi dezvoltarea interfeţelor grafice în C++
147
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
148
1.Biblioteca wxWidgets şi dezvoltarea interfeţelor grafice în C++
149
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
FereastraPrinc::~FereastraPrinc() {}
//---------------------------------------------------------------------
void FereastraPrinc::inchideFereastra(wxCloseEvent& evt)
{ timp->Stop(); evt.Skip(); }
BEGIN_EVENT_TABLE(FereastraPrinc, wxFrame)
EVT_CLOSE(FereastraPrinc::inchideFereastra)
END_EVENT_TABLE()
//---------------------------------------------------------------------
bool AplicatiaTEST1::OnInit()
{ fereastra_1=new FereastraPrinc(); fereastra_1->Show(); return true; }
//---------------------------------------------------------------------
BEGIN_EVENT_TABLE(PanouDesen, wxPanel)
EVT_PAINT(PanouDesen::evenimentDesenare)
EVT_KEY_DOWN(PanouDesen::evi_tasta)
EVT_LEFT_DOWN(PanouDesen::evi_guzgan_apasaBSt)
EVT_LEFT_UP(PanouDesen::evi_guzgan_ridicaBSt)
EVT_MOTION(PanouDesen::evi_guzgan_misca)
EVT_MOUSEWHEEL(PanouDesen::evi_guzgan_scroll)
END_EVENT_TABLE()
//---------------------------------------------------------------------
PanouDesen::PanouDesen(wxFrame* fereastra_parinte) :
wxPanel(fereastra_parinte)
{ x=20; y=40; y_speed=2; x_speed=2; R=20; retine=false; xm1=-1; ym1=-1;
culoare_cerc='r';
L1=new wxStaticText(this,wxID_ANY,_("TESTE"),wxDefaultPosition,
wxDefaultSize, 0); this->SetCursor(wxCURSOR_CROSS);}
//---------------------------------------------------------------------
void PanouDesen::evenimentDesenare(wxPaintEvent& evt)
{wxPaintDC dc(this); wxString sir_culoare;
dc.SetBackground(*wxWHITE_BRUSH); dc.Clear();//sterge fundal
if(culoare_cerc=='r') {dc.SetPen(wxPen(wxColour(255,0,0)));
sir_culoare="rosu";}
if(culoare_cerc=='g')
{dc.SetPen(wxPen(wxColour(0,255,0)));sir_culoare="verde";}
if(culoare_cerc=='b')
{dc.SetPen(wxPen(wxColour(0,0,255)));sir_culoare="albastru";}
dc.DrawRectangle(1,1,dc.GetSize().GetWidth()-1,dc.GetSize().GetHeight()-
1);
dc.DrawText(wxT("Un cerc ")+sir_culoare,x-5, y+R);
dc.DrawCircle(wxPoint(x,y),R);}
//---------------------------------------------------------------------
void PanouDesen::evi_tasta(wxKeyEvent& evt)
{ wxString ach;
switch (evt.m_keyCode)
{case WXK_RIGHT:x+=x_speed;this->Refresh();break;//ALT +SAGEATA
case WXK_LEFT: x -= x_speed; this->Refresh();break;
case WXK_DOWN: y += y_speed; this->Refresh();break;
case WXK_UP: y -= y_speed; this->Refresh();break;
} }
//---------------------------------------------------------------------
void PanouDesen::evi_guzgan_apasaBSt(wxMouseEvent& evt)
150
1.Biblioteca wxWidgets şi dezvoltarea interfeţelor grafice în C++
151
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
152
2.Interfaţarea client-server PostgreSQL în limbajul C/C++
153
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
/*Ex.2(1):*/
/*Ex.2(1):*/ PGresult
PGresult *rezultat1;
*rezultat1;
rezultat1
rezultat1 = PQexec(conexiune1,"SELECT cota,titlu,an_ap
= PQexec(conexiune1,"SELECT cota,titlu,an_ap FROM
FROM c8.inv;");
c8.inv;");
if(PQresultStatus(rezultat1)
if(PQresultStatus(rezultat1) !=!= PGRES_TUPLES_OK)
PGRES_TUPLES_OK)
{PQclear(rezultat1);PQfinish(conexiune1);printf("
{PQclear(rezultat1);PQfinish(conexiune1);printf("EROARE INTEROGARE!");}
EROARE INTEROGARE! ");}
În caz de eroare este necesară eliberarea memoriei de even-
tualele alocări de resurse efectuate până în acel punct. În acest
sens este utilizată funcţia PQclear(rezultat1) înainte de
închiderea conexiunii.
Se poate trimite o singură comandă SQL sau un bloc cu
comenzi SQL.
2.1.3. Extragerea datelor obţinute în urma interogării serverului
În cazul în care rezultatul constă într-un set de înre-
gistrări este necesar să ştim numărul de înregistrări returnate. În
acest sens utilizăm funcţia:
int
int PQntuples(const
PQntuples(const PGresult
PGresult *rezultat);
*rezultat);
Aceasta preia adresa variabilei cu rezultatul interogării şi
întoarce numărul de înregistrări rezultate în urma interogării şi
preluate în variabila de tip PGresult.
Notă: Pentru sistemele pe 32 de biţi, numărul de înregistrări nu
poate fi mai mare de 232 înregistrări, aceasta se datorează
reprezentării tipului “int” pe sistemele pe 32 biţi.
Pentru obţinerea numărului de câmpuri rezultate în urma
interogării avem o funcţie asemănătoare:
int
int PQntuples(const
PQntuples(const PGresult
PGresult *rezultat);
*rezultat);
Este posibilă obţinerea numelui pentru fiecare câmp în
parte. Funcţia preia adresa resursei şi numărul de ordine al
coloanei şi întoarce numele câmpului.
char
char *PQfname(const
*PQfname(const PGresult
PGresult *rezultat,
*rezultat, int
int număr_coloană);
număr_coloană);
De asemenea, se poate obţine tipul datei din cadrul fiecărui
câmp. Funcţia întoarce OID-ul corespondent tipului datei (acesta
este un număr unic şi există în sistemul de cataloage din cadrul
PostgreSQL – tabelul pg_type).
Oid
Oid PQftype(const
PQftype(const PGresult
PGresult *rezultat,
*rezultat, int
int număr_coloană);
număr_coloană);
Dimensiunea câmpurilor, în octeţi, poate fi obţinută prin
funcţia:
int
int PQfsize(const
PQfsize(const PGresult
PGresult *rezultat,
*rezultat, int
int număr_coloană);
număr_coloană);
Preluarea înregistrărilor se realizează prin preluare celulă
cu celulă din tabelul întors. Funcţia prin care se poate realiza
preluarea este: char
char *PQgetvalue(const
*PQgetvalue(const PGresult
PGresult *rezultat,
*rezultat,
int
int număr_rând,
număr_rând, int
int număr_coloană);
număr_coloană);
154
2.Interfaţarea client-server PostgreSQL în limbajul C/C++
155
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
156
2.Interfaţarea client-server PostgreSQL în limbajul C/C++
157
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
host,wxString port);
~IGPG();
//afişare în grid cu structură variabilă de coloane
void afisQ(wxGrid *GDx, wxString cdaSQL);
};
158
2.Interfaţarea client-server PostgreSQL în limbajul C/C++
//main.h
#include <wx/wx.h>
class MainApp : public wxApp { public: virtual bool OnInit(); };
DECLARE_APP(MainApp)
class MainFrame : public wxFrame
{ IGPG *x; protected: wxGrid* GD1; wxButton* B_AFIS; public:
MainFrame(wxWindow* parent, wxWindowID id = wxID_ANY, const wxString&
titlu = _(" Afişare în grid"), const wxPoint& poz = wxDefaultPosition,
const wxSize& dim = wxSize(500, 193), long stilfer = wxCLOSE_BOX|
wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL);
~MainFrame();
protected: virtual void afiseaza(wxCommandEvent& eveniment);
};
159
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
160
3.Generarea în limbajul C a rapoartelor în fişiere format PDF
161
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
162
3.Generarea în limbajul C a rapoartelor în fişiere format PDF
HPDF_Page_BeginText() HPDF_Page_BeginText()
HPDF_GMODE_PAGE_DESCRIPTION
(implicit)
Operaţii permise: Setări
pagină, font, culoare etc.
HPDF_GMODE_PATH_OBJECT
Operaţii permise; Funcţiile de mai
sus. Poziţionarea va fi relativă,
se raportează la ultima poziţie.
Figura VI-4: Diagrama de trecere dintr-un mod grafic în altul
Pentru a putea scrie, este necesară trecerea în modul
HPDF_GMODE_TEXT_OBJECT. În acest mod este asigurat avansul pe
orizontală conform dimensiunii fontului. Pentru a continua pe linia
următoare, se poate utiliza funcţia HPDF_Page_MoveToNextLine(). La
încheierea sesiunii de scriere se va ieşi din acest mod grafic.
163
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
#ifdef HPDF_DLL
void __stdcall
#else
void
#endif
//definirea funcţiei pentru afişarea erorilor
error_handler (HPDF_STATUS error_no, HPDF_STATUS detail_no,
void *user_data)
{ printf ("ERROR: error_no=%04X, detail_no=%u\n",
(HPDF_UINT)error_no, (HPDF_UINT)detail_no);
// A SE VERIFICA http://libharu.sourceforge.net/error_handling.html
throw std::exception ();
}
164
3.Generarea în limbajul C a rapoartelor în fişiere format PDF
165
VI.Dezvoltarea interfeţei client cu ajutorul bibliotecilor
HPDF_Page_LineTo(page1,390,370); HPDF_Page_LineTo(page1,390,410);
HPDF_Page_LineTo(page1,210,410); HPDF_Page_LineTo(page1,210,370);
HPDF_Page_Stroke(page1);
adnotare=HPDF_Page_CreateTextAnnot(page1,rect1,"COMENTARIU...",NULL);
HPDF_TextAnnot_SetIcon(adnotare, HPDF_ANNOT_ICON_COMMENT);
HPDF_TextAnnot_SetOpened(adnotare, HPDF_TRUE);
adnotare=HPDF_Page_CreateTextAnnot(page1,rect2,"Adnotare ...",
NULL); HPDF_TextAnnot_SetIcon(adnotare, HPDF_ANNOT_ICON_NOTE);
adnotare=HPDF_Page_CreateTextAnnot(page1, rect3,"Help ....",
NULL); HPDF_TextAnnot_SetIcon(adnotare, HPDF_ANNOT_ICON_HELP);
166
3.Generarea în limbajul C a rapoartelor în fişiere format PDF
167
VII.Dezvoltarea unor module pentru logistica stocurilor
168
1.Arhitectura aplicaţiei – LogX
EDITARE
(SQL/plpgSQL)
INTERFAŢĂ
UTILIZATOR DATE SERVER
(dezvoltată PostgreSQL
în C++)
RAPOARTE
(SQL/plpgSQL)
SERVER PostgreSQL
169
VII.Dezvoltarea unor module pentru logistica stocurilor
170
1.Arhitectura aplicaţiei – LogX
A B
OPERATOR
nom
SELECŢIE
1 2
FIŞIER CSV
br inx
OPERATOR VALIDARE
D 3 OPERATOR
C OPERATOR
REZERVARE 4
5 bp_
loc SELECŢIE stx
7 _bp
E G ACTUALIZARE STOC
6
ACTUALIZARE VALIDARE
STOC
trx outx
SELECŢIE
OPERATOR
F
Figura VII-4: Fluxul informaţional
Operaţiile de editare a stocurilor sunt descrise prin:
1 - introducerea de date manual sau prin import fişiere CSV;
2 - validarea BR, adăugarea înregistrării în inx şi ştergerea
înregistrărilor din tabelul br;
3 - adăugare automată a înregistrărilor şi în stoc (ID-ul din inx
se va copia şi în stx);
4 - operatorul selectează din stoc liniile ce vor fi livrate;
5 - rezervarea cantităţii (se scade cantitatea disponibilă);
6 - validare BP, inserare înregistrări în outx;
7 - actualizarea cantităţilor fizice în urma livrării;
A - introducerea de coduri noi direct de la operator;
B - actualizarea nomenclatorului pe baza intrărilor, modificări în
intrări pe baza acestuia;
C - introducerea de noi coduri de depozite şi amplasamente direct
de operator;
D - preluarea prin selecţie de noi coduri de depozite şi ampla-
samente;
E - selecţia depozitelor şi amplasamentelor din cadrul transfe-
rurilor;
F - selecţie din stoc în vederea transferurilor;
171
VII.Dezvoltarea unor module pentru logistica stocurilor
172
1.Arhitectura aplicaţiei – LogX
173
VII.Dezvoltarea unor module pentru logistica stocurilor
loc
#dep
#ampl
trx
#nrbt
#nrlin
dep_srs
br inx ampl_srs
#nrbr #id dep_dest
#idx nrbr ampl_dest bt_
datain datain id #nrbt
idcode idcode qtytr databt
po po dep_dest
status status ampl_dest
supplier supplier stx
serialno serialno #dep
depint depint _bt
#ampl #nrbt
amplinit amplinit
qty #id #id
qty
val val qtyfiz #dep_srs
qtydisp #ampl_srs
qtytr
nom
#idcode outx
refteh bp_ _bp #nrbl
refcom #nrbp #nrbp #id
descr databp #id #dep
utiliz destin #dep #ampl
data #ampl destin
ora qtyrez qtyliv
qtyconf dataout
Figura VII-5: Structura tabelelor
În tabelul următor sunt enumerate cheile externe:
Tabel Câmp tabelN câmp1:N Tabel Câmp tabelN câmp1:N
inx id stx id br depinit
trx id _bp dep
outx id trx dep_srs
_bt id trx dep_dest
_bp id tr_ dep_dest
nom idcode inx idcode _tr dep_srs
loc dep stx dep loc ampl stx ampl
inx depinit inx amplinit
174
1.Arhitectura aplicaţiei – LogX
175
VII.Dezvoltarea unor module pentru logistica stocurilor
CURRENT_DATE);
Adaugă o nouă linie în tabelul bt_ şi nu întoarce nimic;
● prelSelST_Tr(_nrbt_ int)
Preia datele din stocul selectat în BT-ul al cărui număr este
transmis prin argument. Nu întoarce nimic.
● tr_valid(_nrbt_ int)
Validează BT-ul al cărui număr este transmis prin argument.
Întoarce un mesaj de eroare sau 'OK'.
2.2. Dezvoltarea modulelor plpgSQL pentru rapoarte
Sunt patru tipuri de rapoarte: stoc curent, intrări, ieşiri,
transfer. Interogările sunt concepute într-o manieră flexibilă,
astfel pentru fiecare câmp există două bife, una în stânga şi una
în partea dreaptă. Prin bifa din stânga se stabileşte dacă acel
câmp va apare ca şi coloană în tabel. De exemplu, dacă nu este
bifat decât câmpul supplier, va aparea un număr de linii egal cu
numărul de furnizori, iar în coloana cantitate va fi trecută suma
cantităţilor grupate după furnizor. Bifa din dreapta semnifică
activarea sau dezactivarea filtrului pentru parametrul din stânga
acesteia. Rezultatul interogării va fi pus în tabelul TEMPORAR dat
de tipul interogării (q_tmp_in, q_tmp_st, q_tmp_out sau q_tmp_tr).
Toate cele patru interogări vor utiliza o singură funcţie ce
se bazează pe construcţia dinamică a interogărilor şi are forma:
q_x(_tipQ_ text,_nr_ smallint,_nume_ text[], _tip_ text[], _a_
boolean[], _s_ boolean[], _val1_ text[], _val2_ text[],_ord_ text)
unde:
● _tipQ_: tipul interogarii: IN-intrare, ST-stoc, STL-stoc selectat
în vederea livrării, OUT-iesire, TR-transfer;
● _nr_: numărul de câmpuri ce sunt în fereastra de selecţie;
● _nume_[]: vectorul cu numele câmpurilor/coloanelor;
● _tabel_[]: vector cu tabelele corespondente pentru fiecare
câmp/colană;
● _tip_[]: vectorul ce conţine tipul fiecărui câmp din fereastra de
selecţie. Acesta poate fi:
☑ C – şir de caractere – cautare exactă – case sensitive (ţine
cont de literă mare sau mică);
☑ A – şir de caractere – cautare aproximativa – case
insensitive (nu ţine cont de litera mare sau mică);
☑ D1 – data calendaristică: valoare exactă;
☑ D2 – data calendaristică: data va fi preluată ca interval;
☑ N1 – data de tip numeric: valoare exactă;
☑ N2 – data de tip numeric: interval.
● _a_[]: vectorul cu bifele pentru afişarea câmpurilor;
● _s_[]: vectorul cu bifele pentru selecţia/filtrarea câmpurilor;
● _ord_: câmpul după care se face ordonarea (un singur câmp).
176
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul
177
VII.Dezvoltarea unor module pentru logistica stocurilor
digrama următoare:
OBIECTELE GRAFICE DIN LEGENDĂ:
FEREASTRA iFACC wxDialog/wxFrame
wxBoxSizer(wxVERTICAL)
iFACC s1
wxBoxSizer(wxHORIZONTAL)
wxFlexGridSizer
wxPanel
OK wxButton
s2 s3 CB wxChoice/wxComboBox
OK b42 OK bAcces wxChoicebook
Edit wxTextCtrl
Text wxStaticText
31.12.00 wxDatePickerCtrl
178
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul
179
VII.Dezvoltarea unor module pentru logistica stocurilor
părinte).
Ierarhia obiectelor din cadrul ferestrei este redată în
diagrama următoare:
iFPB s1
Text t1 s2
s3 s3
Text t3
OK br2
br1
OK br4
Text t2 OK be2 OK be4 OK
OK br3
OK be1 OK be3
Figura VII-10: Obiecze grafice iFPB
180
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul
181
VII.Dezvoltarea unor module pentru logistica stocurilor
182
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul
iFEI s1
s2 pBR
s3
Text t4
CB cbBR
Text t5 GD1
s4 s5
31.12.00 eDataBR
OK bAddBR
Edit eSupplierBR
OK bDelBR OK bValidBR
OK bDelLin
OK bSavBR
bAddLin OK
OK bSelNom
Figura VII-13: Obiectele grafice din fereastra iFEI
Această fereastră asigură următoarele funcţii:
☑ constituirea unui nou BR;
☑ modificarea unui BR existent;
☑ ştergerea parţială sau completă a unui BR;
☑ validarea unui BR.
Răspunsul la evenimente este dat de următorul tabel:
183
VII.Dezvoltarea unor module pentru logistica stocurilor
184
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul
185
VII.Dezvoltarea unor module pentru logistica stocurilor
186
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul
iFBP s1
s2 pBP
s4
Text t1
GD1 s3
Text t2
OK bDelBP
OK bAddBP Edit eDestinBP
CB cbBP 31.12.00 eDataBP OK bSelST
OK bDelLin OK bValidBP
Figura VII-16: Obiectele grafice din fereastra iFBP
Răspunsul la evenimente este dat de următorul tabel:
<Controlul>
funcţie Evenimentul Tratare eveniment
ataşată
<cbBP> wxEVT_COMMAND ● actualizează afişarea pentru Destinatar din
iFEBP::afis_BP _COMBOBOX_SELE
baza de date;
CTED
● actualizează afişarea datei calendaristice
(selecţie
combobox) pentru BP;
● creează tabelul temporar temp_bp, ce
conţine datele din tabelul _bp,
corespunzătoare numărului BP selectat şi
187
VII.Dezvoltarea unor module pentru logistica stocurilor
<Controlul>
funcţie Evenimentul Tratare eveniment
ataşată
implicit a liniei corespondente din tabelul
părinte bp_. Pe lângă datele din tabelul _bp,
tabelul temporar conţine şi date din
nomenclatorul nom sau din tabelul cu intrări
inx;
● apelează funcţia de afişare a datelor în grid
(din clasa lxGrid)
● execută funcţia plpgSQL bp_nou;
wxEVT_COMMAND
<bAddBP> _BUTTON_CLICKED ● reîncarcă lista din combobox-ul cu numerele
iFEBP::addBP (apasă buton) BP afişate (apelează metodă din clasa
lxComboBox)
wxEVT_COMMAND ● şterge din tabelele bp_ şi _bp toate liniile
<bDelBP> _BUTTON_CLICKED
iFEBP::delBP corespondente cu cele afişate în grid
(apasă buton)
wxEVT_COMMAND ● anulează din tabelul _bp linia selectată;
<bDelLin> _BUTTON_CLICKED
iFEBP::delLin ● apelează funcţia afis_BP
(apasă buton)
188
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul
189
VII.Dezvoltarea unor module pentru logistica stocurilor
diagrama următoare:
OBIECTELE GRAFICE DIN FEREASTRA iFNOM
iFNOM s1
rOrd GD1 s2
pEdit
s2Nom OK bEdit
OK bSel
OK bRenNom
OK bAdd
OK bRenEdit
OK bDel
OK bSav
Figura VII-19: Obiectele din fereastra iFNOM
Fişierul header cu declaraţia clasei:
#define __fnom__
#include <wx/wx.h>
#include "lx.h"
class iFNOM : public wxDialog
{public:iFNOM(wxWindow* parent, wxArrayString* rez1, wxWindowID id =
wxID_ANY, const wxString& title = wxT("Nomenclator produse"), const
wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
long style = wxCLOSE_BOX|wxDEFAULT_DIALOG_STYLE|wxMAXIMIZE_BOX|
wxMINIMIZE_BOX|wxRESIZE_BORDER);
virtual ~iFNOM();
protected:wxRadioBox* rOrd; wxGrid* GD1; wxPanel* pEdit; wxButton* bAdd;
wxButton* bDel; wxButton* bSav; wxButton* bRenEdit; wxButton* bEdit;
wxButton* bSel; wxButton* bRenNom;
void afis_NOM();
virtual void ordoneaza(wxCommandEvent& event);
virtual void add_Lin(wxCommandEvent& event);
virtual void del_Lin(wxCommandEvent& event);
virtual void salveaza(wxCommandEvent& event);
virtual void ren_Edit(wxCommandEvent& event);
virtual void editare(wxCommandEvent& event);
virtual void selecteaza(wxCommandEvent& event);
virtual void ren_Nom(wxCommandEvent& event);
190
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul
191
VII.Dezvoltarea unor module pentru logistica stocurilor
192
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul
193
194
LEGENDĂ OBIECTELE GRAFICE DIN
:
wxDialog/wxFrame
FEREASTRA iFSELST
wxBoxSizer(wxVERTICAL) iFSTSEL s1
wxBoxSizer(wxHORIZONTAL)
wxFlexGridSizer s2 pSelBP
wxPanel GD1
OK wxButton
CB wxChoice/wComboBox s4 s17
s3 s5
wxChoicebook
x
Edit wxTextCtrl cblS PQtyPrep
Text t9 s35 p9
Text wxStaticText OK bQ GD2
31.12.00wxDatePickerCtrl s14
x
cblA s15
wxRadioBox
x CBP CB cbOrd
wxCheckListBox Text t12
Text t13 OK Rezerva
Text t8
OK bCopiaza
wxGrid Edit OK bBP
eQtyPrep
OK bDelLin
VII.Dezvoltarea unor module pentru logistica stocurilor
p1 p2 p3 p4 p6
p5 p7 p10
protected:
wxStaticText* t8; wxCheckListBox* cblA; wxStaticText* t9;
wxCheckListBox* cblS; wxChoicebook* CBP; wxPanel* p1; wxButton*
bNom; wxPanel* p2; wxStaticText* t1; wxTextCtrl* eSupplier; wxButton*
bRetFurnizor; wxPanel* p3;
wxDatePickerCtrl* eData1; wxStaticText* t2; wxDatePickerCtrl* eData2;
wxButton* bRetData; wxPanel* p4; wxStaticText* t3; wxComboBox* cbDep;
wxStaticText* t4; wxComboBox* cbAmpl; wxButton* bRetDepAmp; wxPanel*
p5; wxStaticText* t5; wxTextCtrl* ePO; wxButton* bRetPO; wxPanel* p6;
wxStaticText* t6; wxChoice* cbStatus; wxButton* bRetStatus; wxPanel* p7;
wxStaticText* t7; wxTextCtrl* eSerialNo; wxButton* bRetSerialNo;
wxPanel* p10; wxStaticText* t10; wxTextCtrl* eID; wxButton*
bRetID; wxStaticText* t13; wxChoice* cbOrd; wxButton* bCopiaza;
wxButton* bQ; wxGrid* GD1; wxPanel* pSelBP; wxPanel* P_QtyPrep;
wxStaticText* t12; wxTextCtrl* eQtyPrep; wxButton* bRezerva;
wxGrid* GD2; wxPanel* p9; wxButton* bDelLin; wxButton* bBP;
virtual void selNom(wxCommandEvent& event);//Selecţie NOMENCLATOR
virtual void retineFurnizor(wxCommandEvent& event);//selectează furnizor
virtual void retineData(wxCommandEvent& event);//selectează filtru data
calendaristică de intrare
virtual void selDep(wxCommandEvent& event);//Schimbă lista cu amplasamentele
în funcţie de depozitul selectat
virtual void retineDepAmp(wxCommandEvent& event);//selectează depozitul şi
amplasamentul curent
virtual void retinePO(wxCommandEvent& event);//selectează PO
virtual void retineID(wxCommandEvent& event);//selectează ID
virtual void retineSTATUS(wxCommandEvent& event);//selectează STATUS
virtual void retineSerialNo(wxCommandEvent& event);//selectează SerialNo
virtual void qST(wxCommandEvent& event);//FUNCŢIA DE INTEROGARE A STOCULUI
virtual void rezervaQtySelST(wxCommandEvent& event);//Rezervă item-uri
virtual void delLinSelST(wxCommandEvent& event);//Şterge linia selectată
virtual void transferBP(wxCommandEvent& event);//Închide fereastra de sel.
virtual void copiaza(wxCommandEvent& event);//Copiază din GRID în CLIPBOARD
virtual void afis_sel(); // AFIŞARE PANOU SELECŢIE --FILTRE
};
#endif //__fselst__
195
VII.Dezvoltarea unor module pentru logistica stocurilor
<Controlul>
funcţie ataşată
Evenimentul Tratare eveniment
196
3.Dezvoltarea în C++ a modulelor de interfaţare grafică cu utilizatorul
<Controlul>
funcţie ataşată
Evenimentul Tratare eveniment
197
VII.Dezvoltarea unor module pentru logistica stocurilor
198
4.Dezvoltarea interfeţei SQL/plpgSQL – controale grafice
199
VII.Dezvoltarea unor module pentru logistica stocurilor
200
4.Dezvoltarea interfeţei SQL/plpgSQL – controale grafice
201
VII.Dezvoltarea unor module pentru logistica stocurilor
202
4.Dezvoltarea interfeţei SQL/plpgSQL – controale grafice
203
VII.Dezvoltarea unor module pentru logistica stocurilor
Clasele de interfaţare LX
iFEI
schema: logx
tabele,
secvenţe
iFNOM
UTILIZATOR
Clasa
iFPB
schema: logx
funcţii plpgSQL iSELST
GRUPURI şi
UTILIZATORI
SERVER POSTGRESQL iFEBP
Figura VII-24: Instanţierea unor clase
În continuare este prezentat un tabel cu instanţierea clase-
lor.
clasa clase instanţiate Fişier
LogXApp iFACC; iFPB main.cpp
iFPB iFEI; iFNOM; iFSELST; iFEBP main.cpp
iFEI lxCtrl; lxComboBox; lxEditT; lxDPC; lxGrid; iFNOM fei.cpp
iFNOM lxCtrl; lxGrid fnom.cpp
iFEBP lxCtrl; lxEditT; lxComboBox; lxDPC; lxGrid; iFSELST febp.cpp
iFSELST lxCtrl; lxEditT; lxComboBox; lxDPC; lxGrid; iFNOM selst.cpp
204
5.Integrarea modulelor aplicaţiei LogX
RES_LX/lx_grid.cpp.
Server-ul de baze utilizat a fost PostgreSQL 9.2, iar
versiunea de CodeLite utilizată a fost 6.0 cu wxWidgets 3.01.
Pentru simplificarea construcţiei interfeţei, se poate utiliza
wxFormBuilder sau echivalent, însă acestea pot fi utilile doar
pentru interfeţele simple.
Notă: Dacă se utilizează platforma Windows, recomand ca numele
directoarelor/subdirectoarelor în care se instalează ColdeLite şi
mai ales wxWidgets să nu conţină semne de punctuaţie sau alte
caractere de acest tip.
În capitolul ANEXE se regăsec fişierele cu extensia cpp din
cadrul aplicaţiei şi codul SQL pentru construcţia structurii de pe
server-ul PostgreSQL.
205
ANEXE
ANEXE
1. Secvenţe din sintaxa SQL/postgreSQL simplificată
Sunt prezentate pe scurt câteva comenzi SQL frecvent
utilizate. Opţiunile pentru aceste comenzi sunt mult mai numeroase,
am prezentat doar câteva opţiuni, frecvent utilizate.
Parantezele drepte “[opţional]” cuprind opţiuni ale comenzii
SQL (parantezele drepte nu vor fi scrise). Simbolul “|” este
utilizat cu semnificaţia de SAU. Acoladele “{ }” semnifică
repetiţie. Simbolurile “a[, …]“ semnifică o listă de cu elemente de
tipul a separate prin virgulă.
☑ Comanda ALTER ROLE
Modifică parametrii pentru un utilizator sau grup
ALTER
ALTER ROLE
ROLE nume_rol
nume_rol [[ [[ WITH
WITH ]] opţiuni
opţiuni [[ ...
... ]] ]]
Opţiune Descriere
SUPERUSER | NOSUPERUSER Cu drept de superuser sau nu
CREATEDB | NOCREATEDB Poate sau nu să creeze baze de date
CREATEROLE | NOCREATEROLE Poate sau nu să creeze alţi utilizatori sau grupuri
LOGIN | NOLOGIN Poate sau nu să se conecteze (este user sau grup)
PASSWORD 'password' Schimbare parolă
VALID UNTIL 'timestamp' Momentul până la care este valabilă parola
206
1.Secvenţe din sintaxa SQL/postgreSQL simplificată
Opţiune Descriere
ADD COLUMN nume_câmp tip_dată Adaugă un câmp/coloană
DROP COLUMN [IF EXISTS] nume_câmp Şterge un câmp
ALTER COLUMN nume TYPE tip_dată Schimbarea tipului de dată (un câmp)
ALTER nume_câmp SET DEFAULT valoare Setare valoare implicită câmp
ENABLE | DISABLE TRIGGER Activează/Dezactivează trigger
Redenumeşte un tabel
ALTER
ALTER TABLE
TABLE [[ IF
IF EXISTS
EXISTS ]] nume_vechi
nume_vechi RENAME
RENAME TO
TO nume_nou
nume_nou
☑ Comanda COPY
Copiază datele dintr-un tabel într-un fişier format CSV.
COPY
COPY {nume_tabel[(
{nume_tabel[( nume_coloană
nume_coloană [, [, ...]
...] )]
)] || (rezultat_interogare
(rezultat_interogare )} )}
TO
TO {'nume_fişier'
{'nume_fişier' || STDOUT
STDOUT }} [[ [[ WITH
WITH ]] (( opţiune
opţiune [,
[, ...]
...] )) ]]
Opţiune Descriere
FORMAT nume_format Formatul poate fi: CSV, text sau binary
DELIMITER 'caracter_delimitator' Pentru CSV este virgula “,” (implicit)
NULL În lipsa datelor scrie NULL
(nerecomandat)
HEADER Prima linie din fişier este antetul
ENCODING Implicit este cel al bazei de date
207
ANEXE
[CONSTRAINT
[CONSTRAINT nume_restricţie]
nume_restricţie] {{ NOT
NOT NULL
NULL || NULL
NULL || CHECK
CHECK (( expresie
expresie )) ||
DEFAULT valoare_implicită | PRIMARY KEY}
DEFAULT valoare_implicită | PRIMARY KEY}
☑ Comanda DELETE
Şterge înregistrările dintr-un tabel. Atenţie: a nu fi confundată
cu comanda DROP, care şterge întreaga structură a obiectului (în
acest caz, tabelul)!
DELETE
DELETE FROM
FROM nume_tabel
nume_tabel [USING
[USING nume_tabele_legătură]
nume_tabele_legătură] [WHERE
[WHERE expresie]
expresie]
Dacă nu se specifică o condiţie sau dacă expresie este întotdeauna
adevărată, se vor şterge toate înregistrările din cadrul tabelului
☑ Comanda INSERT
Comanda INSERT este utilizată pentru popularea bazei de date.
INSERT
INSERT INTO
INTO nume_tabel
nume_tabel [[ (( nume_câmp
nume_câmp [,
[, ...]
...] )) ]]
{{ DEFAULT
DEFAULT VALUES
VALUES ||
VALUES
VALUES (( {{ valoare_expresie
valoare_expresie || DEFAULT
DEFAULT }} [,
[, ...]
...] )) [,
[, ...]
...] ||
interogare
interogare }}
Se pot adăuga valorile implicite sau o listă de valori (eventual
obţinute din evaluarea unor expresii) sau se poate adăuga
rezultatul unei interogări (query).
☑ Comanda SELECT
Este cea mai complexă comandă din SQL.
SELECT
SELECT [[ ALL
ALL || DISTINCT
DISTINCT [[ ON ON (( expresie_1
expresie_1 [, [, ...]
...] )) ]] ]]
** || expressie_1
expressie_1 [ [ AS ] denumire_nouă_câmp_rezultat ]] [,
[ [ AS ] denumire_nouă_câmp_rezultat [, ...]
...]
[[ FROM
FROM tabel_sau_interogare
tabel_sau_interogare
[[ NATURAL
NATURAL ]] join_type
join_type tabel_sau_interogare
tabel_sau_interogare
[[ ON
ON join_condiţie
join_condiţie || USING USING (( join_column
join_column [, [, ...]
...] )) ]] ]]
[[ WHERE expresie_2
WHERE expresie_2 ] ]
[[ GROUP
GROUP BY BY expresie_3
expresie_3 [, [, ...]
...] ]]
[[ HAVING
HAVING expresie_4 [, ...] ]]
expresie_4 [, ...]
[[ {{ UNION
UNION || INTERSECT
INTERSECT || EXCEPT EXCEPT }} [[ ALL
ALL || DISTINCT
DISTINCT ]] select
select ]]
[[ ORDER BY expresie_5 [ ASC | DESC
ORDER BY expresie_5 [ ASC | DESC ] [, ...] ] ] [, ...] ]
[[ LIMIT
LIMIT {{ count
count || ALLALL }} ]]
[[ OFFSET
OFFSET start [ ROW || ROWS
start [ ROW ROWS ]] ]]
Unele instrucţiuni, precum [NATURAL], sunt redundante (NATURAL JOIN
= JOIN)
208
1.Secvenţe din sintaxa SQL/postgreSQL simplificată
Opţiune Descriere
☑ Comanda UPDATE
Este comanda prin care sunt actualizate informaţiile existente în
tabele.
UPDATE
UPDATE nume_tabel
nume_tabel
SET
SET {{ nume_câmp
nume_câmp == {{ expresie_1
expresie_1 || DEFAULT
DEFAULT }} ||
(( nume_câmp
nume_câmp [, ...] ) = ( { expresie_1 || DEFAULT
[, ...] ) = ( { expresie_1 DEFAULT }}
[,
[, ...]
...] )) }} [,
[, ...]
...]
[[ FROM nume_tabele
FROM nume_tabele ] ] [ WHERE expresie_2
[ WHERE expresie_2 ] ]
Opţiune Descriere
nume_câmp Numele câmpurilor care se actualizează
expresie_1 Condiţia ce trebuie îndeplinită pentru actualizarea înregistrării
nume_tabele Dacă pentru actualizare sunt utilizate şi informaţii din alte tabele
expresie_2 Condiţie actualizare + Legătura între tabele
209
ANEXE
210
3.Operatori C/C++
3. Operatori C/C++
☑ A.Operatori unari
SIMBOLUL FORMA Operaţia realizată Exemplu
- -a negarea lui a -3
+ +a valoarea lui a 3
a++ Postincrementare: a=3++;
preia valoare, apoi creşte cu 1 a are val. 3
++
++a Preincrementare: mai întâi creşte a=++3;
cu 1, apoi preia valoarea a are val. 4
a-- Postdecrementare: a=3--;
preia valoarea, apoi scade cu 1 a are val. 3
--
--a Predecrementare: mai întâi scade a=--3;
cu 1, apoi preia valoarea a are val. 2
211
ANEXE
☑ G.Operatorii logici
SIMBOLUL FORMA Operaţia
&& a && b ŞI / AND
|| a || b SAU / OR
! !a NEGAT / NOT
(T – true, F – false)
x y x&&y x||y !x
F F F F T
F T F T T
T F F T F
T T T T
☑ H.Operatorul cast
SIMBOLUL FORMA Operaţia realizată
(tip) (tip)a a este convertit la tipul tip, operaţie de tip
cast
Precedenţa operatorilor:
1) ( … ), [ … ], , ::, .(referire membru);
2) operatori unari;
3) operatori multiplicativi;
4) acces la membri;
5) operator aditivi;
6) operatori de deplasare;
7) operatori relaţionali;
8) opertori logici la nivel de bit;
9) operatori logici;
10) operatorul condiţional;
11) operatori de asignare;
12) operatorul virgulă;
Citirea expresiilor se face de la dreapta spre stânga.
212
4.Codul sursă SQL pentru aplicaţia LogX
213
ANEXE
214
4.Codul sursă SQL pentru aplicaţia LogX
215
ANEXE
216
4.Codul sursă SQL pentru aplicaţia LogX
f boolean;
begin
--verificare existenţă linie deja adăugată
select exists (select * from logx._bp where _bp.nrbp=_nrbp_ AND
_bp.id=_id_ AND _bp.dep=_dep_ AND _bp.ampl=_ampl_) INTO f;
if f then return 'Exisă deja un item de acest tip introdus în BP-ul
curent!'; end if;
INSERT INTO logx._bp(nrbp,id,dep,ampl,qtyrez)
VALUES(_nrbp_,_id_,_dep_,_ampl_,_qtyrez_);
UPDATE logx.stx set qtydisp=qtydisp-_bp.qtyrez FROM logx._bp WHERE
_bp.id=stx.id AND _bp.dep=stx.dep AND _bp.ampl=stx.ampl AND
_bp.nrbp=_nrbp_ AND _bp.id=_id_ AND _bp.dep=_dep_ AND _bp.ampl=_ampl_;
return 'OK';
end
$BODY$
LANGUAGE plpgsql;
217
ANEXE
218
4.Codul sursă SQL pentru aplicaţia LogX
interogare
)par,logx._bt,logx.bt_
WHERE _bt.id=par.id AND bt_.dep_dest=par.dep AND bt_.ampl_dest=par.ampl
AND _bt.nrbt=bt_.nrbt AND _bt.nrbt=_nrbt_;
--ATENŢIE: se va realiza mai intâi UPDATE şi apoi INSERT altfel
cantităţile se pot dubla
219
ANEXE
220
4.Codul sursă SQL pentru aplicaţia LogX
to_date('||quote_literal(vald1_[i])||','||
quote_literal('dd.mm.yyyy')||')';END IF;
IF _s_[i] AND _tip_[i]='D2' THEN achS:=achS||' AND '||_nume_[i]||' >=
to_date('||quote_literal(vald1_[i])||','||quote_literal('dd.mm.yyyy')||')
AND '||_nume_[i]||' <= to_date('||quote_literal(vald2_[i])||','||
quote_literal('dd.mm.yyyy')||')';END IF;
END LOOP;
--creare tabele sursă şi tabele de legătură
-- utilizatorii pot vedea doar anumite magazii --- DOAR
MAGAZIILE/DEPOZITELE cu drepturi de acces valide vor fi luate în
rezultatul interogarii (tmpacc)!
DROP TABLE IF EXISTS tmpacc; CREATE TEMP TABLE tmpacc AS SELECT dep[s]
FROM (select acces.*, generate_subscripts(dep,1) as s from
logx.acces)par;
IF _tipQ_ ='IN' THEN achTmpTable:='q_tmp_in'; achFROM:=' FROM
logx.inx,logx.nom,tmpacc '; achLegTab:=' nom.idcode=inx.idcode AND
depinit=tmpacc.dep'; END IF;
IF _tipQ_ ='ST' OR _tipQ_ ='STL' THEN achTmpTable:='q_tmp_st';
achFROM:=' FROM logx.inx,logx.nom,logx.stx,tmpacc '; achLegTab:='
nom.idcode=inx.idcode AND inx.id=stx.id AND stx.dep=tmpacc.dep'; END IF;
IF _tipQ_ ='OUT' THEN achTmpTable:='q_tmp_out';achFROM:=' FROM
logx.inx,logx.nom,logx.outx,tmpacc '; achLegTab:=' nom.idcode=inx.idcode
AND inx.id=outx.id AND outx.dep=tmpacc.dep'; END IF;
IF _tipQ_ ='TR' THEN achTmpTable:='q_tmp_tr';achFROM:=' FROM
logx.inx,logx.nom,logx.trx,tmpacc '; achLegTab:=' nom.idcode=inx.idcode
AND inx.id=tr.id AND trx.dep_srs=tmpacc.dep AND trx.dep_dest=tmpacc.dep';
END IF;
IF achG !='#' THEN achG:=' GROUP BY '||achG; ELSE achG:=''; END IF;
achS:=' WHERE '||achLegTab||achS;
IF _tipQ_ ='STL' THEN achS:=achS||' AND stx.qtydisp>0 '; END IF;
IF _ord_!='---' THEN achO:=' ORDER BY '||_ord_; ELSE achO:=''; END IF;
IF _tipQ_ = 'ST' OR _tipQ_ ='STL' THEN ach:= ' AS SELECT SUM(qtyfiz) as
qtyfiz, SUM(qtydisp) as qtydisp '; ELSE ach:= ' AS SELECT SUM(qty) as qty
';END IF;
exeQ:='DROP TABLE IF EXISTS '||achTmpTable||' ;
CREATE TEMPORARY TABLE '||achTmpTable||ach||achA||
achFROM||achS||achG||achO||';';
RAISE NOTICE 'Interogarea: % ',exeQ;
EXECUTE exeQ;
GET DIAGNOSTICS r := ROW_COUNT; RAISE NOTICE 'Rez: %: % inregistrari',
achTmpTable, r;
RETURN codR;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION logx.q_x(text, smallint, text[], text[], boolean[],
boolean[], text[], text[], text)
OWNER TO postgres;
COMMENT ON FUNCTION logx.q_x(text, smallint, text[], text[], boolean[],
221
ANEXE
------------------------------------------------------------------------
--########### POPULAREA CU DATE DE TEST ###############
INSERT INTO logx.acces(alias, pw, dep)
VALUES('u1','0',ARRAY['DP1','DP2']),('u2','abc',ARRAY['DP2','DP3']);
INSERT INTO logx.nom(idcode,descr) VALUES
('A1','DescrA1'),('A2','DescrA2'),('B1','DescrB1'),('B2','DescrZ2'),
('C1','DescrC1'),('C2','DescrC2');
INSERT INTO logx.loc(dep, ampl) VALUES ('DP1','AA1'),('DP1','AA2'),
('DP2','AA1'),('DP2','AB1'),('DP2','AC1'),('DP2','AA2'),('DP3','AA1'),
('DP3','AA2');
INSERT INTO logx.br(nrbr, datain, idcode, status, supplier, serialno,
qty,depinit,amplinit) VALUES
(1,'2012-04-17','A1','functional','Furniz1','SS1',1,'DP1','AA1'),
(1,'2012-04-17','A2','rebut','Furniz1','SS2',1,'DP1','AA1'),
(1,'2012-04-17','B2','functional','Furniz1',NULL,10,'DP1','AA1'),
(2,'2012-04-18','B2','incert','Furniz1',NULL,15,'DP2','AA1'),
(2,'2012-04-18','C1','defect','Furniz1','SS3',1,'DP2','AA1'),
(3,'2012-04-18','C1','defect','Furniz1','SS3',1,'DP3','AA1'),
(3,'2012-04-18','B2','functional','Furniz2',NULL,25,'DP3','AA1');
-- select logx.valid_br(1) as rez;
222
4.Codul sursă SQL pentru aplicaţia LogX
223
ANEXE
ach=ach.FromAscii(PQgetvalue(rezultat, i, 0));
achT1.ParseISODate(ach);
achT1.ParseFormat(ach,wxT("%d.%m.%Y"));
cb->AppendString(ach);}
else {ach=ach.FromAscii(PQgetvalue(rezultat, i, 0));
cb->AppendString(ach);} //end if
}//endfor i
return -1;
}
//-----------------------------------------------------------------
wxString lxComboBox::getSel()
{ return cb->GetStringSelection();
}
//-----------------------------------------------------------------
int lxComboBox::refreshlx()
{ rdLista(achQRD); return 0;
}
224
5.Codul sursă pentru biblioteca LX
int nrInregistrari=PQntuples(rezultat);
if(nrCampuri==1 && nrInregistrari==1)
achR=achR.FromUTF8(PQgetvalue(rezultat, 0, 0));
return achR;
}
return _("OK");
}
//------------------------------------------------------------------
//comanda ce întoarce o lista
wxString lxCtrl::lista(wxString achQ, wxArrayString & a)
{PGresult *rezultat;
rezultat = PQexec(lxCtrl::conexiune0,achQ);
if((PQresultStatus(rezultat) != PGRES_COMMAND_OK) &&
(PQresultStatus(rezultat) != PGRES_TUPLES_OK))
{ wxString ach; ach=ach.FromAscii(PQresultErrorMessage(rezultat));
wxMessageBox(_("EROARE CDA: ")+achQ+_(" ("+ach+")!")); return _(ach);}
if(PQresultStatus(rezultat) == PGRES_TUPLES_OK)
{ wxString achR=_("#");
int nrCampuri = PQnfields(rezultat); int
nrInregistrari=PQntuples(rezultat);
if(nrCampuri!=1) return wxT("Comanda SQL întoarce mai mult de o coloană !");
a.Clear();
for(int i=0; i<nrInregistrari; i++)
a.Add(achR.FromUTF8(PQgetvalue(rezultat, i, 0)));
return achR;
}
return _("OK");
}
225
ANEXE
}
//-----------------------------------------------------------------
int lxDPC::wrSQL(wxString wrachQ)
//wrachSQKL1 - cda de scrirere în baza de date
{ PGresult *rezultat;
rezultat=PQexec(lxCtrl::conexiune0,wrachQ);
if(PQresultStatus(rezultat) != PGRES_COMMAND_OK)
{ wxMessageBox(_("Comanda actualizare eronata: ") + wrachQ +
_(" !")); return -1;}
wxMessageBox("ACTUALIZAT !");
return 0;
}
//------------------------------------------------------------------
wxString lxDPC::getValFormatStr()
{ if(!dpc->GetValue().IsValid()) return _("NULL");
return _("'")+this->dpc->GetValue().FormatISODate()+_("'");
}
226
5.Codul sursă pentru biblioteca LX
//------------------------------------------------------------------
wxString lxEditN::getValFormatStr()
{ if(ed->GetValue().IsEmpty()) return _("NULL");
return this->ed->GetValue();
}
227
ANEXE
228
5.Codul sursă pentru biblioteca LX
229
ANEXE
230
6.Codul sursă pentru aplicaţia LogX
231
ANEXE
232
6.Codul sursă pentru aplicaţia LogX
}
//-------------------------------------------------------------
iFEBP::~iFEBP() {
cbBP->Disconnect(wxEVT_COMMAND_COMBOBOX_SELECTED, wxCommandEventHandler(iFEBP::afis_BP), NULL, this);
bAddBP->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFEBP::addBP), NULL, this);
bDelBP->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFEBP::delBP), NULL, this);
bDelLin->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFEBP::delLin), NULL, this);
bSelST->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFEBP::selST), NULL, this);
bValidBP->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFEBP::validBP), NULL, this);
}
//-------------------------------------------------------------
void iFEBP::afis_BP(wxCommandEvent& event)
{if(cbBP->GetCount()<1) { pBP->Hide(); return;}
cx_destin->rdSQL(_("SELECT destin::text FROM logx.bp_ WHERE nrbp=")
+cx_nrbp->getSel()+_(" LIMIT 1;"));
cx_databp->rdSQL(_("SELECT databp::date FROM logx.bp_ WHERE nrbp=")
+cx_nrbp->getSel()+_(" LIMIT 1;"));
lxCtrl::cda(_("DROP TABLE IF EXISTS itmp_bp; CREATE TEMPORARY TABLE
itmp_bp AS SELECT (_bp.nrbp::text||'->'||_bp.id::text||'->'||
_bp.dep::text||'->'||_bp.ampl::text) AS tcu, _bp.nrbp, _bp.id,
nom.idcode, nom.refcom, nom.refteh, nom.descr, inx.po, inx.status,
inx.serialno, _bp.dep, _bp.ampl, _bp.qtyrez, _bp.qtyconf FROM
logx._bp,logx.inx,logx.nom WHERE nom.idcode=inx.idcode AND nrbp=")
+cx_nrbp->getSel()+_(" AND inx.id=_bp.id;"));
/*tcu contor unic pentru a realiza legătura între cele două tabele, în
grid va fi în prima coloana care va fi setată pe invizibil(dimensiune
zero)*/ cx_grid->preluareVarColRow();GD1->SetColSize(0,0);pBP->Show();
}
//-------------------------------------------------------------
void iFEBP::addBP(wxCommandEvent& event)
{lxCtrl::cda(_("select logx.bp_nou(")+cx_destin->getValFormatStr()+_(",")
+cx_databp->getValFormatStr()+_(");"));
cx_nrbp->rdLista(_("SELECT DISTINCT nrbp::text FROM logx.bp_ ORDER BY
nrbp;"));
cbBP->SetSelection(cbBP->GetCount()-1);
afis_BP(event);
}
//-------------------------------------------------------------
void iFEBP::delLin(wxCommandEvent& event)
{wxMessageDialog *x =
new wxMessageDialog(this,wxT("Doriţi ştergerea liniei curente?"), _(""),
wxYES_NO|wxICON_QUESTION); x->SetYesNoLabels(_("&Nu"),_("&Da"));
if(x->ShowModal() == wxID_NO)
{ lxCtrl::cda(_("DELETE FROM logx._bp USING itmp_bp WHERE itmp_bp.tcu =
(bp.nrbp::text||'->'||bp.id::text||'->'||_bp.dep::text||'->'||
_bp.ampl::text) AND tcu='") + GD1->GetCellValue(GD1->GetSelectedRows()
[0],0) +_("'; DELETE FROM itmp_bp WHERE itmp_bp.tcu='") +
GD1->GetCellValue(GD1->GetSelectedRows()[0],0) +_("';"));
GD1->DeleteRows(GD1->GetSelectedRows()[0],1);GD1->Fit();
}
afis_BP(event);
233
ANEXE
}
//-------------------------------------------------------------
void iFEBP::delBP(wxCommandEvent& event)
{ wxMessageDialog *x =
new wxMessageDialog(this,wxT("Doriţi ştergerea BPORDEROULUI curent?"),
_(""),wxYES_NO|wxICON_QUESTION); x->SetYesNoLabels(_("&Nu"),_("&Da"));
if(x->ShowModal() == wxID_NO) //&Nu corespunde lui wxID_YES
lxCtrl::cda(_("UPDATE logx.stx SET qtydisp=qtydisp+qtyrez FROM itmp_bp
WHERE stx.id=itmp_bp.id AND stx.dep=itmp_bp.dep AND stx.ampl=itmp_bp.ampl
AND itmp_bp.nrbp = ")+cx_nrbp->getSel()+_("; \
DELETE FROM logx._bp WHERE nrbp = ")+cx_nrbp->getSel()+_("; DELETE FROM
logx.bp_ WHERE nrbp = ")+cx_nrbp->getSel()+_(";"));
int s=cbBP->GetSelection(); cx_nrbp->refreshlx(); cbBP->Select(s-1);
afis_BP(event);
}
//-------------------------------------------------------------
void iFEBP::selST(wxCommandEvent& event)
{ iFSELST* x; x=new iFSELST(this, cx_nrbp->getSel()); x->ShowModal();
afis_BP(event);
}
//-------------------------------------------------------------
void iFEBP::validBP(wxCommandEvent& event)
{ wxString achQ,ach;
if(cbBP->GetSelection()<0) wxMessageBox(_("Nimic de selectat!"));
//actualizare în BP qtyconf
for(int i=0;i<GD1->GetNumberRows();i++)
lxCtrl::cda(_("UPDATE logx._bp SET qtyconf=") + GD1->GetCellValue(i,
GD1->GetNumberCols() - 1) + _(" FROM itmp_bp WHERE itmp_bp.tcu =
(_bp.nrbp::text || '->' || _bp.id::text || '->' || _bp.dep::text || '->'
|| _bp.ampl::text) AND itmp_bp.tcu='")+GD1->GetCellValue(i,0)+_("';"));
if((ach=lxCtrl::cda(_("SELECT logx.valid_bp(")+cx_nrbp->getSel()
+");"))==_("OK")) wxMessageBox(_("Validat!")); else
wxMessageBox(ach);
cx_nrbp->refreshlx(); afis_BP(event);
}
234
6.Codul sursă pentru aplicaţia LogX
235
ANEXE
236
6.Codul sursă pentru aplicaţia LogX
237
ANEXE
238
6.Codul sursă pentru aplicaţia LogX
239
ANEXE
240
6.Codul sursă pentru aplicaţia LogX
241
ANEXE
242
6.Codul sursă pentru aplicaţia LogX
243
ANEXE
wxChoice(p6,wxID_ANY,wxDefaultPosition,wxDefaultSize,cbStatusNChoices,cbStatusChoices, 0);
cbStatus->SetSelection(2); s12->Add(cbStatus, 0, wxALL, 5);
bRetStatus=new wxButton(p6, wxID_ANY, wxT("Reţine"), wxDefaultPosition, wxSize(60,-1), 0);
s12->Add(bRetStatus,0,wxALL,5);p6->SetSizer(s12);
p6->Layout();s12->Fit(p6);
CBP->AddPage(p6, wxT("STATUS"), true);
p7 = new wxPanel(CBP, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* s13; s13 = new wxBoxSizer(wxHORIZONTAL);
t7 = new wxStaticText(p7, wxID_ANY, wxT("="), wxDefaultPosition, wxDefaultSize, 0);
t7->Wrap(-1); s13->Add(t7, 0, wxALL, 5);
eSerialNo=new wxTextCtrl(p7, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
s13->Add(eSerialNo, 1, wxALL, 5);
bRetSerialNo=new wxButton(p7, wxID_ANY, wxT("Reţine"), wxDefaultPosition, wxSize(60,-1),0);
s13->Add(bRetSerialNo, 0, wxALL, 5);
p7->SetSizer(s13); p7->Layout(); s13->Fit(p7);
CBP->AddPage(p7, wxT("SerialNo"), false);
p10 = new wxPanel(CBP, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* s16; s16 = new wxBoxSizer(wxHORIZONTAL);
t10 = new wxStaticText(p10, wxID_ANY, wxT("="), wxDefaultPosition, wxDefaultSize, 0);
t10->Wrap(-1); s16->Add(t10, 0, wxALL, 5);
eID = new wxTextCtrl(p10, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
s16->Add(eID, 1, wxALL, 5);
bRetID = new wxButton(p10, wxID_ANY, wxT("Reţine"), wxDefaultPosition, wxSize(60,-1), 0);
s16->Add(bRetID, 0, wxALL, 5);
p10->SetSizer(s16); p10->Layout();s16->Fit(p10);
CBP->AddPage(p10, wxT("ID"), false);
s5->Add(CBP, 1, wxEXPAND | wxALL, 5);
wxBoxSizer* s35; s35 = new wxBoxSizer(wxHORIZONTAL);
t13=new wxStaticText(this, wxID_ANY, wxT("Sortare:"), wxDefaultPosition,wxDefaultSize, 0 );
t13->Wrap(-1); s35->Add(t13, 0, wxALL, 5);
wxString cbOrdChoices[] = { wxT("ID Code"), wxT("Ref Com"), wxT("Ref
Teh."), wxT("Descriere"), wxT("Furnizor"), wxT("Data IN"),
wxT("SerialNo"), wxT("Depozit"), wxT("Status"), wxT("Amplasament"),
wxT("Comandă (PO)"), wxT("ID"), wxT("Neordonat") };
int cbOrdNChoices = sizeof(cbOrdChoices) / sizeof(wxString);
cbOrd = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, cbOrdNChoices,
cbOrdChoices, 0);
cbOrd->SetSelection(12); s35->Add(cbOrd, 1, wxALL, 5);
bCopiaza = new wxButton(this,wxID_ANY,wxT("Copiază"),wxDefaultPosition, wxSize(-1,-
1),wxBU_EXACTFIT);
s35->Add(bCopiaza, 0, wxALL, 5); s5->Add(s35, 0, wxEXPAND, 5);
bQ =new wxButton(this, wxID_ANY,wxT("INTEROGARE STOC"), wxDefaultPosition,wxDefaultSize, 0);
bQ->SetFont(wxFont(13, 70, 90, 92, false, wxEmptyString));
bQ->SetForegroundColour(wxColour(109, 143, 71));
s5->Add(bQ, 0, wxALL|wxEXPAND, 5); s2->Add(s5, 0, wxEXPAND, 5);
s1->Add(s2, 0, wxEXPAND, 5);
GD1 = new wxGrid(this, wxID_ANY, wxDefaultPosition, wxSize(-1,150),
wxALWAYS_SHOW_SB|wxFULL_REPAINT_ON_RESIZE);
GD1->CreateGrid(0,0); GD1->EnableEditing(true);
244
6.Codul sursă pentru aplicaţia LogX
GD1->EnableGridLines(true);
GD1->EnableDragGridSize(false); GD1->SetMargins(0, 0);
GD1->AutoSizeColumns(); GD1->EnableDragColMove(false);
GD1->EnableDragColSize(true); GD1->SetColLabelSize(20);
GD1->SetColLabelAlignment(wxALIGN_CENTRE, wxALIGN_CENTRE);
GD1->AutoSizeRows(); GD1->EnableDragRowSize(true);
GD1->SetRowLabelSize(80);
GD1->SetRowLabelAlignment(wxALIGN_CENTRE, wxALIGN_CENTRE);
GD1->SetDefaultCellBackgroundColour(wxColour(226, 249, 250));
GD1->SetDefaultCellAlignment(wxALIGN_LEFT, wxALIGN_TOP);
GD1->SetBackgroundColour(wxColour(236, 250, 251));
s1->Add(GD1, 1, wxALL|wxEXPAND, 5);
pSelBP = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL) ;
wxBoxSizer* s17; s17 = new wxBoxSizer(wxVERTICAL);
P_QtyPrep = new wxPanel(pSelBP,wxID_ANY, wxPoint(-1,-1), wxSize(-1,40), wxTAB_TRAVERSAL) ;
P_QtyPrep->SetBackgroundColour(wxColour(247, 244, 232));
P_QtyPrep->SetMinSize(wxSize(-1,40));
wxBoxSizer* s14; s14 = new wxBoxSizer(wxHORIZONTAL);
s14->Add(0, 0, 1, wxALL|wxEXPAND, 5);
t12 = new wxStaticText(P_QtyPrep,wxID_ANY,wxT("Qty Preparată:"),wxDefaultPosition,
wxDefaultSize,0); t12->Wrap(-1); s14->Add(t12, 0, wxALL, 5);
eQtyPrep = new wxTextCtrl(P_QtyPrep, wxID_ANY, wxT("1"), wxDefaultPosition, wxSize(30,-1), 0);
s14->Add(eQtyPrep, 0, wxALL, 5);
bRezerva = new wxButton(P_QtyPrep,wxID_ANY,wxT("Rezervă !"),wxDefaultPosition,
wxSize(-1,-1),0);
s14->Add(bRezerva, 0, wxALL, 5); s14->Add(0,0,1,wxALL|wxEXPAND,5);
P_QtyPrep->SetSizer(s14);P_QtyPrep->Layout();
s17->Add(P_QtyPrep,0,wxALL|wxEXPAND,5);
GD2 = new wxGrid(pSelBP,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxALWAYS_SHOW_SB|
wxFULL_REPAINT_ON_RESIZE);
GD2->CreateGrid(0,0); GD2->EnableEditing(true);
GD2->EnableGridLines(true);
GD2->EnableDragGridSize(false);GD2->SetMargins(0, 0);
GD2->AutoSizeColumns(); GD2->EnableDragColMove(false);
GD2->EnableDragColSize(true); GD2->SetColLabelSize(20);
GD2->SetColLabelAlignment(wxALIGN_CENTRE, wxALIGN_CENTRE);
GD2->AutoSizeRows(); GD2->EnableDragRowSize(true);
GD2->SetRowLabelSize(80);
GD2->SetRowLabelAlignment(wxALIGN_CENTRE, wxALIGN_CENTRE);
GD2->SetDefaultCellBackgroundColour(wxColour(247, 224, 223));
GD2->SetDefaultCellAlignment(wxALIGN_LEFT, wxALIGN_TOP);
GD2->SetMinSize(wxSize(-1,200)); s17->Add(GD2,1,wxALL|wxEXPAND,5);
p9 = new wxPanel(pSelBP,wxID_ANY,wxPoint(-1,-1),wxSize(-1,40),wxTAB_TRAVERSAL);
p9->SetBackgroundColour(wxColour(243, 245, 220));
wxBoxSizer* s15; s15 = new wxBoxSizer(wxHORIZONTAL);
bDelLin=new wxButton(p9, wxID_ANY, wxT("Şterge linia"), wxDefaultPosition, wxDefaultSize,0);
s15->Add(bDelLin, 0, wxALL, 5); s15->Add(0, 0, 1, wxEXPAND, 5);
bBP = new wxButton(p9,wxID_ANY,wxT("OK"),wxDefaultPosition,wxDefaultSize,0);
bBP->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(),70,90,92,false,
wxEmptyString));
245
ANEXE
246
6.Codul sursă pentru aplicaţia LogX
247
ANEXE
cx_grid1->preluareVarColRow();
if(achBP != _("#")) //dacă este selecţie pentru BP
lxCtrl::cda(_("DROP TABLE IF EXISTS tmpselst;CREATE TEMPORARY TABLE
tmpselst as SELECT _bp.nrbp, _bp.qtyrez, inx.idcode, nom.descr, _bp.id,
_bp.dep, _bp.ampl FROM logx.inx, logx.nom, logx._bp WHERE
inx.idcode=nom.idcode AND _bp.id= inx.id AND _bp.nrbp=")+achBP+_(" ;"));
}
//------------------------------------------------------------------
// AFIŞARE PANOU SELECŢIE --FILTRE
void iFSELST::afis_sel()//afişare panou selecţie - filtrare
{wxString ach;
wxArrayString aLista;
aLista=aListaInit; cblS->Clear();
for(unsigned int j=0;j<aLista.GetCount();j++)
{ach = aLista[j];
if(val1[j]!=_("NULL")) //diferit de ŞIRUL ce conţine caracterele N U
L L!
{if(val2[j]!=_("NULL") && (listaT[j]==_("N2") ||
listaT[j]==_("D2")))
ach = val1[j] + wxT(" ≤ ") + aLista[j] + wxT(" ≤ ") +val2[j];
if(val2[j]==_("NULL") && (listaT[j]==_("N1") ||
listaT[j]==_("D1")))
ach= aLista[j] + _(" = ") + val1[j];
if(val2[j]==_("NULL") && listaT[j]==_("C"))
ach= aLista[j] + wxT(" ≡ ") + val1[j];
if(val2[j]==_("NULL") && listaT[j]==_("A"))
ach= val1[j] +wxT(" є ") + aLista[j] ;
if(val2[j]==_("NULL") && listaT[j]==_("B"))
ach= aLista[j] + _(" : ") + val1[j];
} //endif
cblS->Append(ach);
} //endfor
}
//------------------------------------------------------------------
//Selecţie NOMENCLATOR
void iFSELST::selNom(wxCommandEvent& event)
{wxArrayString* rez=new wxArrayString;
iFNOM* x; x=new iFNOM(this,rez); x->ShowModal();
if(rez->GetCount()<1)
{wxMessageBox("Nu a fost selectat nimic !"); return;}
for(int j=0; j<4; j++)
val1[j]=_("'")+rez->Item(j)+_("'");
afis_sel();}
//Şterge linia selectată
void iFSELST::delLinSelST(wxCommandEvent& event)
{ wxArrayString achS;
//dacă există selecţie în cadrul gridului
if(!GD2->IsSelection())
{wxMessageBox(wxT("Selectaţi linia!")); return;}
for(int j=0; j<GD2->GetNumberCols(); j++)
achS.Add(GD2->GetCellValue(GD2->GetSelectedRows()[0],j));
248
6.Codul sursă pentru aplicaţia LogX
249
ANEXE
//------------------------------------------------------------------
//selectează depozitul şi amplasamentul curent
void iFSELST::retineDepAmp(wxCommandEvent& event)
{ for(unsigned int j=0;j<listaN.GetCount();j++)
{ if(listaN[j]==_("stx.dep")) val1[j]=_("'")+cx_dep->getSel()+_("'");
if(listaN[j]==_("stx.ampl")) val1[j]=_("'")+cx_ampl->getSel()
+_("'");
}
afis_sel();
}
//--------------------------------------------------------------------
//selectează PO
void iFSELST::retinePO(wxCommandEvent& event)
{ for(unsigned int j=0;j<listaN.GetCount();j++)
{ if(listaN[j]==_("po") && !ePO->GetValue().IsEmpty())
val1[j]=_("'")+ePO->GetValue()+_("'");
}
afis_sel();
}
//----------------------------------------------------------------
//selectează furnizor
void iFSELST::retineFurnizor(wxCommandEvent& event)
{ for(unsigned int j=0;j<listaN.GetCount();j++)
{ if(listaN[j]==_("supplier") && !eSupplier->GetValue().IsEmpty())
val1[j]=_("'")+eSupplier->GetValue()+_("'");
}
afis_sel();
}
//------------------------------------------------------------------
//selectează STATUS
void iFSELST::retineSTATUS(wxCommandEvent& event)
{ for(unsigned int j=0;j<listaN.GetCount();j++)
{ if(listaN[j]==_("status") && !cbStatus-
>GetStringSelection().IsEmpty())
val1[j]=_("'")+cbStatus->GetStringSelection()+_("'");
}
afis_sel();
}
//-----------------------------------------------------------------
//selectează SerialNo
void iFSELST::retineSerialNo(wxCommandEvent& event)
{ for(unsigned int j=0;j<listaN.GetCount();j++)
{ if(listaN[j]==_("serialno") && !eSerialNo->GetValue().IsEmpty())
val1[j]=_("'")+eSerialNo->GetValue()+_("'");
}
afis_sel();
}
//-------------------------------------------------------------------
//selectează ID
void iFSELST::retineID(wxCommandEvent& event)
{ for(unsigned int j=0;j<listaN.GetCount();j++)
250
6.Codul sursă pentru aplicaţia LogX
251
ANEXE
IMPLEMENT_APP(LogXApp);
bool iFACC::accesX=false;
//-------------------------------------------------------------------
bool LogXApp::OnInit()
{ lxCtrl::conexiune0=NULL;
/*conexiunea iniţială pentru verificarea parolei de acces - se
conectează cu parola la nivel de aplicaţie*/
lxCtrl::conectare(_("picdb"),_("logx_sw"),_("lilo"),_("localhost"),_("543
5"));
/* Prin "return true" se asigură menţinerea în aplicaţie
în buclele de citire a evenimentelor şi de tratare a acestora*/
(new iFACC(NULL))->ShowModal();
if(iFACC::accesX)
{(new iFPB(NULL))->Show(); return true;}
//este lansată fereastra cu panoul cu butoane, nu este fereastră modală,
else return false;
}
//-------------------------------------------------------------------
iFPB::iFPB(wxWindow* parent, wxWindowID id, const wxString& title, const
wxPoint& pos, const wxSize& size, long style): wxFrame(parent, id, title,
pos, size, style)
{ this->SetSizeHints(wxDefaultSize, wxDefaultSize);
this->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(),70,90,90,false, wxEmptyString));
this->SetBackgroundColour(wxColour(244, 244, 244));
wxBoxSizer* s1; s1 = new wxBoxSizer(wxVERTICAL);
t1 = new wxStaticText(this, wxID_ANY, wxT("LogX"), wxDefaultPosition, wxDefaultSize,
wxALIGN_CENTRE);
t1->Wrap(-1); t1->SetFont(wxFont(18,72,90,92,false,wxEmptyString));
t1->SetHelpText(wxT("Exemplu pentru o aplicaţie simplă de gestiune a stocurilor."));
s1->Add(t1, 0, wxALIGN_CENTER|wxALL, 5);
wxBoxSizer* s2; s2 = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* s3; s3 = new wxBoxSizer(wxVERTICAL);
t2 = new wxStaticText(this,wxID_ANY,wxT("EDITARE"), wxDefaultPosition, wxDefaultSize,
wxALIGN_CENTRE);
t2->Wrap(-1); t2->SetFont(wxFont(12,75,90,92,false,wxEmptyString));
s3->Add(t2, 0, wxALIGN_CENTER|wxALL, 5);
be1 = new wxButton(this, wxID_ANY, wxT("INTRĂRI"), wxDefaultPosition, wxDefaultSize, 0);
be1->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(),70,90,90,false, wxEmptyString));
s3->Add(be1, 0, wxALL|wxEXPAND, 5);
be2 = new wxButton(this, wxID_ANY, wxT("LIVRĂRI"), wxDefaultPosition, wxDefaultSize, 0);
be2->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(),70,90,90,false, wxEmptyString));
s3->Add(be2, 0, wxALL|wxEXPAND, 5);
be3 = new wxButton(this, wxID_ANY, wxT("TRANSFER"), wxDefaultPosition, wxDefaultSize, 0);
be3->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(),70,90,90,false, wxEmptyString));
be3->Enable(false); s3->Add(be3, 0, wxALL|wxEXPAND, 5);
be4 = new wxButton(this,wxID_ANY,wxT("NOMENCLATOR"),wxDefaultPosition, wxDefaultSize, 0);
s3->Add(be4, 0, wxALL|wxEXPAND, 5); s2->Add(s3, 1, wxEXPAND, 5);
wxBoxSizer* s4; s4 = new wxBoxSizer(wxVERTICAL);
t3 = new wxStaticText(this,wxID_ANY,wxT("RAPOARTE"),wxDefaultPosition, wxDefaultSize,
252
6.Codul sursă pentru aplicaţia LogX
wxALIGN_CENTRE);
t3->Wrap(-1); t3->SetFont(wxFont(12,75,90,92,false,wxEmptyString));
s4->Add(t3, 0, wxALIGN_CENTER|wxALL, 5);
br1 = new wxButton(this, wxID_ANY, wxT("INTRĂRI"), wxDefaultPosition, wxDefaultSize, 0);
br1->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString));
br1->Enable(false); s4->Add(br1, 0, wxALL|wxEXPAND, 5);
br2=new wxButton(this, wxID_ANY, wxT("LIVRĂRI"), wxDefaultPosition, wxDefaultSize, 0);
br2->SetFont(wxFont(wxNORMAL_FONT->GetPointSize(), 70, 90, 90, false, wxEmptyString));
br2->Enable(false); s4->Add(br2, 0, wxALL|wxEXPAND, 5);
br3=new wxButton(this, wxID_ANY, wxT("TRANSFER"), wxDefaultPosition, wxDefaultSize, 0);
br3->Enable(false); s4->Add(br3, 0, wxALL|wxEXPAND, 5);
br4 = new wxButton(this, wxID_ANY, wxT("STOC"), wxDefaultPosition, wxDefaultSize, 0);
s4->Add(br4, 0, wxALL|wxEXPAND, 5); s2->Add(s4, 1, wxEXPAND, 5);
s1->Add(s2, 1, wxEXPAND, 5); this->SetSizer(s1);
this->Layout();
// Evenimente pentru conectare
be1->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFPB::apasa_be1), NULL, this);
be2->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFPB::apasa_be2), NULL, this);
be4->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFPB::apasa_be4), NULL, this);
br4->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFPB::apasa_br4), NULL, this);
}
//-----------------------------------------------------------------
iFPB::~iFPB()
{ lxCtrl::deconectare();
be1->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFPB::apasa_be1), NULL, this);
be2->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFPB::apasa_be2), NULL, this);
be4->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFPB::apasa_be4), NULL, this);
br4->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(iFPB::apasa_br4), NULL, this);
}
//------------------------------------------------------------------
void iFPB::apasa_be1(wxCommandEvent& event)
{ (new iFEI(this))->ShowModal();
}
//------------------------------------------------------------------
void iFPB::apasa_be4(wxCommandEvent& event)
{ (new iFNOM(this,NULL))->ShowModal();
}
//-----------------------------------------------------------------
void iFPB::apasa_br4(wxCommandEvent& event)
{ (new iFSELST(this,_("#")))->ShowModal();
}
//--------------------------------------------------------------------
void iFPB::apasa_be2(wxCommandEvent& event)
{(new iFEBP(this))->ShowModal();
}
253
Bibliografie
Bibliografie
[3] www.postgresql.org.
[4] http://en.cppreference.com/w/
[5] http://www.delorie.com/djgpp/doc/libc/
[6] http://codelite.org/
[7] http://libharu.org/
[8] http://sourceforge.net/projects/wxformbuilder/
254