CATEGORII DOCUMENTE |
Lectia 1
Continut
Un tur rapid al C++Builder
Modul de scriere al aplicatiilor de consola Win32;
O introducere in limbajul C
Variabilele si tipurile de date C
Introducere in utilizarea functiilor C
Utilizarea masivelor de date (vectori si matrici);
1. Un tur rapid al C++Builder
Pentru moment, nu vom acorda decat o privire rapida mediului de dezvoltare C Builder, urmand ca in lectia a sasea sa examinam in detaliu acest IDE.
Atunci cand pornim pentru prima oara IDE-ul C++Builder ni se prezinta mediul de lucru C++Builder in care este deschisa o forma noua, fara continut, ca in figura 1.1. (forma este unul dintre elementele de interfata vizuala, practic o fereastra de uz general pentru o aplicatie oarecare).
Figura 1.1
IDE-ul C++Builder este impartit in trei parti. Fereastra superioara poate fi considerata partea principala a IDE-ului. Pe langa meniul principal ea contine si bara de butoane cu cele mai folosite operatii in stanga si selectorul de componente utilizabile in dreapta. (vezi figura 1.2).
Figura 1.2.
Pentru o mai usoara regasire, componentele sunt impartite in tipuri de componente, fiecare tip avand un tab in paleta de componente. Pentru a utiliza o componenta, este suficient sa o selectam in paleta dupa care sa dam click pe forma pe care dorim sa amplasam componenta, la pozitia dorita.
O componenta este o bucata de cod software care va indeplini in aplicatie o anume functie predefinita (cum ar fi o eticheta, un camp de editare sau o lista).
Cea de-a doua parte a IDE-ului C++Builder este inspectorul de obiecte (Object Inspector) care este amplasat in mod implicit in stanga ecranului. Prin intermediul inspectorului de obiecte vom modifica proprietatile componentelor si modul cum sunt tratate evenimentele referitoare la ele (interactiunile utilizatorului cu componenta respectiva). In inspectorul de obiecte apare intotdeauna lista de proprietati a componentei curent selectate, dublata de lista de evenimente care pot afecta componenta respectiva, dar mai poate aparea (daca este selectata) si ierarhia de componente a aplicatiei.
In dreapta inspectorului de obiecte este spatiul de lucru al C++Builder (cea de-a treia parte). Initial in acest spatiu este afisat editorul de forme. Acesta este utilizat pentru a amplasa, muta sau dimensiona diverse componente ca parte a crearii formelor aplicatiei. In spatele editorului de forme se afla partial ascunsa fereastra editorului de cod de program (locul in care vom scrie cod pentru programele noastre).
Sa incercam o prima aplicatie practica.
In acest moment, C++Builder este pornit si avem la dispozitie o forma fara continut. In mod implicit, acesta forma este denumita Form1. Inspectorul de obiecte afiseaza proprietatile referitoare la ea. Selectati proprietatea Caption din lista de proprietati a formei si tastati un titlu pe care doriti sa-l dati ferestrei de aplicatie reprezentate de Form1.
Observati ca pe masura ce tastati, titlul ferestrei este modificat (veti observa acest comportament si la alte componente).
Pentru a rula aplicatia proaspat obtinuta putem apasa pe butonul Run de pe bara de unelte (cel pe care este desenata o sageata verde) sau putem apela optiunea Run din meniul Run sau putem apasa tasta F9 (care este un shortcut catre optiunea precedenta). La folosirea oricareia din modalitatile de mai sus, IDE-ul va raspunde prin afisarea unui ferestre de stare continand informatii referitoare la procesul de compilare, ca in figura 1.3. (procesul de obtinere a codului executabil al aplicatiei).
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.
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.
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
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 argsused
int main(int argc, char* argv[])
Programul respectiv nu face nimic, dar este un program valid.
3. O introducere in limbajul C
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!";
Aceasta linie de cod spune programului sa insereze textul Bine ati venit! in streamul standard de iesire, adica pe ecranul monitorului.
Observatie. cout nu poate fi utilizat decat in aplicatiile de consola. In aplicatiile cu interfata grafica Windows exista doua functii standard pentru afisare de text: DrawText() si TextOut() (ele nu fac oricum obiectul acestei lectii).
Pentru a folosi cout trebuie inclusa biblioteca care il declara (#include<iostream.h>
Daca am uitat sa facem acest lucru, la incercarea de a rula aplicatia vom obtine o eroare de compilare (Undefined symbol 'cout').
Pentru a afla de unde provine o anumita functie sau un anumit tip, putem da click pe numele functiei sau tipului si apasa F1. La apasarea tastei F1 va aparea textul de ajutor referitor la functia sau tipul respectiv, incluzand fisierul biblioteca in care acesta a fost declarat.
In iostream.h exista de asemenea elemente de modificare a modului in care un stream este tratat. Pentru moment, vom lucra cu endl, care desemneaza inceputul unei noi linii in streamul de iesire.
Acum putem scrie o prima aplicatie care sa afiseze un mesaj. Urmariti listingul de mai jos:
#include <vcl.h>
#include <iostream.h> // am adaugat aceasta linie
#pragma hdrstop
#pragma argsused
int main(int argc, char* argv[])
Observatie. Spatiile inserate in text, atat timp cat nu rup un cuvant, nu au nicio influenta. Spre exemplu bucata de cod urmatoare:
int main(int argc, char **argv)
este acelasi lucru cu:
int main(int argc,char** argv)
Pentru a rula programul, folosim aceeasi optiune ca mai devreme. La executie va aparea o fereastra de consola si in ea va fi afisat mesajul dorit, dupa care fereastra respectiva va fi inchisa imediat. Acest lucru se datoreaza faptului ca aplicatia si-a terminat executia, iar fereastra de consola care a gazduit-o se va inchide imediat dupa terminarea aplicatiei.
Pentru a impiedica acest lucru, mai adaugam inca o linie de cod care sa astepte apasarea unei taste. Vom utiliza functia getch() din biblioteca conio.h (functii de intrare-iesire pentru consola), precum in exemplul urmator:
#include <vcl.h>
#include <iostream.h>
#include <conio.h> // am adaugat aceasta linie
#pragma hdrstop
#pragma argsused
int main(int argc, char* argv[])
De data aceasta aplicatia ruleaza, afiseaza mesajul dorit si fereastra de consola ramane vizibila pana la apasarea unei taste.
Acesta a fost un prim exemplu de aplicatie de consola. Mai departe vom incerca sa intelegem alte elemente ale limbajului C
4. Variabilele si tipurile de date C
Pentru inceput, e bine sa mentionam ca nu vom face o prezentare extensiva a limbajului C++. Pentru acest lucru, este necesara consultarea altor lucrari dedicate.
Variabile
O variabila este o portiune de memorie, identificata printr-un nume si destinata stocarii datelor de un anumit tip. Variabilele sunt utilizate pentru manipularea datelor in memorie.
Un exemplu de utilizarea a variabilelor intr-un program este urmatorul:
int x; // variabila de tip intreg
x = 100; // 'x' contine acum valoarea 100
x += 50; // la valoarea lui 'x' se adauga 50, devenind 150
int y = 150; // se declara si se initializeaza cu valoarea 150 variabila 'y'
x += y; // la valoarea lui 'x' se adauga valoarea lui 'y', devenind 300
x++; // la valoarea lui 'x' se adauga 1, devenind 301
Variabilele care sunt declarate, dar nu sunt initializate, vor contine valoarea continuta pana atunci in zona de memorie respectiva (la initializarea calculatorului, pana la utilizare, locatiile de memorie sunt initializate cu 0, dupa utilizare, o locatie de memorie este doar declarata libera, nu si reinitializata cu 0, drept pentru care la o reutilizare, ea va contine valoarea "mostenita" de la utilizarea anterioara, chiar daca nu mai are aceeasi semnificatie). Din acest motiv, nu este posibil sa stim ce contine o variabila care a fost declarata, dar nu si initializata. Un exemplu de fragment de cod defectuos din acest punct de vedere este urmatorul:
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 combinatie de majuscule, minuscule, cifre si underscore (_). Nu pot contine alte caractere (caractere speciale si spatiu). Nu pot incepe cu o cifra. Numele de variabila care incep cu underscore sunt de obicei folosite pentru variabile cu destinatii speciale. Lungimea maxima a unui nume de variabila depinde de la compilator la compilator, dar implementarile standard au de obicei lungime maxima de 31 de caractere (ceea ce este oricum prea mult pentru un nume de variabila 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;
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 |
-128 to 126 |
|
unsigned char |
0 to 255 |
|
short |
-32,768 to 32,767 |
|
unsigned short |
0 to 65,535 |
|
long |
-2,147,483,648 to |
|
unsigned long |
0 to 4,294,967,295 |
|
int |
la fel ca long (atentie, difera de C-ul clasic) |
|
unsigned int |
la fel ca unsigned long (idem) |
|
float |
1.2E-38 to 3.4E381 |
|
double |
2.2E-308 to 1.8E3082 |
|
bool |
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>
#pragma hdrstop
#pragma argsused
int main(int argc, char* argv[])
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;) |
|
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
incrementeaza
cout << "x = " << x << endl;//il afiseaza din nou pe x
cout << "x = " << ++x << endl;//il incrementeaza pe x inainte
de a il afisa
cout << "x = " x << endl; //il afiseaza din nou pe x
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 in utilizarea functiilor 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 adaugat aceasta linie
#pragma hdrstop
int multiply(int, int); //prototipul unei functii
void showResult(int); //prototipul unei functii
#pragma argsused
int main(int argc, char* argv[])
int multiply(int x, int y)//definitia primei functii; incepe cu prototipul functiei
void showResult(int res) //definitia celei de-a doua functii; incepe cu prototipul functiei
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
valoare
result = multiply(x, y); // transmisie prin referinta
showResult(multiply(x,y)); // valoare rezultata din apelul altei functii
multiply(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;
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 parametri
void 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:bc5bingrep.com d:testgrep.com -d
cei 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 copyx
argv[1] (al doilea string din argv) are valoarea c:bc5bingrep.com
argv[2] (al treilea string din argv) are valoarea d:testgrep.com
argv[3] (al patrulea string din argv) are valoarea -d
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 argsused
int main(int argc, char* argv[])
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 parametri
void main(int argc, char* argv[]); //nu returneaza nimic
6. Utilizarea masivelor de date (vectori si matrici)
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 vectorului |
adresa de baza + 4 |
adresa de baza + 8 |
adresa de baza + 12 |
adresa de baza + 16 |
Figura 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] = ;
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[] = ;
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:
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;
sau
MatriceaMea [3][2]=10;
sau
MatriceaMea [2][5]=-50;
sau
MatriceaMea [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)
Lectia 2
if 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)
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:
if (x == 20)
else
// 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)
else if (x < -100)
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;
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)
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++)
// codul se executa de 10 ori, I se incrementeaza cu o unitate
for (int i=10;i<10;i--)
// i se decrementeaza cu o unitate
INtr-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)
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)
// 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)
Exemplu program:
1: #include <iostream.h>
2: #include <conio.h>
3: #pragma hdrstop
4: int main(int argv, char** argc)
cout << "b!nYipee!";
cout << endl << endl << "Apasati o tasta pentru continuare";
getch();
return 0;
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 while (!done)
Instructiunea goto
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 instructiuni
if (!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)
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 (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 10 :
case 15 :
case 20 :
case 25 :
case 30 :
default :
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**)
else
done = true;
}
cout << "Global x = " << ::x << endl;
cout << endl << "Press any key to continue";
getch();
return 0;
28: void CountLoops(int x)
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 ;
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 ;
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);
7: int main(int, char**)
8:
while (index < 3);
//
// clear the screen
//
clrscr();
//
// display the three records
//
for (int i=0;i<3;i++)
//
// ask the user to choose a record
//
cout << "Choose a record: ";
char rec;
//
// be sure only 1, 2, or 3 was selected
//
do while (rec < 0 || rec > 2);
//
// assign the selected record to a temporary variable
//
mailingListRecord temp = listArray[rec];
clrscr();
cout << endl;
//
// display the selected record
//
displayRecord(rec, temp);
getch();
return 0;
76: void displayRecord(int num, mailingListRecord mlRec)
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.
Clase - nivel de access
Clasele 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 ;
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 ;
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 ;
Definitia constructorilor este:
Rect::Rect()
Rect::Rect(int _left, int _top, int _bottom, int _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 constructor
Rect 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.
Destructori
Destructorul 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 ;
Rect::Rect() :
left(0),
top(0),
bottom(0),
right(0)
// code omitted
Rect::~Rect()
Destructorul acestei clase elibereaza memoria alocata unui vector de caractere -text.
Date membre
Atributele 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()
void Rect::SetLeft(int 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 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
inline ReturnType ClassName::FunctionName
Sau in interiorul clasei:
ClassName
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)
// se asigneaza proprietatii Parent a butnoului pointerul this
Mostenire
Una 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 ;
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.
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)
//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)
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
Exemplu de clase derivate:
Mostenire multipla
Derivarea unei clase din doua sau mai multe clase de baza se numeste mostenire multipla.
class Fighter : public MilitaryPlane, public Armaments ;
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:
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 hdrstop
9: int main(int argc, char **argv)
19: infile.close();
20: cout << endl << "Press any key to continue";
21: getch();
22: return 0;
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().
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:windowswin.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())
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>
8: #pragma hdrstop
10: int main(int argc, char **argv)
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())
29: infile.close();
30: cout << endl << "Press any key to continue";
31: getch();
32: return 0;
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 adaugare
ate - cautarea sfarsitului fisierului cand se dechide
in - deschidere pentru citire, implicit pentru clasa istream
out - deschidere pentru scriere , implicit pentru clasa ostream
binary - deschidere in mod binary
trunc - deschide un fisier si sterge continutul
nocreate - fisierul nu va fi creat daca nu exista
noreplace - 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.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1264
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved