clase si program are c++ builder

48
Lecţia 1 Conţinut - Un tur rapid al C++Builder; - Modul de scriere al aplicaţiilor de consolă Win32; - O introducere în limbajul C++; - Variabilele şi tipurile de date C++; - Introducere în utilizarea funcţiilor C++; - Utilizarea masivelor de date (vectori şi matrici); 1. Un tur rapid al C++Builder Pentru moment, nu vom acorda decât o privire rapidă mediului de dezvoltare C++Builder, urmând ca în lecţia a şasea să examinăm în detaliu acest IDE. Atunci când pornim pentru prima oară IDE-ul C++Builder ni se prezintă mediul de lucru C++Builder în care este deschisă o formă nouă, fără conţinut, ca în figura 1.1. (forma este unul dintre elementele de interfaţă vizuală, practic o fereastră de uz general pentru o aplicaţie oarecare). Figura 1.1

Upload: crestronik

Post on 05-Jul-2015

636 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Clase Si Program Are C++ Builder

Lecţia 1Conţinut

- Un tur rapid al C++Builder;- Modul de scriere al aplicaţiilor de consolă Win32;- O introducere în limbajul C++;- Variabilele şi tipurile de date C++;- Introducere în utilizarea funcţiilor C++;- Utilizarea masivelor de date (vectori şi matrici);

1. Un tur rapid al C++Builder

Pentru moment, nu vom acorda decât o privire rapidă mediului de dezvoltare C++Builder, urmând ca în lecţia a şasea să examinăm în detaliu acest IDE.

Atunci când pornim pentru prima oară IDE-ul C++Builder ni se prezintă mediul de lucru C++Builder în care este deschisă o formă nouă, fără conţinut, ca în figura 1.1. (forma este unul dintre elementele de interfaţă vizuală, practic o fereastră de uz general pentru o aplicaţie oarecare).

Figura 1.1

IDE-ul C++Builder este împărţit în trei părţi. Fereastra superioară poate fi considerată partea principală a IDE-ului. Pe lângă meniul principal ea conţine şi bara de butoane cu cele mai folosite operaţii în stânga şi selectorul de componente utilizabile în dreapta. (vezi figura 1.2).

Figura 1.2.

Page 2: Clase Si Program Are C++ Builder

Pentru o mai uşoară regăsire, componentele sunt împărţite în tipuri de componente, fiecare tip având un tab în paleta de componente. Pentru a utiliza o componentă, este suficient să o selectăm în paletă după care să dăm click pe forma pe care dorim să amplasăm componenta, la poziţia dorită. O componentă este o bucată de cod software care va îndeplini în aplicaţie o anume funcţie predefinită (cum ar fi o etichetă, un câmp de editare sau o listă).Cea de-a doua parte a IDE-ului C++Builder este inspectorul de obiecte (Object Inspector) care este amplasat în mod implicit în stânga ecranului. Prin intermediul inspectorului de obiecte vom modifica proprietăţile componentelor şi modul cum sunt tratate evenimentele referitoare la ele (interacţiunile utilizatorului cu componenta respectivă). În inspectorul de obiecte apare întotdeauna lista de proprietăţi a componentei curent selectate, dublată de lista de evenimente care pot afecta componenta respectivă, dar mai poate apărea (dacă este selectată) şi ierarhia de componente a aplicaţiei.În dreapta inspectorului de obiecte este spaţiul de lucru al C++Builder (cea de-a treia parte). Iniţial în acest spaţiu este afişat editorul de forme. Acesta este utilizat pentru a amplasa, muta sau dimensiona diverse componente ca parte a creării formelor aplicaţiei. În spatele editorului de forme se află parţial ascunsă fereastra editorului de cod de program (locul în care vom scrie cod pentru programele noastre).

Să încercăm o primă aplicaţie practică.În acest moment, C++Builder este pornit şi avem la dispoziţie o formă fără conţinut. În mod implicit, acestă formă este denumită Form1. Inspectorul de obiecte afişează proprietăţile referitoare la ea. Selectaţi proprietatea Caption din lista de proprietăţi a formei şi tastaţi un titlu pe care doriţi să-l daţi ferestrei de aplicaţie reprezentate de Form1.Observaţi că pe măsură ce tastaţi, titlul ferestrei este modificat (veţi observa acest comportament şi la alte componente).Pentru a rula aplicaţia proaspăt obţinută putem apăsa pe butonul Run de pe bara de unelte (cel pe care este desenată o săgeată verde) sau putem apela opţiunea Run din meniul Run sau putem apăsa tasta F9 (care este un shortcut către opţiunea precedentă). La folosirea oricăreia din modalităţile de mai sus, IDE-ul va răspunde prin afişarea unui ferestre de stare conţinând informaţii referitoare la procesul de compilare, ca în figura 1.3. (procesul de obţinere a codului executabil al aplicaţiei).

Figura 1.3

Dupa scurt timp, fereastra de stare a compilarii, dispare, apare forma pe care am lucrat pana acum, de data aceasta fiind executata, iar titlul ei este cel pe care l-am introdus mai sus, vezi figura 1.4.

Page 3: Clase Si Program Are C++ Builder

Figura 1.4

Revenim la modul editare inchizand aplicatia executata (click pe butonul de inchidere al formei).Pentru a putea adauga un prim element functional acestei forme vom adauga o eticheta cu un text oarecare pe forma noastra. Pentru aceasta, in Tab-ul Standard al paletei de componente, dam click pe componenta Label (butonul cu un A mare pe el). Dati din nou click pe forma, la pozitia la care doriti sa amplasati eticheta. Dupa amplasarea acesteia, observam ca ea apare in ierahia de obiecte ale aplicatiei (daca ierarhia este vizibila) si ca proprietatile etichetei sunt listate in Inspectorul de obiecte. Selectati proprietatea Caption si modificati-o pentru a modifica textul afisat de eticheta. Pentru a modifica si modul in care este afisat textul, dam dublu-click pe proprietatea Font din aceeasi lista (se va deschide o sublista cu proprietati suplimentare legate de aspectul si tipul fontului folosit). Cautati in sublista proprietatea Size (este curent setata la 8) si modificati-o la 24. Dupa ce confirmati noua dimensiune a fontului apasand Enter, ea va fi aplicata etichetei respective.Putem modifica si pozitia etichetei in mod simplu, dand click pe ea si tragand-o pe noua pozitie.Dupa toate aceste modificari putem rula din nou programul (cum am facut mai sus). Rezultatele vor fi asemanatoare cu cele din figura 1.5.

Page 4: Clase Si Program Are C++ Builder

Figura 1.5

Pentru etapa urmatoare a acestei lectii vom inchide proiectul pe care am lucrat pana acum. Pentru aceasta vom apela optiunea Close All din meniul File (vom fi intrebati daca dorim sa salvam proiectul respectiv si daca da, sub ce nume si unde...).

2. O aplicatie de consola Win32

Pentru inceput vom incerca sa invatam elementele de baza ale limbajului C++. Programele de mici dimensiuni pe care le vom utiliza in acest scop sunt cel mai simplu de realizat ca programe de consola (programe care nu au nevoie de o interfata grafica Windows). E de remarcat ca programele de consola Win32 (se numeste asa pentru ca vorbim de o versiune de Windows pe 32 de biti ...) arata exact la fel cu cele de DOS (diferentele dintre ele neavand absolut nicio legatura cu aspectul).Din meniul File alegem optiunea New->Other. O fereastra de dialog va fi afisata si ea va contine tipurile de noi programe sau componente pe care le putem crea (colectia respectiva se numeste Object Repository) pe baza unor modele predefinite. Dublu click pe optiunea Console Wizard pentru a porni un nou proiect de aplicatie de consola. O fereastra de dialog continand optiunile de baza ale noii aplicatii de consola va fi afisata. Optiunile implicite (C++ code, console application) ne convin drept pentru care nu le vom schimba (vezi figura 1.6).

Figura 1.6

Page 5: Clase Si Program Are C++ Builder

Observam ca spre deosebire de aplicatia precedenta nu mai avem la dispozitie nicio forma, ci numai editorul de cod, ca in figura 1.7.

Figura 1.7

Pe langa absenta editorului de forme vom observa si ca Inspectorul de obiecte nu afiseaza nimic (el este activ doar atunci cand exista componente vizuale la care sa se refere – il putem chiar inchide atunci cand scriem aplicatii de consola, fiind inutil). Pentru a redeschide ulterior Inspectorul de obiecte putem apela optiunea Object inspector din meniul view sau putem apasa F11.La deschiderea noului proiect, codul afisat al aplicatiei este urmatorul:

//---------------------------------------------------------------------------#include <vcl.h>#pragma hdrstop//---------------------------------------------------------------------------#pragma argsusedint main(int argc, char* argv[]){ return 0;}//---------------------------------------------------------------------------

Programul respectiv nu face nimic, dar este un program valid.

3. O introducere în limbajul C++

Page 6: Clase Si Program Are C++ Builder

Liniile care incep cu // sunt linii de comentarii (observati modul in care au fost folosite linii de comentarii pentru a imparti programul C++ in cele doua sectiuni majore, cea de declaratii si cea de cod direct executabil).Observati si faptul ca singura linie de cod executabila (cea care returneaza rezultatul functiei main) este terminata cu ; (regulile sunt aceleasi ca in C-ul simplu).De asemenea observati acoladele de la inceputul si sfarsitul functiei main (ele au rolul de a marca inceputul si sfarsitul codului unei functii sau al unei secvente de linii executabile).Este inclusa si o biblioteca de functii (vcl.h care contine definirea catorva functii si tipuri pentru lucrul cu componente vizuale, VCL = Visual Component Library)Putem adauga la acest schelet de program pus la dispozitie de C++Builder codul necesar pentru a ajunge la o aplicatie de consola completa.Una dintre cele mai utilizate biblioteci in aplicatiile de consola C++ este iostream.h. Ea se bazeaza pe utilizarea de streamuri pentru a efectua operatii de baza de intrare si iesire. Streamul cout este utilizat pentru a trimite date catre iesirea standard (in mod implicit monitorul). Streamul cin este utilizat pentru a prelua date de la intrarea standard (in mod implicit tastatura). Iostream implemenetaza doi operatori pentru a insera informatii intr-un stream (<<) si respectiv pentru a extrage informatii dintr-un stream (>>).Spre exemplu, pentru a afisa ceva intr-o aplicatie de consola am putea utiliza intr-un program urmatoarea linie de cod:

cout << “Bine ati venit!”;

Această linie de cod spune programului să insereze textul Bine ati venit! în streamul standard de ieşire, adică pe ecranul monitorului.Observaţie. cout nu poate fi utilizat decât în aplicaţiile de consolă. În aplicaţiile cu interfaţă grafică Windows există două funcţii standard pentru afişare de text: DrawText() şi TextOut() (ele nu fac oricum obiectul acestei lecţii).Pentru a folosi cout trebuie inclusă biblioteca care îl declară (#include<iostream.h>).Dacă am uitat să facem acest lucru, la încercarea de a rula aplicaţia vom obţine o eroare de compilare (Undefined symbol ‘cout’). Pentru a afla de unde provine o anumită funcţie sau un anumit tip, putem da click pe numele funcţiei sau tipului şi apăsa F1. La apăsarea tastei F1 va apărea textul de ajutor referitor la funcţia sau tipul respectiv, incluzând fişierul bibliotecă în care acesta a fost declarat.În iostream.h există de asemenea elemente de modificare a modului în care un stream este tratat. Pentru moment, vom lucra cu endl, care desemnează începutul unei noi linii în streamul de ieşire.Acum putem scrie o primă aplicaţie care să afişeze un mesaj. Urmăriţi listingul de mai jos:

//---------------------------------------------------------------------------#include <vcl.h>#include <iostream.h> // am adãugat aceastã linie#pragma hdrstop//---------------------------------------------------------------------------#pragma argsusedint main(int argc, char* argv[]){ cout << "Salutare!" << endl; // am adãugat aceastã linie return 0;

Page 7: Clase Si Program Are C++ Builder

}//---------------------------------------------------------------------------Observaţie. Spaţiile inserate în text, atât timp cât nu rup un cuvânt, nu au nicio influenţă. Spre exemplu bucata de cod urmatoare:

int main(int argc, char **argv){cout << “Salutare!”;return 0;}

este acelaşi lucru cu:int main(int argc,char** argv){cout<<“Salutare!”;return 0;}

Pentru a rula programul, folosim aceeaşi opţiune ca mai devreme. La execuţie va apărea o fereastră de consolă şi în ea va fi afişat mesajul dorit, după care fereastra respectivă va fi închisă imediat. Acest lucru se datorează faptului că aplicaţia şi-a terminat execuţia, iar fereastra de consolă care a găzduit-o se va închide imediat după terminarea aplicaţiei.Pentru a împiedica acest lucru, mai adăugăm încă o linie de cod care să aştepte apăsarea unei taste. Vom utiliza funcţia getch() din biblioteca conio.h (funcţii de intrare-ieşire pentru consolă), precum în exemplul următor:

//---------------------------------------------------------------------------#include <vcl.h>#include <iostream.h>#include <conio.h> // am adãugat aceastã linie#pragma hdrstop//---------------------------------------------------------------------------#pragma argsusedint main(int argc, char* argv[]){ cout << "Salutare!" << endl; cout << "Apasati orice tasta pentru a continua..."; // am adãugat aceastã linie getch(); // am adãugat aceastã linie return 0;}//---------------------------------------------------------------------------

De data aceasta aplicaţia rulează, afişează mesajul dorit şi fereastra de consolă rămâne vizibilă până la apăsarea unei taste.Acesta a fost un prim exemplu de aplicaţie de consolă. Mai departe vom încerca să înţelegem alte elemente ale limbajului C++.

4. Variabilele şi tipurile de date C++;

Pentru început, e bine să menţionăm că nu vom face o prezentare extensivă a limbajului C++. Pentru acest lucru, este necesară consultarea altor lucrări dedicate.

Page 8: Clase Si Program Are C++ Builder

VariabileO variabilă este o porţiune de memorie, identificată printr-un nume şi destinată stocării datelor de un anumit tip. Variabilele sunt utilizate pentru manipularea datelor în memorie. Un exemplu de utilizarea a variabilelor intr-un program este următorul:

int x; // variabila de tip intregx = 100; // ‘x’ contine acum valoarea 100x += 50; // la valoarea lui ‘x’ se adauga 50, devenind 150int y = 150; // se declara si se initializeaza cu valoarea 150 variabila ‘y’x += y; // la valoarea lui ‘x’ se adauga valoarea lui ‘y’, devenind 300x++; // la valoarea lui ‘x’ se adauga 1, devenind 301

Variabilele care sunt declarate, dar nu sunt iniţializate, vor conţine valoarea conţinută până atunci în zona de memorie respectivă (la iniţializarea calculatorului, până la utilizare, locaţiile de memorie sunt iniţializate cu 0, după utilizare, o locaţie de memorie este doar declarată liberă, nu şi reiniţializată cu 0, drept pentru care la o reutilizare, ea va conţine valoarea “moştenită” de la utilizarea anterioară, chiar dacă nu mai are aceeaşi semnificaţie). Din acest motiv, nu este posibil să ştim ce conţine o variabilă care a fost declarată, dar nu şi iniţializată. Un exemplu de fragment de cod defectuos din acest punct de vedere este următorul:

int x;int y;x = y + 10; // gresit, pentru ca nu ma pot baza pe faptul ca y are valoarea 0 (sau orice alta valoare la care m-as astepta)

Numele de variabile pot fi o combinaţie de majuscule, minuscule, cifre şi underscore (_). Nu pot conţine alte caractere (caractere speciale şi spaţiu). Nu pot începe cu o cifră. Numele de variabilă care încep cu underscore sunt de obicei folosite pentru variabile cu destinaţii speciale. Lungimea maximă a unui nume de variabilă depinde de la compilator la compilator, dar implementările standard au de obicei lungime maximă de 31 de caractere (ceea ce este oricum prea mult pentru un nume de variabilă folosit curent).

Tipuri de date C++

Un tip de date specifica modul in care informatia va fi stocata (reprezentata) in memorie, intr-o variabila. In C++ este necesara specificarea tipului de date care va fi utilizat la declararea unei variabile. Exemple de declaratii posibile intr-un program:

int x1 = -1;int x = 1000;float y = 3.14;long z = 457000;

Page 9: Clase Si Program Are C++ Builder

Aceasta specificare permite compilatorului sa faca verificari de tip la compilare si pe pracurusul rularii programului. Utilizari improprii ale tipurilor de date vor duce la aparitia de erori sau avertismente care pot fi analizate si corectate la timp. Anumite tipuri de date (cele numerice intregi) pot fi declarate ca fiind cu semn (signed – pot contine si valori negative) sau fara semn (unsigned – pot contine numai valori pozitive). Tabelul 1.1 specifica cateva tipuri de date folosite curent in C++ impreuna cu caracteristicile lor:

Tip de date Memorie ocupata (in octeti)

Domeniu de valori

char 1 -128 to 126 unsigned char 1 0 to 255 short 2 -32,768 to 32,767 unsigned short 2 0 to 65,535 long 4 -2,147,483,648 to

2,147,483,648 unsigned long 4 0 to 4,294,967,295

int 4 la fel ca long (atentie, difera de C-ul clasic)

unsigned int 4 la fel ca unsigned long (idem)

float 4 1.2E-38 to 3.4E381 double 8 2.2E-308 to 1.8E3082 bool 1 true sau false

Observatie. Intre tipurile de date considerate a fi partial compatibile se pot face conversii. Spre exemplu se poate da o valoare fractionara unei variabile de tip intreg dar aceasta va retine numai partea intreaga a numarului respectiv:

int x = 3.75; // va avea ca rezultat darea valorii 3 lui ’x’

C++ va face conversii implicite intre diferitele tipuri de date de cate ori este posibil. Un alt exemplu de conversie implicita (desi cu rezultate nedorite) este urmatorul:

short result;long num1 = 200;long num2 = 200;result = num1 * num2; //rezultatul este teoretic 40000 dar short are valoarea maxima 32767 drept pentru care rezultatul va fi o valoare negativa, -25,536 (o ia de la inceput cu „baleierea” domeniului de short)Pentru a vedea practic ce se intampla intr-un astfel de caz putem incerca programul de mai jos:

//---------------------------------------------------------------------------#include <vcl.h>#include <iostream.h>#include <conio.h>

Page 10: Clase Si Program Are C++ Builder

#pragma hdrstop

//---------------------------------------------------------------------------#pragma argsusedint main(int argc, char* argv[]){ short x = 32767; //x ia valoarea 32767 care este maximul pentru tipul short cout << "x = " << x << endl; x++; //la valoarea lui x mai adaug 1, noua valoare a lui x va fi -32768 cout << "x = " << x << endl; getch(); return 0;}//---------------------------------------------------------------------------

Desigur, pentru un program ideal construit ar trebui sa utilizam tipul de date cel mai potrivit pentru fiecare variabila dar in marea majoritate a aplicatiilor nu foarte pretentioase putem folosi int ca tip generic pentru numere intregi.

In anumite cazuri compilatorul nu reuseste sa realizeze conversia automata intre doua tipuri de date diferite caz in care vom primi un mesaj de eroare de genul „Cannot convert from X to Y” (unde X si y sunt tipurile de date implicate). De asemenea putem primi, in locul unui mesaj de eroare un avertisment de tipul „Conversion may lose significant digits” (prin conversie se vor pierde cifre semnificative). In orice caz, o buna programare presupune obtinerea de programe care nu numai ca nu au erori (adica vor rula) dar si care nu vor avea avertismente (vor duce la rezultatele urmarite). Din acest punct de vedere, avertismentele, desi nu opresc executia programului, e bine sa fie tratate asemeni erorilor, adica eliminate.

Operatori C++

Operatorii sunt utilizati pentru a manipula datele. Ei pot efectua calcule, verifica relatia intre doua valori, manipula variabile precum si alte operatii. In continuare prezentam lista celor mai cunoscuti operatori din C++ (tabelul 1.2):

Operator Descriere Exemplu

Operatori matematici+ Adunare x = y + z; – Scadere x = y - z; ∗ Inmultire x = y * z; / Impartire x = y / z;

Operatori de atribuire= Atribuire x = 10; += Atribuire si adunare x += 10; (same as x = x + 10;)

Page 11: Clase Si Program Are C++ Builder

-= Atribuire si scadere x -= 10; *= Atribuire si inmultire x *= 10; \= Atribuire si impartire x \= 10; &= Atribuire si SI la nivel de biti x &= 0x02; |= Atribuire si SAU la nivel de biti x |= 0x02; Operatori logici&& SI logic if (x && 0xFF) {...} || SAU logic if (x || 0xFF) {...}

Operatori de comparatie== Egal cu if (x == 10) {...}!= Diferit de if (x != 10) {...}< Mai mic ca if (x < 10) {...}> Mai mare ca if (x > 10) {...}<= Mai mic sau egal cu if (x <= 10) {...} >= Mai mare sau egal cu if (x >= 10) {...}

Operatori unari * Operator de indirectare int x = *y; & Operator de adresare int* x = &y; ~ Negatie la nivel de biti x &= ~0x02; ! Negatie logica if (!valid) {...} ++ Operator de incrementare x++; (same as x = x + 1;) -- Operator de decrementare x--;

Operatori de clase si structuri:: Precizare a tintei MyClass::SomeFunction(); -> Apartenenta indirecta myClass->SomeFunction(); . Apartenenta directa myClass.SomeFunction();

Dupa cum vedem, lista de operatori este destul de lunga. Deprinderea lor se va face incet, incet pe masura ca vom inainta in invatarea limbajului C++.O observatie interesanta se refera la operatorii de incrementare si decrementare al caror efect difera partial in functie de pozitia in care sunt aplicati (inainte sau dupa variabila) precum in portiunea de program urmatoare:

int x = 10;cout << “x = “ << x++ << endl;//il afiseaza pe x dupa care il incrementeazacout << “x = “ << x << endl;//il afiseaza din nou pe xcout << “x = “ << ++x << endl;//il incrementeaza pe x inainte de a il afisacout << “x = “ x << endl; //il afiseaza din nou pe x

Page 12: Clase Si Program Are C++ Builder

Efectul executiei codului intr-un program va fi: x = 10 x = 11 x = 12 x = 12

O alta observatie este faptul ca operatorii pot fi supraincarcati in C++. Aceasta este o tehnica ce permite ca un anume operator sa se comporte diferit in contexte diferite. Spre exemplu, pentru o clasa oarecare operatorul ++ poate fi supraincarcat de asa natura incat sa creasca valoarea variabile tinta nu cu 1 ci cu o valoare oarecate.

5. Introducere în utilizarea funcţiilor C++

Functiile sunt sectiuni de cod separate de functia main (main este functia principala a unui program C++, singura functie care este executata direct; toate celelalte functii sunt executate prin apelare directa sau indirecta din functia main). Ele sunt utilizate pentru a executa calcule sau operatiuni specifice in cadrul programului. Regulile pentru denumirea functiilor sunt aceleasi ca cele discutate mai devreme pentru denumirea variabilelor. Figura 1.7 arata structura unei functii:

Figura 1.7 Structura unei functii

Un parametru este o valoare trimisa functiei si utilizata de aceasta ca element intr-un calcul, pentru a-si modifica functionarea sau pentru a-si preciza modul de lucru. Inainte ca o functie sa poata fi folosita ea trebuie declarata. Declaratia (prototipul) unei functii spune compilatorului cati parametri primeste functia, tipul fiecarui parametru precum si tipul de rezultat returnat de functia respectiva.Functia poate fi declarata inainte ca ea sa fie definita (sa ii fie descris si modul de functionare) urmand ca la definire prototipul functiei respective sa apara inca odata (vezi programul urmator).

//---------------------------------------------------------------------------#include <vcl.h>#include <iostream.h>#include <conio.h> // am adãugat aceastã linie#pragma hdrstopint multiply(int, int); //prototipul unei functii

Tipul returnat Lista de parametri a functiei

Numele functiei

Corpul functiei

Returnarea rezultatului

int OFunctie (int x, int y) { int z = (x * y); return z; }

Prototipul functiei

Page 13: Clase Si Program Are C++ Builder

void showResult(int); //prototipul unei functii//---------------------------------------------------------------------------#pragma argsusedint main(int argc, char* argv[]){ int x, y, result; cout << endl << "Introduceti prima valoare: "; cin >> x; cout << "Introduceti a doua valoare: "; cin >> y; result = multiply(x, y); showResult(result); cout << endl << endl << "Apasati orice tasta pentru a continua..."; getch(); return 0;}//---------------------------------------------------------------------------int multiply(int x, int y)//definitia primei functii; incepe cu prototipul functiei{ return x * y;}

void showResult(int res) //definitia celei de-a doua functii; incepe cu prototipul functiei{ cout << "Rezultatul este: " << res << endl;}//---------------------------------------------------------------------------

Programul cere doua numere de la utilizator, face inmultirea lor folosind functia multiply dupa care afiseaza rezultatul folosind functia showResult.O functie poate fi folosita in mai multe moduri diferite (putem transmite parametri unei functii prin valoare, prin referinta sau chiar ca rezultat al apelului unei alte functii). Folosind functiile din programul de mai sus putem ilustra acest concept:

result = multiply(2, 5); // transmisie prin valoareresult = multiply(x, y); // transmisie prin referintashowResult(multiply(x,y)); // valoare rezultata din apelul altei functiimultiply(x, y); // executia unei functii cu ignorarea valorii returnate

Observatie: Exista mai multe cazuri in care rezultatul unei functii poate fi ignorat (desi acest lucru pare gresit la prima vedere). Spre exemplu, atunci cand folosim functia getch() pentru a astepta apasarea unei taste oarecare, valoarea returnata de getch() va fi ignorata.Observatie: o functie se poate apela si pe ea insasi. Acest procedeu se numeste recursie si este folosita in rezolvarea mai multor tipuri de probleme.

Reguli pentru lucrul cu functii:- O functie poate avea orice numar de parametri sau sa nu aibe parametri;

Page 14: Clase Si Program Are C++ Builder

- Nu este obligatoriu ca functia sa returneze o valoare (se va pune void ca tip al rezultatului functiei);

- Daca o functie are void ca tip returnat ea nu poate returna o valoare. Pentru orice alt tip indicat ca tip returnat, functia trebuie sa returneze o valoare;

- O functie nu poate returna decat o singura valoare. Functia main()

Un program C++ de consola trebuie sa aibe o functie main(). Aceasta functie serveste ca punct de inceput al programului. In programele Windows scrise in C++ exista o functie echivalenta numita WinMain().Obs. La lucrul in C++Builder functia WinMain() este generata automat si scrisa in sectiunea de cod predefinit, programatorul nevazand-o in codul de program corespunzator formelor cu care lucreaza.

main() este o functie normala, in sensul ca are exact aceeasi structura (vezi structura definitiei unei functii de mai sus). Ati vazut deja ca prototipul functiei main pentru aplicatii de consola Windows pe 32 de biti este urmatorul: int main(int argc, char* argv[]);

Declarata in acest mod functia main() primeste doi parametri si returneaza o valoare intreaga. O diferenta fundamentala dintre functia main si toate celelalte functii este ca functia main nu este practic apelata de nimeni. Ea ruleaza automat atunci cand programul este executat. Tinand cont ca functia poate avea totusi parametri ca toate celelalte functii, se poate pune intrebarea: „De la cine primeste acesti parametri?” iar raspunsul corect este ca parametrii respectivi sunt parametrii care au fost dati in linie de comanda atunci cand a fost rulat programul. Desigur, putem rula un program fara nici un fel de parametri (si in marea majoritate a cazurilor asa se si intampla). In acest caz putem chiar specifica explicit ca nu vom folosi parametri:

int main();//nu primeste parametrivoid main();//nu primeste parametri, nu returneaza rezultat

argc, primul dintre cei doi parametri, contine numarul de parametri primiti in linie de comanda. Cel de-al doilea, argv, este un vector de stringuri de dimensiune neprecizata(va aminti ca putem lucra cu un string ca fiind un vector de caractere sau ca fiind un pointer la un caracter, cele doua fiind de fapt acelasi lucru) in care vor fi stocati parametrii primiti in linie de comanda la executarea programului.Spre exemplu, pentru un program fictiv numit copyx care va fi executat in linie de comanda in modul urmator:copyx c:\bc5\bin\grep.com d:\test\grep.com –dcei doi parametri vor contine urmtoarele:argc va contine valoarea 4 (linia de comanda contine 4 stringuri, cu tot cu numele programului)argv[0] (primul string din argv) are valoarea copyxargv[1] (al doilea string din argv) are valoarea c:\bc5\bin\grep.comargv[2] (al treilea string din argv) are valoarea d:\test\grep.comargv[3] (al patrulea string din argv) are valoarea –d

Page 15: Clase Si Program Are C++ Builder

Putem realiza un mic program care sa ilustreze afirmatiile de mai sus. Programul va afisa numarul de parametri primiti (valoarea lui argc) si parametrii respectivi (valorile din argv):

//---------------------------------------------------------------------------#include <vcl.h>#include <iostream.h>#include <conio.h>

#pragma hdrstop//---------------------------------------------------------------------------#pragma argsusedint main(int argc, char* argv[]){ cout << "argc = " << argc << endl; for (int i=0;i<argc;i++) cout << "Parametrul " << i << " este: " << argv[i] << endl; cout << endl << endl << "Apasati orice tasta pentru a continua..."; getch(); return 0;}//---------------------------------------------------------------------------

Pentru a simula ca programul este rulat in linie de comanda si primeste niste parametri, inainte de executie ne vom duce in meniul Run, optiunea Parameters si vom introduce in linia Parameters cativa parametri (pentru programul nostru ei nu trebuie sa aibe nici o semnificatie – vor fi doar listati, nu si folositi la ceva). Rezultatul ar trebui sa semene cu cel din figura 1.8:

Figura 1.8

Valoarea returnata de main poate fi folosita ca indicator al succesului executiei programului. In cele mai multe programe ea va ramane totusi nefolosita asa ca putem renunta la a returna vreo valoare din functia main:

void main(); // nu returneaza nimic, nu primeste parametrivoid main(int argc, char* argv[]); //nu returneaza nimic

6. Utilizarea masivelor de date (vectori şi matrici)

Page 16: Clase Si Program Are C++ Builder

Un masiv de date este o colectie de date de acelasi tip, asezate succesiv intr-o zona continua de memorie. Vectorii si matricile sunt tipuri de masive de date. Spre exemplu la vectorul:

int VectorulMeu[5];

compilatorul aloca memorie asa cum este ilustrat in figura 1.9. Pentru ca fiecare variabila de tip int ocupa 4 octeti in memorie, intregul vector va ocupa 20 de octeti:

VectorulMeu[0] VectorulMeu[1] VectorulMeu[2] VectorulMeu[3] VectorulMeu[4]adresa de baza a

vectoruluiadresa de baza

+ 4adresa de baza

+ 8adresa de baza

+ 12adresa de baza

+ 16Figura 1.9

Odata vectorul declarat, putem lucra cu fiecare element al vectorului in parte:VectorulMeu[0] = -200;VectorulMeu[1] = -100;VectorulMeu[2] = 0;VectorulMeu[3] = 100;VectorulMeu[4] = 200;

Mai tarziu in program putem lucra cu aceste elemente ale vectorului ca si cu variabile independente: int result = VectorulMeu[3] + VectorulMeu[4]; // rezultatul va fi 300

Exista si o metoda de a declara vectorul si de a intializa valorile tuturor elementelor sale intr-o singura operatie:

int VectorulMeu[5] = { -200, -100, 0, 100, 200 };

Daca se cunoaste exact numarul de componente si se foloseste metoda de mai sus pentru intializarea elementelor vectorului, nu mai e necesar nici macar sa precizam numarul de elemente al vectorului:

int VectorulMeu[] = { -200, -100, 0, 100, 200 };

Matricile sunt masive multidimensionale. Spre exemplu pentru crearea unei matrici bidimensionale de intregi, declaratia ar putea arata asa:

int MatriceaMea[3][5];

Aceasta declaratie aloca spatiu pentru 15 variabile intregi (15*4=60 de octeti). Accesarea elementelor matricii se face la fel cu accesarea elementelor unui vector cu deosebirea ca trebuie sa avem un index pentru fiecare dintre dimensiunile matricii:

