Delphi este o colectie integrata de capabilitati de dezvoltare a sistemelor soft care, mânuite în spiritul care a dus la specificarea lor, pot simplifica mult existenta, îndeosebi a programatorilor implicati în derularea unui proiect de sistem soft. Ceva mai exact putem spune ca "Delphi este un mediu de programare vizuala, obiect orientat, pentru dezvoltare rapida si cu scop general a aplicatiilor Windows 95, 98, 2000 si NT".
Dintre caracteristicile principale ale sistemului Delphi, semnalam:
Mediul de dezvoltare poate fi personalizat
Este cunoscut faptul ca, de câtiva ani, mediile vizuale de programare au adaugat clasicelor IDE (Integrated Development Environment), care integrau trei instrumente de baza în programare( editor, compilator si depanator), capabilitati de realizare a interfetelor cu suport vizual si de generare automata a codului aferent. Delphi merge un pas mai departe, permitând utilizatorului sa personalizeze IDE Delphi cu ajutorul serviciilor oferite de componenta Open Tools API.
Orientare pe obiect
Limbaje precum Visual Basic sunt pseudo-obiect orientate, folosind obiecte si metode fara a oferi suport pentru încapsulare, mostenire si polimorfism. Limbajul Pascal Object, care sta la baza aplicatiilor Delphi, este un limbaj cu adevarat obiect orientat care permite combinarea datelor si a codului asociat pentru a defini clasele (încapsulare), crearea de descendenti ai acestor clase (mostenire) si tratarea unei clase descendente în relatia cu o clasa parinte din perspectiva polimorfica.
Biblioteca de componente
Toate elemenetele cu ajutorul carora sunt realizate, în mod uzual, interfetele aplicatiilor Windows sunt standardizate si puse la dispozitia programatorilor ca si componente, pastrate în biblioteca de componente a sistemului. Daca exista programatori care vor sa modifice functionalitatea componentelor oferite de Delphi, o pot face elegant, printr-o derivare adecvata, dar cu un efort de programare considerabil mai mare decât în cazul simplei utilizari a componentelor.
Suport OCX si ActiveX
Delphi "tolereaza" obiecte care sunt create cu alte limbaje (ca de exemplu C++) si sunt distribuite conform standardului OCX. Obiectele OCX sunt, în general, furnizate de companii de soft specializate, asigurând o gama larga de functionalitati. ActiveX este o redezvoltare a modelului OCX, cu utilizare larga, îndeosebi pentru browserele de Internet. OCX, ActiveX, COM, DCOM, OLE, etc. sunt tehnologii Microsoft importante pentru a întelege mai exact puterea oferita programatorilor de paradigma Windows de programare. Din nou fac trimitere la optionalul de programare Windows sau la autoinstruire.
sabloane
Delphi recunoaste patru tipuri de sabloane: forma, aplicatia, componenta si codul. sabloanele de tip forma, aplicatie si componenta permit reutilizarea colectiilor de obiecte în programe diferite sau ca baza pentru realizarea unui program nou. sabloanele de tip cod simplifica procesul de scriere a codului aferent unor enunturi Delphi standard.
Compilare adevarata
Multe medii de dezvoltare Windows genereaza executabile semi-compilate (p-cod). Deoarece p-codul nu este executabil pe o masina fizica, el trebuie translatat în momentul executiei, ceea ce înseamna o semnificativa penalizare a performantei unui program. Delphi produce cod executabil autentic care, în plus, nu pretinde performante deosebite din partea mediului de executie gazda. Totodata, filozofia Delphi permite lucrul cu componente DLL, fapt ce are implicatii asupra performantelor programului si mediului de executie. Orientarea pe componente DLL a aplicatiilor realizate în spirit Windows creeaza, este drept, niste probleme de portabilitate de la sisteme puternic configurate la sisteme mai modeste atat din punct de vedere hard cat si din punct de vedere al fortei sistemului de operare.
Aplicatii robuste
Sunt cunoscute de la alte limbaje dificultatile legate de tratarea de catre programator a exceptiilor care pot sa apara în timpul executiei unui program. Delphi rezolva aceste probleme propunând enunturi de limbaj adecvate pentru solutionarea lor. Aceste enunturi nu fac altceva decât sa transpuna în sintaxa Object Pascal, semantica cunoscuta de la abordarea C++ pentru tratarea exceptiilor.
Gestiunea colectiilor de date
Specialistii de la Borland sunt constienti de faptul ca foarte multe aplicatii sunt realizate în jurul ideii de gestiune a datelor. De aceea, Delphi ofera obiecte si componente care reduc semnificativ efortul de realizare a aplicatiilor cu baze de date.
Delphi este, în felul lui, un mediu de dezvoltare mamut care permite o deschidere aproape totala catre toate capabilitatile specifice aplicatiilor Windows (aplicatiile grafice, aplicatiile multimedia, locale sau în retea).
As mai adauga inca un motiv important în alegerea mediului Delphi pentru a face programare vizuala: usurinta a învatarii protocoalelor de dezvoltare asistata a aplicatiilor Delphi, comparativ cu alte medii (Visual Basic sau Visual C++).
Desi capabilitatile mediului Delphi permit realizarea unor aplicatii utilizând, esential, doar click-ul de mouse, adevaratele aplicatii utilizator presupun, înca, efort de programare pentru rezolvarea unor probleme specifice acestora. Limbajul prin intermediul caruia se face insertia de comportament specific în aplicatiile Delphi este limbajul Object Pascal. Schema de principiu dupa care un programator combina capabilitatile Delphi de generare a codului cu activitatea de adaugare a codului specific poate fi dedusa facând o scurta trecere în revista a disciplinei Delhpi de realizarea a unei aplicatii.
Left =200
Top =110
Width =544
Height =375
Caption ='Form1'
Font.Charset =DEFAULT_CHARSET
Font.Color =clWindowText
Font.Height =-11
Font.Name ='MS Sans Serif'
Font.Style =[]
PixelsPerInch=96
TextHeight =13
end
Daca doreste, programatorul poate modifica unele dintre proprietatile care apar în vizualizarea de mai sus.
Revenirea de la reprezentarea de tip text la reprezentarea vizuala a unei forme se poate face cu ajutorul comenzii View as Form (Alt+F12), accesibila în meniul local al reprezentarii de tip text.
Inspectorul de obiecte este o componenta a mediului Delphi, responsabila de actualizarea proprietatilor de tip câmp sau eveniment, asociate componentelor care contribuie la functionalitatea unei aplicatii. Este vorba de acele proprietati ale obiectelor unei aplicatii care sunt publicabile (se va vedea mai precis sensul acestei sintagme când se va prezenta perspectiva Object Pascal asupra conceptului de clasa).
Pentru programator este important faptul ca, inspectorul de obiecte este instrumentul care permite adaptarea proprietatilor obiectelor unei aplicatii la cerintele concrete ale aplicatiei, cooperând permanent cu editorul de forme si cu editorul de cod. Impactul dinamicii relatiei inspector de obiecte - editor de cod - editor de forme poate fi apreciat corect doar rezolvând efectiv probleme cu ajutorul mediului Delphi.
Pentru descrierea obiectelor care alcatuiesc o aplicatie se utilizeaza conceptul de proprietate. În Delphi obiectele pot avea proprietati (un concept nou pe care îl vom lamuri din interiorul limbajului Object Pascal). Aceste proprietati pot fi de tip câmp sau de tip eveniment. Proprietatile de tip câmp optimizeaza procesul de gestiune a atributelor informationale ale unui obiect. Proprietatile de tip eveniment optimizeaza procesul de gestiune a atributelor comportamentale ale unui obiect, implicate în gestiunea mesajelor unei aplicatii, stiut fiind faptul a o aplicatie Windows este puternic dirijata de evenimente si în consecinta intens preocupata de tratarea diverselor mesaje care apar pe timpul executiei acestei aplicatii.
De exemplu, proprietatea Width a unei forme descrie latimea acesteia.
Evenimentul OnClick în contextul unei forme se refera la efectuarea unui click de mouse pe forma. Aceleasi consideratii sunt valabile si relativ la o componenta oarecare. Prin intermediul proprietatilor stabilim caracteristicile vizuale sau functionale ale formelor sau componentelor. Unele proprietati au valori implicite; valorile altora pot fi selectate dintr-o multime de alternative. Totodata, proprietatile pot fi modificate si în timpul executiei aplicatiei. De fapt, proprietatea de tip câmp este un concept cu ajutorul caruia se obtine un spor de flexibilitate în ceea ce priveste accesul la câmpurile unui obiect. În spatele proprietatilor de tip eveniment se vor afla întotdeauna metode ale claselor care le abstractizeaza. Evident, acestor metode le asociem cod Object Pascal care reprezinta tratarea evenimentului cu care sunt solidare.
Conform strategiei Delphi de organizare a codului scris de programator, fiecare forma are asociat si un fisier cu extensia .PAS în care se pastreaza atât codul generat automat de Delphi cât si codul adaugat de programator structurat dupa exigentele conceptului de unit, cunoscut din Pascal. Mai multe forme într-o aplicatie înseamna mai multe unit-uri. Legarea formelor, astfel încât acestea sa formeze o aplicatie este realizata cu ajutorul conceptului de proiect.
Nu este interzis ca o forma sa îsi implementeze functionalitatea cu ajutorul mai multor unit-uri, daca este necesar din punct de vedere al modularizarii.
În timp ce unit-urile corespunzatoare formelor reprezinta modalitatea prin care Delphi organizeaza obiectele unei aplicatii, prin conceptul de proiect se ofera o pârghie de reprezentare a structurii de prelucrare a aplicatiei la un nivel înalt de abstractizare (care ar putea imita oarecum ideea de program principal din Pascal sau TVision). Astfel ca putem spune ca, programului principal al unei aplicatii, Delphi îi asociaza un fisier cu extensia .DPR . Implicit, numele fisierului proiect este Proiect1.DPR. În cazul unei aplicatii cu o singura forma codul asociat este:
uses Forms,
Unit1 in "Unit1.pas'
begin
Application.Initialize;
Application.CreateForm(Tform1,Form1);
Application.Run;
end.
Asadar, aplicatiile Delphi înca se mai bazeaza pe abilitatea programatorilor de a scrie cod. Date fiind particularitatile limbajului Object Pascal, putem concluziona ca procesul de realizare a aplicatiilor Delphi nu este întotdeauna un exercitiu în care rutina si automatismele înseamna totul. Aplicatiile adevarate presupun cunostinte temeinice de algortimica, modelare obiect orientata, modularizare, precum si o cunoastere profunda a tuturor posibilitatilor oferite de binomul Object Pascal - IDE Delphi.
Prin intermediul tipurilor de date compilatorul este informat cu privire la modul în care vor fi organizate datele programului în memorie. Ori de câte ori se declara o variabila, este necesara raportarea la un tip de data. Anumite tipuri de date sunt deja definite în limbaj (predefinite); alte tipuri pot fi definite de catre utilizator. Pascal a fost unul dintre primele limbaje de programare care a permis programatorului sa defineasca tipuri de date noi, conform cerintelor programelor.
Despre limbajele care ofera suport pentru declararea de tipuri utilizator (date, pointer sau procedurale, în general) se spune ca sunt limbaje cu suport pentru tipizare.
Sintaxa Pascal referitoare la definirea si instantierea tipurilor de date este valabila si în Object Pascal.
Observatie
În mod uzual, identificatorii de tip în Object Pascal pot fi utilizati doar în contextul definirii unui nou tip sau în contextul unei declaratii de variabile.
Exista, totusi, câteva rutine care folosesc identidicatorii de tip ca parte a unei instructiuni executabile. De exemplu, SizeOf( T ) returneaza numarul de octeti necesari pentru o instanta de tip T.
Tipuri de date simple
Fiecare tip de data din lumea reala, oricât de complicat, poate fi exprimat cu ajutorul unor componente simple, usor de manipulat la nivel de microprocesor. În Object Pascal, astfel de tipuri de date simple sunt separate conventional în doua grupe: tipurile ordinale (care reprezinta informatia cu ajutorul unor componente de marime variata, usor de manipulat de catre microprocesor) si tipul real (care aproximeaza informatii ce pot fi reprezentate prin numere reale.
Observatie
Pentru toate tipurile ordinale, Object Pascal asigura un mecanism typecasting pentru convertirea valorilor întregi la valoarea ordinala corespunzatoare, asftel:
"Daca T este numele unui tip ordinal si X este o expresie întreaga, atunci T(X) returneaza o valoare de tip T a carui valoare ordinala este X.
Low(T) |
Functie; returneaza valoarea minima a tipului ordinal T. |
High(T) |
Functie; returneaza valoarea maxima a tipului ordinal T. |
Ord(X) |
Functie; returneaza valoarea ordinala a expresiei ordinale X, relativ la tipul ordinal gazda. |
Pred(X) |
Functie; returneaza predecesorul valorii expresiei X. Pentru expresii întregi returneaza X-1. |
Succ(X) |
Functie; returneaza succesorul valorii expresiei X. Pentru expresii întregi returneaza X+1. |
Dec(V) |
Procedura; decrementeaza variabila V; Efectul ei este echivalent cu V:=Pred(V). |
Inc(V) |
Procedura; incrementeaza variabila V; Efectul ei este echivalent cu V:=Succ(V). |
Tabelul 2.1 Proceduri si functii relativ la tipurile ordinale
Tipuri întregi
Tipurile întregi reprezinta informatia ca numere întregi. În Object Pascal tipurile întregi predefinite se împart în tipuri fizice (fundamentale) si tipuri logice (generice). În mod uzual în aplicatii sunt preferate tipurile logice deoarece acestea sunt implementate astfel încât sa asigure cele mai bune performante pe o masina si un sistem de operare date. Tipurile întregi fizice sunt utile atunci când se doreste un control strâns asupra numarului de octeti afectati întregilor cu care lucreaza programul. Distributia exacta pe cele doua tipuri a varietatilor de întregi o prezentam în Tabelul 2.2 si Tabelul 2.3.
Tip |
Ordin de marime |
Reprezentare fizica |
ShortInt |
8 biti /cu semn |
|
SmallInt |
16 biti/cu semn |
|
LongInt |
32 biti/ cu semn |
|
Byte |
8 biti/fara semn |
|
Word |
16 biti/fara semn |
Tabelul 2.2 Tipurile fizice
Tip |
Ordin de marime |
Tip reprezentare fizica |
Integer |
16 biti/cu semn/SmallInt |
|
Integer |
32 biti/cu semn/LongInt |
|
Cardinal |
16 biti/fara semn/Word |
|
Cardinal |
32 biti/fara semn/LongInt |
Sa binevoim fata de cititor si sa-i spunem ca, utilizând tipurile fizice punem niste "contre" mai mari sau mai mici portabilitatii programelor noastre, ceea ce, la un anumit nivel de profesionalism nu este lipsit de importanta.
Tipurile de date întregi partajeaza toate operatiile specifice tipurilor ordinale având si operatii specifice numerelor. În Tabelul 2.4 prezentam lista acestor operatii.
Operatia |
Rezultatul |
Abs(X) |
Returneaza valoarea absoluta a întregului din X |
X Div Y |
Returneaza câtul împartirii întregului X la întregul Y |
X Mod Y |
Returneaza restul împartirii întregului X la întregul Y |
Odd(X) |
Returneaza TRUE daca X este impar si FALSE daca X este par |
Sqr(X) |
Returneaza patratul lui X |
Tipuri caracter
Implementarile pe calculatoarele compatibile IBM-PC ale limbajului Pascal au folosit, de la început, pentru reprezentarea caracterelor codul ASCII (American Standard Code for Information Interchange). Schema de codificare ASCII utilizeaza efectiv sapte biti ai unei locatii de memorie pentru reprezentarea unui caracter. În mod evident, bitul suplimentar dubleaza numarul de caractere care pot fi reprezentate pe opt biti. Actuala definitie a sistemului Delphi utilizeaza o varianta extinsa a codului ASCII numita Schema de codificare extinsa ANSI (American National Standard Institute). Codul extins ANSI permite, pe diferite platforme de operare, includerea de caractere suplimentare, utile în comunicarea cât mai completa cu utilizatorii calculatoarelor. Pentru acoperirea tuturor cerintelor de comunicare a calculatoarelor cu utilizatorii, în contextul internationalizarii comunicatiei prin Internet, a fost specificat codul pe 16 biti UNICODE, în care primele 256 de intrari corespund direct celor 256 caractere definite în codul ANSI. Pentru a facilita utilizarea acestor tipuri de reprezentare a caracterelor, Object Pascal defineste doua tipuri fizice de date de tip caracter si un tip generic sau logic de data de tip caracter. Tipurile fizice sunt prezentate în Tabelul 2.5.
Tipul |
Caracteristici |
AnsiChar |
Caractere orientate byte, ordonate conform setului de caractere extins ANSI |
WideChar |
Caractere orientate word, ordonate conform setului de caractere UNICODE. Primele 256 caractere UNICODE corespund setului extins de caractere ANSI. |
Tabelul 2.5 Tipuri fizice de caractere utilizabile în Delhpi
Tipul generic de caracter în Delphi se numeste simplu char. În limbajul Pascal clasic exista doar tipul char. În Delphi tipul char corespunde întotdeauna tipului fizic AnsiChar.
Apelul functiei Ord (C) unde C este o valoare de tip caracter, returneaza o valoare de tip întreg folosita la reprezentarea caracterului C în memoria microprocesorului.
De asemenea, Chr(X) este o functie care converteste întregul X în caracterul corespunzator codului X. În Delphi, acest apel este echivalent cu Char( X ).
Avem la dispozitie si functia UpCase care converteste,daca este cazul, un singur caracter la valoarea lui majuscula.
Tipuri logice
Programatorii se lovesc, de timpuriu, de necesitatea de a lucra cu variabile cu doua stari. În Pascal-ul clasic tipul predefinit care raspunde unei astfel de cerinte este tipul boolean care poate lua una din valorile true sau false. În limbajul C valoarea numerica 0 este asimilata cu false iar o valoare numerica nenula este asimilata cu true. În Delphi exista patru tipuri logice predefinite, prezentate în Tabelul 2.6.
Tip |
Marimea reprezentarii în octeti |
Boolean |
1 octet |
ByteBool |
1 octet |
WordBool |
2 octeti |
LongBool |
4 octeti |
Tabelul 2.6 Tipuri logice în Delphi
Variabilele de tip Boolean pot lua numai valorile False sau True. Variabilele de tip ByteBool, WordBool si LongBool pot lua alte valori ordinale interpretate prin conventie ca False pentru 0 sau True pentru orice valoare nenula.
Tipuri enumerate
În mod uzual, un tip enumerat este capabil sa reprezinte valori discrete care au nume. Tipul Boolean din Object Pascal este un exemplu de tip enumerat predefinit astfel:
type Boolean=(False, True);
Cele mai multe tipuri enumerate sunt pur si simplu liste de identificatori unici pe care programatorul îi va utiliza în situatii dedicate.
Sintaxa de declarae este:
type <Tip_Enumerat>=(Identificator_1, Identificator_n,., Identificator_n);
Tipul enumerat este ordinal. Prin urmare, identificatorii din lista enumerata au asociat un numar numit valoare ordinala asociata. Primul identificator are valoarea ordinala 0, al doilea are valoarea ordinala 1 s.a.m.d..
Tipuri subdomeniu
Un tip subdomeniu reprezinta informatii care pot lua valori de un anumit ordin al unui tip ordinal corespunzator, altul decât subdomeniu.
Sintaxa de declarare a tipului subdomeniu ramâne aceeasi din Pascal:
type <Subdomeniu>=<Valoare_De_Început>..<Valoare_De_Sfârsit>;
Variabilele tipului subdomeniu partajeaza toate caracteristicile tipului definitor.
Tipuri reale
Tipurile reale reprezinta informatii numerice care pot avea atât parte întreaga cât si parte fractionara. Object Pascal are sase specii de tipuri reale. Aceste tipuri se deosebesc prin ordinul de marime asociat si precizia reprezentarii corespunzatoare, fapt ilustrat mai precis în Tabelul 2.7.
Tipul |
Minimum în valoare absoluta |
Maximum în valoare absoluta |
Cifre semnificative |
Nr. octeti |
Real |
2.9E-39 |
1.7E38 | ||
Single |
1.5E-45 |
3.4EE38 | ||
Double |
5.0E-324 |
1.7E308 | ||
Extended |
3.4E-4932 |
1.1E4932 | ||
Comp |
9.2E18 | |||
Currency |
9.2E14 |
Tabelul 2.7 Tipuri reale în Delphi
Numerele reale, în înteles Object Pascal, nu sunt acelasi lucru cu numerele reale ca înteles matematic. Un tip real Object Pascal este o submultime stricta a lui R,ale carei elemente pot fi reprezentate în virgula mobila utilizând un registru cu numar specific de biti, conform standardului IEEE (Institute of Electrical and Electronic Engineers). Într-o masura mult mai mare decât numerele întregi, numerele reale ridica probleme dintre cele mai neasteptate celor care au aplicatii în care precizia reprezentarii si ordinul de marime sunt esentiale.
Unit-ul Delphi System pune la dispozitia programatorilor o serie de rutine pentru manipularea numerelor reale. Cele mai uzuale dintre ele sunt prezentate în Tabelul 2.8. Alte rutine de interes în acest scop sunt disponibile în unit-urile SysUtils si Math.
Functia |
Ce returneaza |
Abs(x) |
Valoare absoluta a lui x |
ArcTan(x) |
Arctangenta lui x |
Cos(x) |
Cosinusul argumentului x, considerat în radiani |
Exp(x) |
Puterea x a numarului e |
Frac(x) |
Partea fractionara a lui x |
Int(x) |
Partea întreaga a lui x. Atentie! Int returneaza o valoare de tip real. |
Ln(x) |
Logaritmul natural al numarului x |
Pi |
Numarul p |
Round(x) |
Numarul întreg cel mai apropiat de x. Rezultatul returnat de Round este de tip înreg. Formula "cel mai apropiat de x" devine ambigua când partea fractionara este o.5. Delphi lasa pe seama sistemului sa decida cum efectuiaza rotunjirea în aceasta situatie. În mod uzual, cu procesor INTEL, recomandarea IEEE este de a se rotunji la cel mai apropiat numar înreg par. |
Sin(x) |
Sinusul trigonometric al argumentului x, considerat în radiani. |
Sqr(x) |
Patratul lui x. Adica x*x. |
Sqrt(x) |
Radacina patrata a lui x. |
Trunc(x) |
Partea întreaga a lui x. Spre deosebire de Int, Trunc returneaza o valoare de tip întreg. |
Tabelul 2.8 Functii pentru lucrul cu numere reale
Tipuri sir
În expresii, Delphi suporta trei specii de siruri de caractere format fizic :
-scurt (ShortString);
-lung (AnsiString);
-marit (WideString).
AnsiString, ShortString si WideString pot fi utilizate combinat în atribuiri si expresii, Delphi executând automat conversiile necesare.
Atât tipul AnsiString cât si tipul WideString pastreaza caracterele în vectori alocati dinamic, a caror lungime este plafonata doar de lungimea fizica a memoriei. Diferenta între aceste doua tipuri consta în faptul ca AnsiString pastreaza caracterele într-un arrray de caractere de tip char iar WideString pastreaza caracterele într-un array de caractere de tip WideChar. În mod uzual este utilizat tipul AnsiString, tipul WideString fiind indispensabil daca se realizeaza aplicatii care utilizeaza setul de caractere UNICODE.
Fizic, tipul ShortString este pastrat ca un array [0..255] of char. Prima pozitie în sir pastreaza lungime dinamica a sirului, care poate varia între 0 si 255 caractere. Caracterele efective ocupa pozitiile de la 1 pâna la 255. Tipul ShortString a fost introdus din motive de compatibilitate cu Borland Pascal si versiunile timpurii ale mediului Delphi.
Tipul sir de caractere generic este cunoscut în Delphi ca string. Cu ajutorul directivei de compilare putem stabili daca string se refera la ShortString sau AnsiString. Pentru , care este starea implicita a directivei, string se refera la un AnsiString.
Din motive de compatibilitate cu alte limbaje, Delphi suporta o clasa de siruri de caractere numite siruri de caractere null-terminate. Nu exista cuvinte rezervate sau identificatori speciali pentru a indica folosirea sirurilor de caractere null-terminate.
sirurile de caractere null-terminate se compun din caractere nenule urmate de caracterul null (#0). Spre deosebire de tipurile Object Pascal AnsiString, ShortString si WideString, sirurile de caractere null-terminate nu au indicator de lungime separat.
Tabelul 2.9 prezinta câteva rutine utile în lucrul cu siruri de caractere.
Functia |
Descrierea |
Concat (S1, S2, S3) |
Returneaza rezultatul concatenarii sirurilor S1, S2, S3. |
Copy (S, Pos, Len) |
Returneaza un subsir de lungime cel mult Len caractere, care începe din pozitia Pos a sirului de caractere S. |
Delete (S, Pos, Len) |
sterge cel mult Len caractere din sirul S, începând cu pozitia Pos |
Insert ( Sursa, Dest, Pos) |
Insereaza sirul de caractere Sursa în variabila sir Dest începând din pozitia Pos. |
Length (S) |
Returneaza lungimea dinamica a sirului S. Similara functiei LEN din Basic sau functiei strlen( ) din C/C++. |
Pos (Subs,S) |
Returneaza pozitia primei aparitii a subsirului Subs în sirul S. Similara functiei SUBSTR din Basic sau functiei strstr( ) din C/C++. |
SetLength(S, NewLen) |
Seteaza lungimea dinamica a variabilei sir S. |
SetString |
Seteaza continutul unui sir de caractere. |
Str (X, S) |
Converteste expresia numerica X în sirul de caractere S. |
StringOfCharS |
Returneaza un un sir de un numar dat de caractere. |
Val (S, V, Code) |
Converteste sirul S la reprezentarea numerica corespunzatoare. |
Tabelul 2.9 Rutine sistem utile în lucrul cu siruri de caractere
Tipuri de date structurate
La nivel elementar, cele mai utile tipuri de date sunt acelea care pot contine numere sau informatii de tip caracter sau sir de caractere. Pornind de la tipurile elementare de date, putem crea alte tipuri de date utile, prin combinarea mai multor instante ale tipurilor elementare. Tipurile de date structurate furnizeaza capabilitati de creare a unor tipuri de date noi, prin extinderea definitiei unor tipuri de date anterior definite, astfel încât, în esenta, mai multe valori ale tipului anterior definit, sa poata fi manipulate cât se poate de comod si eficient. Asadar, componentele tipurilor structurate pot fi manipulate individual, sau ca întreg si pot fi ele însele de tip structurat. Tipurile structurate din Delphi sunt:
-Tipul înregistrare (record);
-Tipul tablou(array);
-Tipul multime;
-Tipul fisier;
-Tipul clasa;
-Tipul referinta la clasa;
Dupa cum se va vedea, noutatea fata de Pascal o reprezinta introducerea tipului clasa, prin care se opereaza nu doar o schimbare de nume ci o noua abordare a problemelor specifice programarii obiect orientate. Tipul referinta la clasa, aduce un argument în plus în ceea ce priveste încercarea platformei Delphi de a se apropia de alte limbaje importante pentru paradigma obiect orientata.
Tipul înregistrare
Cuvântul rezervat record permite gruparea diferitelor tipuri de date într-un singur tip. Sintaxa generala a declaratiei unui tip înregistrare este:
type
:
<Identificator_Tip_Record>=record
<Câmp_1>:<Tip_Câmp_1>;
<Câmp_2>:<Tip_Câmp_2>;
:
<Câmp_n>:<Tip_Câmp_n>;
[case <Selector_parte_variabila> : <Tip_Selector> of
<Val_1_Selector>:<Parte_variabila_1>;
<Val_2_Selector>:<Parte_variabila_2>;
:
<Val_k_Selector>:<Parte_variabila_k>;]
end;
sau:
type
:
<Identificator_Tip_Record>=record
<Câmp_1>:<Tip_Câmp_1>;
<Câmp_2>:<Tip_Câmp_2>;
:
<Câmp_n>:<Tip_Câmp_n>;
[case <Tip_Selector> of
<Val_1_Selector>:<Parte_variabila_1>;
<Val_2_Selector>:<Parte_variabila_2>;
:
<Val_k_Selector>:<Parte_variabila_k>;]
end;
Dupa cum se vede, sintaxa generala permite, optional, definirea de înregistrari cu lungime variabila, în doua moduri:
În prima varianta, alegerea partii variabile se face prin intermediul unei variabile selector introdusa de clauza case.
În varianta a doua, alegerea partii variabile se face în functie de valoarea unui câmp discriminator care face parte din lista de câmpuri a partii fixe. În acest caz clauza case case introduce doar tipul selectorului.
Este cunoscut faptul ca, diferitele instante ale unui tip înregistrare cu format variabil, ocupa în memorie acelasi numar de octeti. De asemenea, procedeele de adresare a câmpurilor unei variabile de tip înregistrare, sunt cele cunoscute de la Borland Pascal: calificarea individuala cu punct sau calificarea globala cu ajutorul clauzei with astfel:
var
Inreg:<TInregistrare>;
.Inreg . <Nume_Câmp> .
var
Inreg:<TInregistrare>;
with Inreg do
.<Nume_Câmp>.
end
A Putem remarca faptul ca tipul struct din C este echivalent cu tipul record fara parte variabila din Delphi. De asemenea, tipul union din C este echivalent cu tipul record cu lungime variabila din Delphi.
Tipul array
Structurile de tip array pot exista în variante unidimensionale sau multidimensionale. Sintaxa generala pentru declararea unui tip array este urmatoarea:
type
<TArray>=array [<Tip_ordinal_1>,<Tip_ordinal_2>,.,<Tip_ordinal_n>]
of <Tip_element>;
Desi este utilizat în varianta triviala, în care tipurile ordinale dupa care se face indexarea sunt subdomenii ale unor varietati de întregi, tipul array are si posibilitati de indexare dupa alte tipuri ordinale, în functie de particularitatile problemei de rezolvat.
Tipul multime
Cu ajutorul cuvântului rezervat set, se pot defini colectii ordonate de cel mult 256 valori ordinale distincte. Sintaxe de declarare a tipului multime este:
type
<TSet>=set of <Tip_ordinal>;
Declararea variabilelor de tip multime respecta sintaxa cunoscuta:
var
<VSety: <TSet>;
Notatia [ ] desemneaza multimea vida.
Tipul fisier
Un tip file permite controlarea accesului la o secventa liniara de elemente care pot fi de orice tip cu exceptia tipului file si a tipului class. În Delphi, putem declara tipuri de fisiere astfel:
type
<TFile>=file of <Tip_Record>;
sau
<TFile>=file ;
sau
<TFile>=textfile ;
Tipul file of corespunde fisierelor cu structura definita de utilizator din Pascal. În Delphi, tipul file permite tratarea fisierelor la nivel fizic sau nedefint. În sfârsit, tipul textfile este echivalentul tipului text din Pascal.
Asupra problematicii fisierelor în Delphi se va reveni, pe larg, într-un paragraf afectat acestui scop, datorita problemelor deosebite pe care le ridica lucrul eficient cu o structura de tip fisier.
Tipuri speciale
Tipul pointer
Un tip pointer este un tip de data ale carui valori sunt adrese catre variabile ale tipului de baza. Altfel spus, o variabila de tip pointer poate contine adresa din memorie a unei variabile. Sintaxa de declarare a varietatilor de pointeri din Delphi este:
type
<Tip_Pointer_Structurat>= ^ <Tip_Definit_De_Utilizator>;
sau
<Tip_Pointer_Nedefinit>=pointer ;
În Tabelul 2.10 prezentam rutinele specifice lucrului cu pointeri în Delphi.
Rutina |
Descriere |
New |
Aloca memorie (din zona Heap a aplicatiei) unei variabile dinamice, prin intermediul unei variabile pointer. |
GetMem |
Aloca un block de memorie nedefinita (din zona Heap a aplicatiei) unei variabile dinamice, prin intermediul unei variabile pointer. |
Returneaza adresa din memorie a unei variabile, sau adresa punctului de intrare într-o procedura sau functie. |
|
Addr |
La fel ca la operatorul @ |
Assigned |
Verifica daca o variabila de tip procedural are valoarea speciala Nil. |
Ptr |
Converteste o adresa specificata prin <Segment> si <Ofsset) la o variabila pointer. |
Tabelul 2.10 Rutine pentru lucrul dinamic cu memoria
Rolul special al constantei Nil, precum si cerintele care privesc utilizarea corecta a tipului pointer sunt cunoscute de la programarea în Pascal.
Tipuri procedurale
Object Pascal permite tratarea procedurilor si a functiilor ca entitati care pot fi atribuite variabilelor si transmise ca parametri (fapt deosebit de benefic, cel putin în programarea generica). Astfel de actiuni sunt posibile datorita tipurilor procedurale.
Sintaxa de definire a tipurilor procedurale este:
type
<Tip_Procedural>= procedure [(Lista_parametri_formali)]
[of object] [<Conventie_de_apel>];
sau
<Tip_Procedural>= function [(Lista_parametri_formali)]:<Tip_rezultat>
[of object] [<Conventie_de_apel>];
unde <Conventie_de_apel> poate lua una din valorile:.
Conventiile de apel indica: ordinea în care sunt transmisi parametrii de la apelant catre apelat, cui îi apartine responsabilitatea de a descarca stiva de parametri la revenirea din apelat, precum si implicarea sau nu a registrilor CPU în transferul parametrilor.
Parametrii sunt transferati procedurilor sau functiilor prin intermediul registrilor CPU sau prin intermediul stivei, depinde de conventia de apel. Conventia register este singura în care transferul se face prin intermediul registrilor CPU.
Pe de alta parte, conventiile register si pascal sunt singurele în care se efectueaza transmiterea parametrilor de la stânga la dreapta (adica, cel mai din stânga parametru este evaluat si transmis primul si cel mai din dreapta parametru este evaluat si transmis ultimul). Conventiile cdecl, stdcall si safecall transmit parametrii de la dreapta la stânga.
Exceptând conventia cdecl, în toate celelalte eliminarea parametrilor din stiva este realizata de procedurile sau functiile apelate. În cazul conventiei cdecl, parametrii sunt eliminati din stiva de apelant.
Conventia de apel implicita este register.
Revenind, se poate observa ca declararea tipurilor procedurale este asemanatoare declararii antetelor procedurilor sau functiilor, cu deosebirea ca lipseste identificatorul care urmeaza dupa cuvintele cheie procedure sau function la definirea unui antet.
Analiza sintaxei de apel ne arata ca exista doua categorii de tipuri procedurale:
Indicatori de procedura globala
Indicatori de metoda.
AIndicatorii de procedura globala
Corespund unei declaratii de tip procedural în care lipseste clauza of object. Un indicator de procedura globala poate referi o functie sau procedura globala si este specificat ca pointer care pastreaza adresa unei proceduri sau functii globale.
Exemple:
type
TProcedura = procedure;
TSirProc = procedure (const S:string);
TMathFunc = function (X:double):double;
AIndicatori de metoda
Corespund unei declaratii de tip în care este prezenta clauza of object. Un indicator de metoda poate referi o metoda de tip procedura sau functie care apartine unui obiect. Indicatorul de metoda este specificat cu ajutorul a doi pointeri: in primul se pastreaza adresa metodei; în al doilea se pastreaza referinta la obiect.
Exemple:
type
TGenMetoda = procedure of object;
TNotifyEvent=procedure (Sender:TObject) of object;
AValori de tip procedural
O valoare de tip procedural poate fi atribuita unei variabile procedurale. Valori procedurale pot fi:
-Constanta Nil;
-O variabila referinta la un tip procedural;
-Un identificator de procedura sau functie globala;
-Un designator de metoda.
În contextul valorilor procedurale, un identificator de procedura sau functie globala desemneaza o valoare a unui pointer la o procedura globala iar un designator de metoda indica o valoare a unui indicator de metoda.
Exemple:
type
TMainForm=class(TForm)
procedure ButtonClick(Sender:TObject);
.
end
var
MainForm:TMainForm;
MathFunc:TMathFunc;
Onclick :TNotifyEvent;
function Tan(Unghi:double):double;
begin
Result:=Sin(Unghi)/Cos(Unghi);
end;
Variabilelor MathFunc si OnClick li se pot atribui valori astfel:
MathFunc:=Tan;
OnClick:=MainForm.ButtonClick;
situatie în care putem avea apeluri de tipul:
X:=MathFunc(X);
OnClick(Self);
N:=ReadInt;
end
Compilatorul discerne tipul de atribuire dupa tipul variabilei din partea stânga a instructiunii de atribuire. Din pacate exista si situatii în care compilatorul nu poate decide actiunea pe care trebuie sa o întreprinda din analiza contextului. Astfel, în exemplul:
if F=ReadInt
then
Edit1.Text:='Egalitate';
compilatorul nu stie daca trebuie sa compare valorea procedurala a lui F cu valoarea procedurala a lui ReadInt pentru a determina daca F refera ReadInt sau trebuie sa apeleze F si ReadInt pentru a compara valorile returnate.
Sintaxa Object Pascal specifica faptul ca prezenta unui identificator de functie într-o expresie înseamna apelul acelei functii, astfel ca efectul comparatiei din exemplul de mai sus este previzibil. Pentru a cere compararea valorilor procedurale ale identificatorilor F si ReadInt sintaxa obligatorie este:
if @F=@ReadInt
then
Edit1.Text:='Egalitate';
Aplicat unei valori procedurale sau unui identificator de functie sau procedura, operatorul @ previne compilatorul sa nu apeleze procedura si, totodata converteste argumentul caruia i se aplica în pointer. Asadar, @F converteste F într-o variabila pointer fara tip care contine o adresa iar @ReadInt returneaza adresa functiei ReadInt. Cele doua valori pointer pot fi comparate pentru a determina daca F refera ReadInt.
O alta situatie în care putem folosi operatorul @ este prezentata în exemplul de mai jos:
type
TSirComp=function(Sir1,Sir2:PChar):integer;
var
SirComp:TSirComp;
begin
@SirComp:=GetProcAdress(KernelHandle,'istrcmpi');
end
Functia GetProcAdress, definita în Windows API (în WinProcs unit), returneaza adresa unei functii exportate unui DLL ca o valoare pointer fara tip. Utilizând operatorul @, rezultatul apelului functiei GetProcAdress poate fi atribuit variabilei procedurale SirComp.
Remarca
Pentru a consulta adresa de memorie a unei variabile procedurale, deci nu adresa pastrata în ea, se apeleaza la dubla adresare a operatorului @. Astfel ca, daca @P converteste P la o variabila pointer nedefinita, atunci @@P returneaza adresa fizica a variabilei P.
Tipurile variabile
Limbajul Object Pascal introduce, prin intermediul cuvântului cheie variant, posibilitatea de a reprezenta valori al caror tip se modifica dinamic. În timp ce o variabila de orice alt tip este strict dependenta de acel tip, o variabila de tip variant poate primi valori de tipuri diferite, în timpul executiei programului.
Tipul variant are urmatoarele caracteristici:
O variabila de tip variant poate contine: valori întregi, valori reale, siruri de caractere, valori booleene, valori de tip data-si-ora, precum si obiecte OLE. Mai mult, o variabila de tip variant poate contine tablouri de dimensiuni variabile, populate cu elemente de oricare din tipurile mai sus precizate.
Valoarea speciala de tip variant Unassigned este utilizata pentru a indica faptul ca unei variabile de tip variant nu i s-a atribuit, înca, o valoare.
Valoarea speciala de tip variant Null este utilizata pentru a indica o data lipsa sau necunoscuta.
Valorile de tip variant pot fi combinate între ele sau cu variabile statice de tip integer, real, string si boolean în expresii, compilatorul efectuând automat conversiile necesare.
Daca o variabila de tip variant contine un obiect OLE, atunci aceasta poate fi folosita pentru a consulta si seta proprietatile obiectului sau pentru a invoca metodele obiectului.
Variabilele de tip variant sunt întotdeauna initializate ca Unassigned când sunt create pentru prima data. Acest fapt este valabil indiferent daca o variabila de tip variant este globala, locala sau parte a unei structuri de tip tablou, record sau obiect.
Exemplificam, mai jos, modul de utilizarea a tipului variant:
var
V1,V2,V3,V4,V5: variant;
I:integer;
D:double;
S:string;
begin
V1:=1;
V2:=1234.5678;
V3:=' Sir de caractere';
V4:='1000';
V5:=V1+V2+V4;
I:=V1;
D:=V2;
S:=V3;
I:=V4';
S:=V5;
end;
De remarcat, faptul ca desi variabilele de tip variant ofera o mare flexibilitate în manevrarea datelor, ele consuma mai multa memorie decât variabilele obisnuite.
O variabila de tip variant ocupa 16 octeti iar reprezentarea ei interna consta dintr-un cod de tip si o valoare (sau referinta la o valoare) de un anumit tip dat, conform codului de tip. Functia standard VarType returneaza codul de tip al unei variabile de tip variant. În Tabelul 2.11 prezentam o lista partiala a constantelor utilizate pentru identificarea tipului datelor pastrate într- variabila de tip variant, împreuna cu valorile asociate si semnificatia lor.
Constanta |
Valoare |
Semnificatia |
varEmpty |
Variabilei nu i s-a atribuit o valoare; tipul i se cunoaste |
|
varNull |
Variabila are tip necunoscut |
|
varSmallInt |
Întreg cu semn pe 16 biti (SmallInt) |
|
varInteger |
Întreg cu semn pe 32 biti (Integer) |
|
varSingle |
Valoare virgula mobila simpla precizie (Single) |
|
varDouble |
Valoare virgula mobila dubla precizie (Double) |
|
varCurrency |
Valoare virgula mobila de tip Currency |
|
varDate |
Valoare de tip Data si Ora (tipul TDateTime) |
|
varOleStr |
Referinta la un sir OLE (un sir UNICODE alocat dinamic) |
|
varDispatch |
Referinta la un obiect OLE |
|
varError |
$000A |
Cod eroare sistem de operare |
varBoolean |
$000B |
Valoare booleana pe 16 biti (tipul WordBool) |
varVariant |
$000C |
Valori variabile (utilizabila în cazul tablourilor cu elemente variabile) |
varUnknown |
$000D |
Referinta la un obiect OLE necunoscut |
varByte |
Întreg fara semn pe 8 biti (Byte) |
|
varString |
Referinta la un sir de caractere de tip AnsiString alocat dinamic |
|
varTypeMask |
$0FFF |
Masca de biti pentru extragere codului de tip |
varArray |
Bit care indica un tablou de tip variant. |
Tabelul 2.11 Lista partiala a constantelor sistem utilizate pentru controlul continutului variabilelor de tip variant.
Data si ora în Delphi
Tipul TDateTime este folosit de rutinele care permit manipularea informatiilor referitoare la data si ora. Tipul este declarat în unit-ul System astfel:
type TDateTime = type double;
Delphi pastreaza valorile referitoare la data si ora în variabile de tip TDateTime astfel:
Partea întreaga a valorii pastrate în variabila de tip TDateTime reprezinta numarul de zile trecute începând din 30 decembrie 1889.
Partea fractionara a valorii pastrate în variabila de tip TDateTime reprezinta ora.
O parte din procedurile furnizate de unit-ul SysUtils pentru manipularea variabilelor de tip TDateTime sunt:
procedure DateTimeToString ( var NewString: string; const Format:
string; DateTime: TDateTime);
DateTimeToString converteste o variabila de tip TDateTime la un sir de caractere, utilizând un format de conversie. Formatele suportate sunt prezentate la descrierea functiei FormatDateTime.
procedure DateTimeToSystemTime (DateTime:TDateTime; var SystemTime: TSystemTime);
DateTimeToSystemTime converteste data si ora pastrate în format TDateTime în formatul TSystemTime specific interfetei Win32 API.
function DateTimeToStr( DateTime: TDateTime): string;
Daca parametrul DateTime nu contine o valoare referitor la data atunci data afisata este 00/00/00. Daca parametrul DateTime nu contine o valoare referitor la timp, ora afisata este 00:00:00 AM.
Exemplu:
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption := DateTimeToStr(Now);
end
Acest exemplu presupune ca pe forma aplicatiei curente se afla o eticheta (referita de Label1) si un buton asociat cu un eveniment OnClick. La efectuarea unui click pe buton eticheta va arata data si ora curenta a sistemului (parametrul Now).
function DateTimeToFileDate(DateTime: TDateTime): integer;
DateTimeToFileDate converteste o valoare de tip TDateTime la o valoare Data-Timp de tip DOS. Rutinele FileAge, FileGetDate, si FileSetDate opereaza asupra vaorilor Timp-Data specifice DOS (Câmpul Time al tipului TSearchRec din Dos poate contine o valoare Data-Timp de dip DOS).
function DateToStr(Date: TDateTime): string;
Converteste o data de tip TDateTime la un sir de caractere.
Conversia foloseste formatul indicat de variabila globala ShortDateFormat.
Exemplu:
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption := DateToStr(Date);
end
function Date: TDateTime;
Returneaza data curenta în format TDateTime.
Exemplu :
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption := 'Today is ' + DateToStr(Date);
end
Alte functii a caror descriere poate fi gasita cu ajutorul Help-ului Delphi sunt:
function DateTimeToTimeStamp(DateTime: TDateTime): TTimeStamp;
function DayOfWeek(Date: TDateTime): integer;
Operatori si expresii în Delphi
Doar posibilitatea de a reprezenta informatii în memorie în diferite moduri nu rezolva problemele unui program. Un program adevarat utilizeaza a doua capabilitate importanta a unui sistem de calcul exprimata prin puterea de a efectua calcule si transformari asupra datelor. La nivelul limbajelor de programare, componentele care permit valorificarea puterii de calcul a unui sistem de calcul sunt: operatorii, variabilele si constantele. Combinarea acestora, dupa reguli conforme celor invatate la aritmetica sau la logica, duce la realizarea, si în Delphi, a expresiilor. Specificarea expresiilor în Object Pascal, trebuie asadar sa tina cont de ordinea de evaluare a a acestora. Tabloul precedentelor, valabil în Object Pascal, este prezentat în Tabelul 2.12.
Operatori |
Categoria |
^ |
Dereferentiere câmp sau pointer (Precedenta cea mai înalta) |
not |
Operatori unari |
* / div mod as and shl shr |
Operatori multiplicativi si de typecasting |
- or xor |
Operatori conjunctivi(aditivi) |
= <> > < <= >= in is |
Operatori de comparare si apartenenta (Precedenta cea mai joasa. |
Tabelul 2.12 Operatorii Object Pascal grupati pe categorii de precedenta.
Operator |
Semnificatie |
not |
negatia logica asupra variabilelor booleene / inversarea pozitiilor binare ale unei variabile convenabile aplicarii operatorului. |
and |
si logic asupra variabilelor booleene / si logic asupra altor tipuri de operatori convenabili. |
or |
sau logic asupra variabilelor booleene / sau logic asupra altor tipuri de operatori convenabili. |
xor |
sau logic exclusiv asupra variabilelor booleene / sau logic exclusiv asupra altor tipuri de operatori convenabili. |
shl |
Shiftare logica la stânga |
shr |
Shiftare logica la dreapta |
Tabelul 2.13 Operatori la nivel de bit în Object Pascal
Ca în oricare alt limbaj de programare, în Object Pascal instructiunile permit, în ultima analiza, controlarea ordinii de evaluare a expresiilor sau a numarului de treceri peste o expresii cu scopul de a o evalua. Cu ajutorul instructiunilor se reprezinta algoritmul de rezolvare a unei probleme date. Desi acum pare trivial, trebuie sa atragem atentia asupra faptului ca, pentru paradigmele de programare procedural-secventiale, stabilirea unui set minimal de instructiuni pentru reprezentarea structurilor de prelucrare, este un moment-cheie în specificarea unui limbaj de programare.
Oferta Object Pascal în ceea ce priveste reprezentarea instructiunilor de prelucrare se compune din:
-Instructiuni simple;
-Instructiuni structurate.
Instructiuni simple
Instructiunile simple modifica continutul memoriei prin asignarea unei valori, apeleaza o procedura sau o functie sau (ceea ce nu este tocmai în spirit profesional) determina transferarea neconditionata a controlului executiei unui program la o instructiune oarecare a programului. Instructiunile simple în Object Pascal sunt:
-Instructiunea de atribuire;
-Apelul de subrutina;
-Instructiunea goto;
Instructiunea de atribuire
Sintaxa Object Pascal pentru o instructiune de atribuire este:
<Identificator_Variabila>:=<Expresie>;
Toate consideratiile care se fac în Pascal pe marginea acestei instructiuini sunt valabile si în Object Pascal. Evident, apar o serie de observatii legate de introducerea de tipuri de date noi, conversia acestora si rezolvarea automata a problemelor de compatibilitate la atribuiri. Iata un exemplu de situatie simpla în care atentia programatorului trebuie sa fie încordata: un caracter poate fi întotdeauna atribuit unei variabile sir; un sir de caractere nu poate fi atribuit unei variabile de tip caracter.
Apelul de subrutina
Un apel de subrutina determina transferul controlului executiei programului catre o procedura, functie sau metoda de prelucrare,executia blocului de instructiuni aferent, urmata de revenirea si continuarea executiei cu instructiunea carea urmeaza apelului de subrutina. Sintaxa unui apel de subrutina se circumscrie regulilor cunoscute deja de la studiul limbajului Pascal.
Instructiunea goto
Desi controversta, mai ales din perspectiva principiilor programarii structurate, instructiunea goto are drept de cetate si în Object Pascal. Se cunoaste faptul ca, de exemplu, si limbajul C, specifica posibilitatea utilizarii instructiunii goto. Recomandarea valabila în orice limbaj de programare este sa nu se abuzeze de utilizarea acestei instructiuni, deoarece, în caz contrar, calitatea programului are de suferit.
Instructiuni structurate
Cu ajutorul instructiunilor structurate, putem grupa prelucrarile simple sau compuse în conformitate cu cerintele de moment, putem ramifica prelucrarile în functie de valoarea anumitor conditii logice, putem executa în mod repetat anumite prelucrari. Adica, pot fi reprezentate structurile fundamentale de prelucrare.
Oferta Object Pascal pentru reprezentarea structurilor fundamentale de prelucrare este urmatoarea:
-Instructiunea compusa;
-Instructiunile conditionale (if, case);
-Instructiunile repetitive (for, while, repeat);
-Instructiunea with.
Instructiunea compusa
Instructiunile compuse specifica o ordine în care instructiunile, pe care le contin, trebuie executate. Daca secventa de instructiuni este delimitata de begin si end, atunci întreaga secventa poate fi tratata ca o instructiune si utilizata ca atare în constructiile sintactice Object Pascal care o permit.
Instructiuni conditionale
AInstructiunea if
Sintaxa instructiunii if este:
if <Expresie>
then
<Instructiune_1>
[else
<Instructiune_2>];
<Expresie> trebuie sa returneze un rezultat de tip boolean. Daca <Expresie> returneaza TRUE, atunci va fi executata <Instructiune_1>, care urmeaza clauze then. Daca <Expresie> returneaza FALSE si clauza else este prezenta, atunci se executa <Instructiune_2> care urmeaza clauzei else. Daca <Expresie> returneaza FALSE si clauza else lipseste, atunci se executa instructiunea care urmeaza dupa instructiunea if, privita ca întreg. <Instructiune_1> si <Instructiune_2> pot fi simple sau compuse.
AInstructiunea case
Sintaxa instructiunii case este:
case <Selector> of
<Val_Sel_1>: <Instructiune_1>;
<Val_Sel_2>: <Instructiune_2>;
:
<Val_Sel_n>: <Instructiune_n>
end;
sau
case <Selector> of
<Val_Sel_1>: <Instructiune_1>;
<Val_Sel_2>: <Instructiune_2>;
:
<Val_Sel_n>: <Instructiune_n>
else
<Instructiune>
end;
Instructiunea case permite executia instructiunii prefixate de o constanta egala cu valoarea variabilei selector sau de un domeniu care contine valoarea variabilei selector. De remarcat faptul ca, spre deosebire de implementarea Pascal a instructiunii case, implementarea Object Pascal nu permite intersectii nevide între constantele care prefixeaza instructiunile într-un case. Daca nici o constanta-prefix nu este egala cu valoarea variabilei selector, atunci se va executa instructiunea asociata clauzei else, daca aceasta este prezenta, sau instructiunea care urmeaza instructiunii case în caz contrar. <Instructiune_1>,.,<Instructiune_n> pot fi simple sau compuse.
Exemple:
case Operator of
Plus: X := X + Y;
Minus: X := X - Y;
Times: X := X * Y;
end
sau
case I of
0, 2, 4, 6, 8: Edit1.Text := 'Cifra para';
1, 3, 5, 7, 9: Edit1.Text := 'Cifra impara';
10..100: Edit1.Text := 'Intre 10 si 100';
else
Edit1.Text := 'Negativ sau mai mare decat 100';
end
sau
case MySelector of
5: Edit1.Text := 'Caz special';
1..10: Edit1.Text := 'Caz general';
end
Instructiuni repetitive
ARepetitiva cu numar cunoscut de pasi
Pentru reprezentarea secventelor repetitive cu numar cunoscut de pasi în Object Pascal, la fel ca în Pascal, avem la dispozitie instructiunea cu sintaxa generala:
for <Contor>:=<Val_Inceput> to <Val_Sfarsit> do
<Instructiune>;
sau
for <Contor>:=<Val_Inceput> downto <Val_Sfarsit> do
<Instructiune>;
<Instructiune> poate fi simpla sau compusa. Se mai numeste si corpul repetitivei.
<Contor> este o variabila de tip ordinal care va lua la fiecare trecere corpul repetitivei valorile cuprinse între <Val_Inceput> si <Val_Sfârsit>, ascendent sau descendent, dupa cum este prezenta clauza to sau clauza downto. Nu avem comentarii deosebite de facut fata de semantica Pascal a instructiunii.
ARepetitive cu numar necunoscut de pasi
Pentru reprezentarea repetitivelor cu numar necunoscut de pasi la care se prefera conditionarea anterioara avem sintaxa:
while <Expresie> do
<Instructiune>;
<Instructiune> poate fi simpla sau compusa.
Semantica instructiunii este imediata: cât timp în urma evaluarii expresiei <Expresie> se obtine TRUE, se va executa corpul repetitivei. În caz contrar, se preda controlul primei instructiuni care urmeaza dupa instructiunea while.
Instructiunea while este preferata atunci când o anumita secventa de instructiuni poate fi executata niciodata sau de mai multe ori.
Pentru reprezentarea repetitivelor cu numar necunoscut de pasi la care se prefera conditionarea posterioara avem sintaxa:
repeat
<Instructiune>
until <Expresie>;
<Instructiune> poate fi simpla sau compusa.
Semantica instructiunii este imediata: cât timp în urma evaluarii expresiei <Expresie> se obtine FALSE, se revine la executia corpului repetitivei. În caz contrar, se preda controlul primei instructiuni care urmeaza dupa instructiunea repeat.
Instructiune repeat este preferata atunci când o anumita secventa de instructiuni poate fi executata cel putin odata.
Instructiunea with
Instructiunea with este utilizata pentru simplificarea dereferentierii câmpurilor unor variabile record si a membrilor unui obiect. Astfel, în Object Pascal este foarte frecvent întâlnita o situatie de genul:
procedure TForm1.Button1Click(Sender: TObject);
begin
ListBox1.Clear;
ListBox1.MultiSelect := True;
ListBox1.Items.Add('One');
ListBox1.Items.Add('Two');
ListBox1.Items.Add('Three');
ListBox1.Sorted := True;
ListBox1.Font.Style := [fsBold];
ListBox1.Font.Color := clPurple;
ListBox1.Font.Name := 'Times New Roman';
ListBox1.ScaleBy(125, 100);
end
Daca programatorul utilizeaza instructiunea with secventa de cod de mai sus va arata astfel:
procedure TForm1.Button1Click(Sender: TObject);
begin
with ListBox1 do
begin
Clear;
MultiSelect := True;
Items.Add('One');
Items.Add('Two');
Items.Add('Three');
Sorted := True;
Font.Style := [fsBold];
Font.Color := clPurple;
Font.Name := 'Times New Roman';
ScaleBy(125, 100);
end;
end
O utilizare similara este posibila si în cazul variabilelor record.
2.6 Proceduri si functii în Object Pascal
Introduse în Pascal ca suport pentru modularizare si abstractizare, procedurile si functiile joaca acelasi rol si în Object Pascal. Toate mentiunile Pascal referitoare la proceduri si functii sunt în vigoare si în Object Pascal. O imagine mai precisa asupra semanticii procedurilor si functiilor în Object Pascal o putem obtine urmarind diagramele de sintaxa de mai jos.
Declararea unei proceduri
Antet procedura
Declararea unei functii
Antet functie
Bloc subrutina
Din analiza sumara a diagramelor de sintaxa, rezulta o serie de particularitati Object Pascal în utilizarea procedurilor si a functiilor. Aceste particularitati se refera la posibilitatea de a alege, în functie de context, conventia de apel, precum si la protocolul de utilizare a directivelor externe în cazul în care procedurile sau functiile fac parte din potentialul de calcul al bibliotecilor de legaturi dinamice (DLL). Deocamdata, sa mai mentionam un amanunt care nu transpare din analiza diagramei de sintaxa a functiei.
Pentru a returna prin nume o valoare de un anumit tip, în sectiunea executabila a unei functii trebuie sa apara o atribuire de tipul:
<Nume_Functie>:=Result;
Variabila Result este creata automat în corpul unei functii Object Pascal, având tipul acesteia.
Precizarile care se refera la vizibilitatea variabilelor în blocurile procedurale, precum si la transmiterea parametrilor între <apelat> si <apelant> sunt similare celor cunoscute de la programarea în Pascal.
2. 7 Unit-uri Object Pascal
Structura de principiu a unui unit Object Pascal este:
ANTET |
unit <Nume unitate>; |
SECŢIUNEA DE INTERFAŢĂ |
interface [uses <Lista alte unitati> <Declaratii globale> <Lista de functii si proceduri globale>] |
SECŢIUNEA DE IMPLEMENTARE |
implementation [uses <Lista unitati utilizate> <Declaratii locale> <Implementare proceduri si functii >] |
SECŢIUNEA DE INIŢIALIZARE |
[initialization <Secventa de initializarea unit-ului>] |
SECŢIUNEA DE FINALIZARE |
[finalization <Sectiunea de finalizare a unit-ului>] |
end. |
Analiza structurii de mai sus permite urmatoarele aprecieri:
Sectiunea de interfata a unitatii este destinata declararii acelor resurse care urmeaza sa fie exportate catre alte programe sau unit-uri (constante, tipuri, variabile, proceduri,functii);
Sectiunea de implementare este portiunea din unit în care apare codul complet al unitatilor de prelucrare exportate, precum si codul unor unitati de prelucrare de interes local, daca este cazul.
Sectiunea de initializare a unit-ului este sectiunea în care apare, optional, codul care realizeaza initializarea mediului în care urmeaza sa lucreze capabilitatile unit-ului. Acest cod este executat la începerea executiei programului, deci înainte de a se preda controlul instructiunilor programului principal. Daca sunt mai multe unit-uri care au secvente de initializare, acestea se vor executa în ordinea în care sunt declarate unit-urile în lista asociata clauzei uses.
Sectiunea de finalizare, o noutate Object Pascal, în materie de modularizare a aplicatiilor în context Delphi, este utilizata pentru a permite o serie de prelucrari specifice terminarii apelului la resursele unui unit. Aceasta sectiune este optionala, dar poate apare numai în conditiile în care exista si o secventa de initializare. Instructiunile care urmeaza cuvântului cheie finalization sunt executate la terminarea programului. Ne putem imagina urmatorul scenariu plauzibil pentru utilizarea celor doua sectiuni: toate resursele alocate sau deschise în secventa de initializare (memorie, fisiere,etc.) sunt eliberate sau închise în sectiunea de finalizare. De asemenea, secventa de finalizare poate elibera orice resursa necesara pentru executia normala a unit-ului însusi. Daca sunt mai multe unit-uri care au secvente de finalizare, acestea se vor executa în ordinea inversa în care apar în unit-urile în lista care face obiectul clauzei uses.
Asadar, programarea orientata pe unit-uri presupune abilitatea programatorului de a specifica resurse statice generice (constante, tipuri, variabile) si, mai ales, abilitatea de a specifica unitati de prelucrare cu interfata eficienta si stabila. Daca exista astfel de abilitati, atunci codul obtinut este fiabil, rezistent la modificari si versatil. La nevoie, datorita localizarii indusa de abstractizare, modificarile se fac cu minim de efort.
Unit-urile ofera pentru programator urmatoarele avantaje:
Sunt pastrate în format binar, ceea ce înseamna scurtarea timpului de generare a fisierelor executabile;
Pot fi utilizate ca suport pentru promovarea încapsularii acelor resurse care sunt critice pentru existenta aplicatiei (Se opereaza o distinctie clara între ceea ce trebuie vazut din afara unit-ului si ceea ce este de interes local acestuia);
Constituie o baza a promovarii abstractizarii, în sensul ca pot exista doua unitati cu aceeasi interfata dar cu implementari diferite, înlocuirea unei unitati cu alta nefiind problematica din punct de vedere sintactic.
Referitor la utilizarea unit-urilor, adaugam urmatoarele precizari:
<Nume unitate> este identificatorul unit-ului si trebuie sa coincida cu numele fisierului în care este definit acesta. De remarcat faptul ca unit-urile folosite la un moment dat trebuie sa aiba nume diferite.
<Lista alte unitati> reprezinta lista altor unitati folosite de catre unitatea curenta. Nu se permit referinte circulare.
<Declaratii globale> indica declaratiile de constante, tipuri,variabile,etc. vizibile atât în cadrul unit-ului curent cât si în toate unitatile si programele care îl utilizeaza.
<Lista de functii si proceduri globale> specifica antetele functiilor si/sau procedurilor declarate ca vizibile în unit si în toate unitatile si programele care îl utilizeaza.
<Lista unitati utilizate> reprezinta lista altor unitati utilizate de catre unitatea curenta, dar necesare doar partii de implementare. Sunt permise referinte circulare între unitati.
<Declaratii locale> permite specificarea unor constante, variabile, etc. necesare doar partii de implementare, deci invizibile pentru alte unitati sau programe.
<Implementare proceduri si functii> ocazioneaza implementarea procedurilor si functiior ale caror antete au fost anuntate în interface ,precum si a altor proceduri si functii necesare partii de implementare.
|