int x = MatriceaMea [1][1] + MatriceaMea [2][1];

Figura 1.10 ilustreaza cum arata matricea declarata mai sus in memorie:

Page 17: Clase Si Program Are C++ Builder

MatriceaMea[][0](coloana 0)

MatriceaMea[][1](coloana 1)

MatriceaMea[][2](coloana 2)

MatriceaMea[][3](coloana 3)

MatriceaMea[][4](coloana 4)

MatriceaMea[0][](linia 0)

adresa de baza a matricii

adresa de baza + 4

adresa de baza + 8

adresa de baza + 12

adresa de baza + 16

MatriceaMea[1][](linia 1)

adresa de baza + 20

adresa de baza + 24

adresa de baza + 28

adresa de baza + 32

adresa de baza + 36

MatriceaMea[2][](linia 2)

adresa de baza + 40

adresa de baza + 44

adresa de baza + 48

adresa de baza + 52

adresa de baza + 56

Figura 1.10

Obs. Trebuie sa fim atenti sa nu suprascriem memoria de dupa sfarsitul unui vector sau al unei matrici. C++ acceseaza direct memoria si nu verifica, inainte de a scrie intr-o anumita zona de memorie daca are de fapt acces la acea zona de memorie sau nu. Din acest motiv elemente de cod precum:

VectorulMeu[5] = 150;sauMatriceaMea [3][2]=10;sauMatriceaMea [2][5]=-50;sauMatriceaMea [3][5]=72;

desi sunt acceptate de compilator (nu vor duce la aparitia unui mesaj de eroare) vor duce de cele mai multe ori la o terminare fortata a programului (eroare Windows). In cazul in care nu se va ajunge la o iesire fortata din program, rezultatele vor fi oricum impredictibile. Erorile de acest tip sunt comun intalnite, in special la persoanele care au lucrat anterior intr-un limbaj (Ex. Pascal sau Fox) la care numaratoarea liniilor/coloanelor incepe de la 1 si nu de la 0 ca in cazul C-ului si la care ultima linie / coloana este data de numarul de linii/coloane. Mai mult, tipul acesta de eroare este cateodata dificil de diagnosticat (s-ar putea ca programul sa nu iasa fortat de la o o prima executie).

Reguli pentru lucrul cu vectori/matrici:

- vectorii/matricile incep de la indexul 0.- dimensiunile vectorilor/matricilor trebuie sa fie constante la compilare (adica sunt

specificate fie prin precizarea numarului de elemente/linii/coloane fie prin initializarea tuturor elementelor cu valori date. O declaratie de genul:

int x=10;int VectorulMeu[x];

va duce la o eroare de compilare.

- atentie la scrierea zonelor de memorie de dupa sfarsitul unui masiv.- Masivele de mari dimensiuni e mai bine sa fie alocate dinamic (din heap) decat static (din

stack) (vom reveni ceva mai tarziu asupra acestui subiect)

Page 18: Clase Si Program Are C++ Builder

Lectia 2

Intructiunea conditionala if Instructiuni de ciclare: for, do, do-while Instructiunea switch Structuri

ifif este folosit pentru a testa o conditie si a executa apoi sectiunea de cod bazata pe valoarea de adevar (adevarat/fals) a respectivei conditii.Ex:

int x;cout << “Introduceti un numar: “;cin >> x;if (x > 10) cout << “Ati introdus un numar mai mare ca 10.” << endl;

Se cere introducerea unui numar de la utilizator. Daca numarul este mai mare ca 10, expresia x>10 este adevarata si este afisat un mesaj, altfel nu se afiseaza nimic.

Nota:Expresia if nu trebuie inchisa cu “;” (simbolizeaza o instructiune vida). Daca if este urmat de “;” compilatorul va interpreta intructiunea vida ca fiind cea care trebuie executata in cazul in care conditia este evaluate ca fiind adevarata.Ex: if (x==10) ;

Functie(x);// in acest cax Functie(x) va fi executat indifferent de valoarea de adevar a

conditiei.

Pentru a conditiona executia mai multor linii de cod cu expresia if se folosesc accolade pentru incadrarea respectivelor linii.

if (x > 10) { cout << “The number is greater than 10” << endl; DoSomethingWithNumber(x);

}

Nota: C++ permite folosirea de cod prescurtat. Se poate folosi:if (fisierData) ReadData();

in loc de forma:if (fisierData == true) ReadData();

Expresia este evaluate la adevarata atata timp cat variabila contine orice valoare diferita de 0. Se poate testa o conditie falsa aplicand operatorul logic ! (NOT) unei variabile:

if (!fileGood) ReportError();

In anumite cazuri este necesara executia unui cod si in cazul in care conditia este falsa. In acest caz se foloseste expresia else:

Page 19: Clase Si Program Are C++ Builder

if (x == 20) { Functie(x);}else { AltaFunctie(x);}

// in exemplu numai una din cele 2 functii va fi executata in functie de valoarea de adevar a conditiei

Se pot folosi in acelasi timp mai multe conditii if:

if (x > 10) if (x < 20) cout << “X este intre 10 si 20” << endl;

Sau se pot folosii conditii if-else imbricate:

if (x > 100) { y = 20; if (x > 200) { y = 40; if (x > 400) { y = 60; Functie(y); } }}else if (x < -100) { y = -20; if (x < -200) { y = -40; if (x < -400) { y = -60; Functie(y); } }}

Nota: Editorul C++Builder are o functie utila pentru potrivirea acoladelor. Pozitionati cursorul pe acoloda pentru care doriti sa gasiti corespondenta, si tastati ALT+[ sau ALT+], si cursorul se va pozitiona pe acolada cautata, indifferent daca este cea de inchidere sau deschidere.Daca o sectiune de cod contine mai mult de 3 if-uri imbricate care testeaza diferite valori alea aceeasi variabile, ati putea lua in considerare folosirea expresiei switch.

Exista si o versiune scurta a instructiunii conditionale if – else:Conditia:

if (directia == EAST) lost = true;else (lost = false);

Poate fi scrisa ca:directia == EAST ? lost = true : lost = false;

Page 20: Clase Si Program Are C++ Builder

Instructiuni de ciclare

Instructiunile de ciclare sunt folosite pentru parcurgerea unui vector, pentru a repeat o actiune de un anumit numar de ori, sau pentru a citi fisiere de pe disk. Toate instructiunile de ciclare au comune aceste caracteristici:

- un punct de plecare- un corp de instructiuni inchis intre accolade care se executa de fiecare data- un punct de oprire- un test de determinare a conditiei de oprire- folosirea optionala a intructiunii break sau continue.

In general intr-o instructiune de ciclare se evalueaza conditia de test, daca acesta conditie este indeplinita corpul de instructiuni este executat. Cand se termina de executat ultima instructiune se sare la inceput si se evalueaza din nou conditia, daca aceasta este adevarata se repeat executia corpului de instructiuni, daca este falsa se sare la executia urmatoarei linii de cod care urmeza dupa blocul de ciclare.

Nota: In C++ Builder rulearea unui program se realizeaza cu Run de pe Speed Bar sau apasand F9. Daca aveti nevoie sa terminate un program rulat din IDE, selectati Run|Reset Process din meniu, sau apasati CTRL+F2.

Instructiunea for:

for (initial; cond_expr; incrementare) { bloc instructiuni

}

Instructiunea repeta executia blocului de instructiuni, cat timp expresia conditionala cond_expr este adevarata. Starea de inceput este initializarea initial, dupa executarea blocului de instructiuni starea este modificata cu ajutorul expresiei de incrementare incrementare. Ex:

for (int i=0;i<10;i++) { cout << “Acesta este iteratia “ << i << endl;

}

// codul se executa de 10 ori, I se incrementeaza cu o unitate

for (int i=10;i<10;i--) { cout << “Acesta este iteratia “ << i << endl;

}

// i se decrementeaza cu o unitateINtr-o instructiune for variabila initializata poate lua orice valoare doriti, conditia de test poate fi orice expresie valida in C++ care poate avea valoarea de adevar true (adevarata). Cateva exemple de conditii de test:

for (int i=0;i < 100;i++) {...}for (int i=1;i == numarDeElemente;i++) {...}for (int i=0;i <= AflaNumarElemente();i+=2) {...}

Page 21: Clase Si Program Are C++ Builder

Intructiunea while

Instructiunea while difera de for, continand numai o conditie de test, care este verificata la fiecare iteratie. Cat timp conditia este adevarata se executa cate o iteratie.

int x;while (x < 1000) {x = executaCalcul();}// cat timp functia returneaza un numar mai mic ca 1000 se repeta iteratia

Se poate inclementa intructiunea while cu o variabila booleana ca si conditie de test, starea variabilei putand fi setate in interiorul ciclului.

bool done = false;while (!done) { //intructiuni code aici done = FunctieReturneazaBool(); //instructiuni cod}

Exemplu program:1: #include <iostream.h> 2: #include <conio.h> 3: #pragma hdrstop 4: int main(int argv, char** argc) 5: { 6: cout << endl << “Inceput program...” << endl << endl; 7: int i = 6; 8: while (i-- > 0) { 9: cout << endl << “Today I have “ << i;10: cout << “ problems to worry about.”;11: }12: cout << “\b!\nYipee!”;13: cout << endl << endl << “Apasati o tasta pentru continuare...”;14: getch();15: return 0;16: }

Instructiunea do-wile

Instuctiunea do-while este asemanatoare cu instructiunea while. Diferenta consta in locul unde se face evaluarea conditiei de test, daca while verifica expresia de iesire din ciclu la inceput, do-while face verificarea la sfarsit dupa executia blocului de cod, astfel corpul de instructiuni se executa cel putin odata chiar daca expresia de test este falsa.

bool done = false;do { // some code done = SomeFunctionReturningABool(); // more code} while (!done)

Instructiunea goto

Page 22: Clase Si Program Are C++ Builder

Aceasta instructiune permite saltul in executia unui program, la o eticheta declarata in prealabil prin un nume_eticheta urmat de “:”.

bool done = false;startPoint:// executa instructiuniif (!done) goto(startPoint);// dupa salt, executare instructini...

Nota: Este recomandat ca acesta instructiune sa nu fie utilizata. In C++ ea poate fi inlocuita usor de instructiunile do-while sau while.

Intructiunile continue si break

Cele doua instructiuni ajuta la controlul executiei codului in instructiunile de ciclare. De exemplu, ati putea avea un ciclu in care nu doriti sa executati anomite instructiuni daca un anumit test este adevarat. In acest caz se va folosi continue pentru a face salt la inceputul ciclului si evitarea executiei oricarui cod de dupa continue din interiorul iteratiei.:

bool done = false;while (!done) { // instr cod bool error = Functioe(); if (error) continue; // sare la inceputul ciclului // alt cod ce se executa numai daca nu apare o eroare}

Instructiunea break este folosita pentru a opri executia unei instructiuni de ciclare, inainte de indeplinirea conditiilor de oprire normale ale instructiunii. De exemplu, la cautarea unui numar intr-un vector, prin oprirea executiei ciclului de cautare puteti obtine indexul vectorului unde este localizat respectivul numar:

int index = 0;int cautaNumar = 50;for (int i=0;i<numElemente;i++) {

if (myArray[i] == cautaNumar) {index = i;break;}if (index) cout << “Numar gasit la index “ << index << endl;else cout << “Numarul nu a fost gasit in vector.” << endl;

Instructiunea switch

Instructiunea switch permite executarea unui bloc de instructiuni din mai multe posibilitati in fuctie de rezultatul evaluarii unei expresii. Evaluarea se poate face dupa o variabila, rezultatul apelului unei functii sau orice alta expresie C++ care poate fi evaluata.

Ex: switch(cantitate) { case 0 : { fine = 0; break; } case 10 : {

Page 23: Clase Si Program Are C++ Builder

fine = 20; break; } case 15 : { fine = 50; break; } case 20 : case 25 : case 30 : { fine = cantitate * 10; break; } default : { fine = Functie1(); jailTime = Functie2(); }}

Intructiune switch contine mai multe parti: expresia al carui rezultat este evaluat – cantitate, expresia case care testeaza rezultatul pentru egalitate (case 0 – daca cantitate egal 0 ) si executa un cod in acest caz. Se foloseste break petru a iesi din instructiunea switch dupa executia blocului specific rezultatului, altfel s-ar putea executa si alt cod nedorit din switch. Putem avea si un cod default care se executa in caz ca nu a existat nici un caz potrivit. Folosirea lui default este optionala.In cazul un care dupa un caz nu avem un bloc de instructiuni, pentru acel caz/cazuri se executa primul bloc de intructiuni pana la intalnirea lui break.

Vizibilitatea variabilelor

Majoritatea variabilelor sunt locale, adica sunt vizibile numai in interiorul bloclui de cod in care sunt declarate.

Ex: 1: #include <iostream.h> 2: #include <conio.h> 3: #pragma hdrstop 4: int x = 20; 5: void CountLoops(int); 6: int main(int, char**) 7: { 8: int x = 40; 9: int i = 0;10: cout << “In main program x = “ << x << endl;11: bool done = false;12: while (!done) {13: int x;14: cout << endl << “Enter a number (-1 to exit): “15: cin >> x;16: if (x != -1) {

Page 24: Clase Si Program Are C++ Builder

17: cout << endl << “In while loop x = “ << x;18: CountLoops(++i);19: }20: else21: done = true;22: }23: cout << “Global x = “ << ::x << endl;24: cout << endl << “Press any key to continue...”;25: getch();26: return 0;27: }28: void CountLoops(int x)29: {30: cout << “, While loop has executed “31: << x << “ times” << endl;32: }

In exemplu de mai sus varibila x este declarata de 4 ori. Daca din greseala o variabila este declarata de mai multe ori compilatorul va da un mesaj de eroare, in acest caz insa programul va rula pentru ca respectiva variabila, x, este vizibila numai in anumite blocuri. Declararea variabilei x in linia 13 este in interiorul cilcului while si este vizibila numai in acel bloc, lafel in linia 28 unde declararea este in interiorul unei functii si nu exista in afara ei. In cazul declaratiei de linia 8, este vizibil in interiorul functiei main si ar putea aparea confuzii cu folosirea lui x in ciclul while. In acest tip de situatii este folosita variabila cea mai apropiata de blocul de cod, adica cea din while.

Declararea din linia 4 este exterioara oricarei functii, acea variabila este vizibila peste tot in program si este o variabila globala. Accesul la o variabila globala se face cu operatorul de rezolutie “::”.

Variabile externe

O aplicatie are de obicei mai multe fisiere/module care contin codul sursa. O variabila globala declarata intr-un modul este vizibila in acel fisier insa nu este acesibila in celelalte module. Pentru a fi accesibila si in alte module o variabila globala trebuie declarata si in modulul in care se doreste ca ea sa fie accesibila. Declararea in module se realizeaza folosindu-se cuvantul cheie extern:

extern int varGlobala;

Structuri

O structura este o colectie de campuri de date grupate intr-o singura unitate de memorie. Declararea unei structuri se face cu cuvantul cheie struct:

struct mailingListRecord { char firstName[20]; char lastName[20]; char address[50]; char city[20]; char state[4];

Page 25: Clase Si Program Are C++ Builder

int zip; bool aFriend; bool aFoe;};

Fiecare element al structurii este o data membra si se declara ca o variabila intr-un bloc de cod. Declararea unei structuri se termina cu “;”.

In momentul definirii structurii se pot declara si variabile (instante) prin inserarea numelui respectivelor variabile, separate de virgula, intre acolada de inchidere si “;”.

Pentru accesarea campurilor member dintr-o structura se foloseste operatorul ., care se pune intre numele variabilei si numele campului membru.

Tablouri de structuri

La fel ca si vectorii de tipuri fundamentale de date (int, char), se pot crea vectori de structuri. Declararea si folosirea unei vector de structuri:

mailingListRecord listArray[5];strcpy(listArray[0].firstName, “Chuck”);listArray[4].aFoe = true; // grrrrr!!// etc.

Headere si fisiere sursa

Fisierele sursa sunt fisiere in cod ASCII care contin cod sursa pentru un program. Declaratiile de clase si structuri, functii sunt deregula separate de restul codului unui program in fisiere numite header. Headere-le sunt fisiere cu extensia .h sau .hpp. Odata creat un header acesta se poate include in orice modul care foloseste respectivele definitii de clase sau structuri din header, cu ajutorul directivei #include:

# include “fisierHeader.h”

Exemplu de program care foloseste structuri:Listing STRUCTUR.H. 1: #ifndef _STRUCTUR_H 2: #define _STRUCTUR.H 3: struct mailingListRecord { 4: char firstName[20]; 5: char lastName[20]; 6: char address[50]; 7: char city[20]; 8: char state[5]; 9: int zip;10: };11: #endif

//programul principal:1: #include <iostream.h> 2: #include <conio.h> 3: #include <stdlib.h> 4: #pragma hdrstop 5: #include “structur.h” 6: void displayRecord(int, mailingListRecord mlRec);

Page 26: Clase Si Program Are C++ Builder

7: int main(int, char**) 8: { 9: //10: // create an array of mailingListRecord structures11: //12: mailingListRecord listArray[3];13: cout << endl;14: int index = 0;15: // get three records16: //17: do {18: cout << “First Name: “;19: cin.getline(listArray[index].firstName,20: sizeof(listArray[index].firstName) - 1);21: cout << “Last Name: “;22: cin.getline(listArray[index].lastName,23: sizeof(listArray[index].lastName) - 1);24: cout << “Address: “;25: cin.getline(listArray[index].address,26: sizeof(listArray[index].address) - 1);27: cout << “City: “;28: cin.getline(listArray[index].city,29: sizeof(listArray[index].city) - 1);30: cout << “State: “;31: cin.getline(listArray[index].state,32: sizeof(listArray[index].state) - 1);33: char buff[10];34: cout << “Zip: “;35: cin.getline(buff, sizeof(buff) - 1);36: listArray[index].zip = atoi(buff);37: index++;38: cout << endl;39: }40: while (index < 3);41: //42: // clear the screen43: //44: clrscr();45: //46: // display the three records47: //48: for (int i=0;i<3;i++) {49: displayRecord(i, listArray[i]);50: }51: //52: // ask the user to choose a record53: //54: cout << “Choose a record: “;55: char rec;56: //57: // be sure only 1, 2, or 3 was selected58: //59: do {60: rec = getch();61: rec -= 49;62: } while (rec < 0 || rec > 2);63: //

Page 27: Clase Si Program Are C++ Builder

64: // assign the selected record to a temporary variable65: //66: mailingListRecord temp = listArray[rec];67: clrscr();68: cout << endl;69: //70: // display the selected record71: //72: displayRecord(rec, temp);73: getch();74: return 0;75: }76: void displayRecord(int num, mailingListRecord mlRec)77: {78: cout << “Record “ << num + 1 << “:” << endl;79: cout << “Name: “ << mlRec.firstName << “ “;80: cout << mlRec.lastName;81: cout << endl;82: cout << “Address: “ << mlRec.address;83: cout << endl << “ “;84: cout << mlRec.city << “, “;85: cout << mlRec.state << “ “;86: cout << mlRec.zip;87: cout << endl << endl;88: }

Saptamana 4 – Clase si programarea orientata pe obiecte

O clasa, asemanator cu o structura, este o colectie de date membre si functii specifice pentru realizarea unui anumit task. Putem spune ca o clasa incapsuleaza respectivul task.

Page 28: Clase Si Program Are C++ Builder

Clase – nivel de accessClasele pot avea trei nivele de acces: private, public si protected. Nivelul de acces controleaza modul in care utilizatorii au acces la o clasa. Orice clasa are o parte publica care este modalitatea de interactiune cu userii si o parte privata – implementarea interna la care nu se permite accesul din exterior.

Specificatorii de acces sunt utilizati in declararea unei clase:class Vehicle { public: bool haveKey; bool Start(); void SetGear(int gear); void Accelerate(int acceleration) void Break(int factor); void Turn(int direction); void ShutDown(); protected: void StartupProcedure(); private: void StartElectricalSystem(); void StartEngine(); int currentGear; bool started; int speed;};

Membrii unei clase care au specificatorul de acces protected pot fi accesati doar din clasele derivate nu direct de catre utilizatorii clasei. Daca nu se specifica nici un nivel de acces membrii clasei sunt setati default private.

Constructori

Constructorul este o functie a unei clase care se apeleaza automat cand se instantiaza o clasa. Constructorul este folosit pentru initializarea oricarei variabile membre a clasei, alocarea memoriei pentru clasa sau orice alt task de initializare. In momentul in care nu se specifica un constructor compilatorul C++Builder va crea automat un constructor implicit. Constructorul are acelasi nume cu clasa.

class Vehicle {public:Vehicle(); // constructorbool haveKey;bool Start();void SetGear(int gear);void Accelerate(int acceleration);void Break(int factor);void Turn(int direction);void ShutDown();protected:void StartupProcedure();private:void StartElectricalSystem();void StartEngine();int currentGear;bool started;int speed;};

Page 29: Clase Si Program Are C++ Builder

Observati ca un constructor nu are un tip returnat, un constructor nu returneaza nici o valoare.

O clasa poate avea mai multi constructori. De exemplu putem avea o clasa cu un constructor fara parametrii - constructor implicit si un constructor cu parametrii care initializaeaza anumite variabile membre cu valori specifice.Ex : class Rect {

public:Rect();Rect(int _left, int _top, int _bottom, int _right);int GetWidth();int GetHeight();void SetRect(int _left, int _top, int _bottom, int _right);private:int left;int top;int bottom;int right;};

Definitia constructorilor este:

Rect::Rect(){left = 0;top = 0;bottom = 0;right = 0;}Rect::Rect(int _left, int _top, int _bottom, int _right){left = _left;top = _top;bottom = _bottom;right = _right;

}

Nota : Instantierea este procesul de creere a unui obiect, instanta a unei clase.

Apelarea unui constructor se face la instantierea unei clase. Pentru clasa definita anterior putem avea doua moduri de instantiere, cu constructorul implicit si cu cel cu parametrii:

Rect rect1; // object created using default constructorRect rect2(0, 0, 100, 100); // created using 2nd constructor

Liste de initializare

C++ permite initializarea datelor member ale unei clase intr-o lista de initializare. Exemplul de folosire pentru cei doi constructori definiti anterior este:

Rect::Rect() :left(0),top(0),bottom(0),right(0){}Rect::Rect(int _left, int _top, int _right , int _bottom) :left(_left),top(_top),bottom(_bottom),right(_right){}

Observati ca lista de initializare este precedata de un bloc de acolade. De asemenea fiecare variabila din lista este urmata de ‘,’ exceptie facand ultima variabila. 

Page 30: Clase Si Program Are C++ Builder

DestructoriDestructorul este o functie speciala, care se apeleaza automat la distrugerea unui obiect.

Poate fi considerat inversul constructorului si este folosit la eliberarea memoriei alocate obiectului distrus. Un destructor nu returneaza nici o valoare si nu are nici parametrii. Numele destructorului este numele clasei precedat de simbolul tilda (~).

Ex : class Rect {public:Rect();Rect(int _left, int _top, int _bottom, int _right);~Rect(); // destructor addedint GetWidth();int GetHeight();void SetRect(int _left, int _top, int _bottom, int _right);private:int left;int top;int bottom;int right;char* text; // new class member added};Rect::Rect() :left(0),top(0),bottom(0),right(0){text = new char[256];strcpy(text, “Any Colour You Like”);}// code omittedRect::~Rect(){delete[] text;}

Destructorul acestei clase elibereaza memoria alocata unui vector de caractere –text.

Date membreAtributele unei clase sunt variabile definite in interiorul unei clase, si care au definite

specificatori de access. Datele membre ale unei clas esunt accesibile in toate functiile clasei indiferent de specificatorii de acces. In exteriorul unei clase sunt vizibile numai datele declarate public, cele private si protected neputand fi accesate. Pentru accesul la datele membre private ale unei clase se folosest functii publice ale unei clase pentru setarea si returnarea datelor membre.

Un exemple de functii de setare si returnare:int Rect::GetLeft(){return left;}void Rect::SetLeft(int newLeft){left = newLeft;}

Pentru utilizare folosim:TRect rect;int x = rect.GetLeft();

Functii member

Functiile membre sunt functii care apartin unei clase. Apelul lor se poate face doar din interiorul clasei sau printr-o instanta a clasei. Ele au acces la toti membrii clasei membr indifferent de specificatorii de acces.

Functiile membre au specificatori de acces in functie de modul de utilizare. Functiile publice sunt o interfata a clasei cu exteriorul, prin ele se pot accesa date ale clasei. Functiile

Page 31: Clase Si Program Are C++ Builder

private sunt folosite intern (ex. Functii de initializare a datelor membre care pot fi apelate de constructori).

Declarearea functiilor membre se poate face in doua feluri. Cu definirea functiei in exteriorul clasei, caz in care se foloseste cuvantul cheie inline si numele functiei este precedat de numele clasei si operatorul de rezolutie:

ClassName {public:ReturnType FunctionName();};inline ReturnType ClassName::FunctionName() {statements

} Sau in interiorul clasei:

ClassName {public:ReturnType FunctionName(){statements}};

Pointerul this

Toate clasele au o variabila membru ascunsa, pointerul this, un pointer la instanta clasei respective in memorie. Cand se instantiaza o clasa, pointerul this este automat initializat cu adresa respectivei clase in memorie.

Ex:void __fastcall TMyForm::Button1Click(TObject *Sender){TButton* button = new TButton(this);button->Parent = this;button->Caption = “New Button”;button->Left = 100;button->Top = 100;button->Show();// more code}// se asigneaza proprietatii Parent a butnoului pointerul this

MostenireUna din cele mai importante insusiri ale unei clase C++ este posibilitatea de extindere

prin mostenire. Mostenirea inseamna crearea unei noi clase pornind de la o clasa de baza prin adaugarea de noi functionalitati. Clasa de la care se pleaca se numeste clasa de baza iar clasa nou obtinuta se numeste clasa derivata.

La definirea unei clase derivate se pune dupa numele clasei “:” si numele clasei de baza:class MilitaryPlane : public Airplane {

public:MilitaryPlane(char* name, int _type);virtual int GetStatus(char* statusString);protected:virtual void TakeOff();virtual void Land()virtual void Attack();virtual void SetMission();private:Mission theMission;};

Folosirea cuvantului cheie – virtual in fata declararii unei functii, defineste o functie virtuala. O functie virtuala este o functie care va fi apelata automat daca o functie cu acest nume exista in clasa derivata.

Page 32: Clase Si Program Are C++ Builder

Intr-o clasa derivate, se poate inlocui definitia unei functii existente in clasa de baza. Acest procedura poarta denumirea de suprascriere a unei functii. Suprascrierea se foloseste pentru a modifica actiunile functiei din clasa de baza sau pentru a-i mari functionalitatea. La suprascriere se foloseste exact acelasi antet al functiei din clasa de baza.

Ex: void MilitaryPlane::TakeOff(int dir){// new code goes here}

//cazul in care se inlocuieste total codul

Daca se doreste imbunatatirea functiei prin suprascriere atunci in declarare se va apela functia din clasa de baza:

void MilitaryPlane::TakeOff(int dir){Airplane::TakeOff(dir);// new code goes here}

Operatorul de rezolutie se foloseste numai in cazul in care avem functii din clasa de baza si derivate cu acelasi nume si antet, orice alta functie publica sau protejata din clasa de baza poate fi apelata direct.

La derivarea unei clase trebuie sa apelati constructorul claselor de baza ca sa fiti sigur ca toate clasele parinte sunt initializate corect.

MilitaryPlane:: MilitaryPlane(char* _name): Airplane(_name, MILITARY) // call base class{// body of constructor

}

Exemplu de clase derivate:

Mostenire multiplaDerivarea unei clase din doua sau mai multe clase de baza se numeste mostenire multipla.class Fighter : public MilitaryPlane, public Armaments {public:Fighter(char* name);private:// other stuff

};

La definire clasele de baza sunt scrise separate prin virgula, de asemenea la apelul constructorului clasei derivate se apeleaza si toti constructorii din clasele de baza.

Exemplu de mostenire multipla:

Page 33: Clase Si Program Are C++ Builder

Lucrul cu fisiere I/O

Atunci cand doriti sa realizati aplicatii care sa citeasca sau sa scrie in fisiere veti apela la fluxuri de I/O.

Lucrul cu fluxuri de I/O in C++Builder se realizeaza prin intermediul a 3 clase:- ofstream – se ocupa de iesiri- ifstream – se ocupa de intrari- fstream – atat iesiri cat si intrari

Fluxuri de intrare

1: #include <condefs.h>2: #include <stdio.h>3: #include <stdlib.h>4: #include <iostream.h>5: #include <fstream.h>6: #include <conio.h>7: #pragma hdrstop8:9: int main(int argc, char **argv)10: {11: char buff[80];12: ifstream infile;13: infile.open(“readfile.cpp”);14: if (!infile) return 0;15: while (!infile.eof()) {16: infile.getline(buff, sizeof(buff));17: cout << buff << endl;18: }19: infile.close();20: cout << endl << “Press any key to continue...”;21: getch();22: return 0;23: }

Citirea dintr-un fisier se face prin instantierea clasei ifstream (obiectul infile), deschiderea fisierului cu metoda open asociata clasei si inchiderea prin metoda close.Pentru a se citi o linie se foloseste functia getline si verificarea ajungerii la sfarsitul fisierului se face cu eof().

Page 34: Clase Si Program Are C++ Builder

Nota: calea fisierului la deschidere se da folosind backslash dublu, iar initializarea instantei clasei ifstream si deschiderea fisierului se pot face si intr-o singura linie:

ifstream infile(“c:\\windows\\win.ini”);

La citirea unor variabile dintr0un fisier se poate folosi si operatorul de extractie (>>) care se opreste la intalnirea unui spatiu.

ifstream infile(“somefil.dat”);while (!infile.eof()) {int x;infile >> x; // read number from file and assign it to xcout << x << endl;}

Fluxuri de iesire

La scrirea intr-un fisier procedura este asemanatoare cu citirea. De acesta data se initializeaza clasea ofstream si se foloseste operatorul de insertie (<<) pentru scrierea efectiva.

1: #include <condefs.h>2: #include <stdio.h>3: #include <stdlib.h>4: #include <iostream.h>5: #include <fstream.h>6: #include <conio.h>7:8: #pragma hdrstop9:10: int main(int argc, char **argv)11: {12: char buff[81];13: cout << “Creating File...” << endl;14: ofstream outfile(“test.dat”);15: if (!outfile) return 0;16: cout << “Writing File...” << endl;17: for (int i=0;i<10;i++) {18: outfile << “This is line #” << i + 1 << endl;19: }20: outfile.close();21: cout << “Opening File for Input...” << endl;22: ifstream infile(“test.dat”);23: if (!infile) return 0;24: cout << “Reading File...” << endl << endl;25: while (!infile.eof()) {26: infile.getline(buff, sizeof(buff));27: cout << buff << endl;28: }29: infile.close();30: cout << endl << “Press any key to continue...”;31: getch();32: return 0;33: }

Moduri deschidere fisiere

In momentul folosirii fisierele pot fi deschise in mai multe feluri. In mod implicit deschiderea unui fiser cu clasa ofstream este in modul creare fiser. Daca fisierul deschis exista acesta se va suprascrie. Pentru a specifica modul adaugare la deschidere va trebui specificat unul din modurile de deschidere (open_mode) ale clasei ios.

ofstream outfile(“test.dat”, ios::app);

specificatori open_mode ai clasei ios:

app - deschidere pt adaugareate – cautarea sfarsitului fisierului cand se dechidein – deschidere pentru citire, implicit pentru clasa istream

Page 35: Clase Si Program Are C++ Builder

out – deschidere pentru scriere , implicit pentru clasa ostreambinary - deschidere in mod binarytrunc – deschide un fisier si sterge continutulnocreate – fisierul nu va fi creat daca nu existanoreplace – similar cu nocreate

Puteti specifica in acelasi timp mai multe moduri de deschiderea a fisierelor,ofstream outfile(“test.dat”, ios::app | ios::binary);

ceea ce inseamna deschidere in mod binary si adaugare la sfarsitul fisierului.