Sunteți pe pagina 1din 43

Cuvinte importante:

-preprocesare: constante, macrocomenzi, directive preprocesor,


crearea propriilor macroinstructiuni cu parametrii, apelul
macroinstructiunilor cu parametrii, crearea propriilor fisiere antet;
- utilizarea unui proiect si a fisierelor antet proprii;
- utilizarea bibliotecior-obiect de functii;
- utilitarul MAKE.

1
Preprocesare
Preprocesorul este un program lansat in executie automat inainte de compilare. El
executa toate directivele preprocesor incluse in program, efectuand substitutii de
texte.
Toate directivele preprocesor incluse in program incep cu caracterul # si sunt puse
inaintea oricaror declaratii de variabile sau functii (deci, sunt plasate la inceputul
programului).
Directive preprocesor
Directiva #define permite definirea unei constante simbolice.
Sintaxa folosita este:
#define <identificator_constanta> valoare
unde:
- <identificator_constanta> - specifica numele constantei simbolice definite; numele
constantei se scrie cu majuscule;
- <valoare> - specifica valoarea atribuita constantei; constantele pot contine valori
de diferite tipuri (int, float, char etc).
Ca efect, preprocesorul va substitui in program orice aparitie a identificatorului de
constanta cu valoarea acesteia. 2
Nota: Se recomanda utilizarea constantelor simbolice atunci cand se doreste sa se
asocieze o denumire mai sugestiva la o valoare. De asemenea, prin utilizarea
constantelor simbolice programul devine mai usor de modificat.
Exemple:
1. Urmatoarea directiva creaza o constanta denumita DIM_LINIE si ii atribuie
valoarea 128:
#define DIM_LINIE 128
Cand preprocesorul de C/C++ va intalni numele constantei DIM_LINIE in program,
il va inlocui cu valoarea ei.
2. Urmatoarele directive creaza doua constante denumite TRUE si FALSE si le
atribuie valoarea 1 si respectiv 0:
#define TRUE 1
#define FALSE 0
In program aceste doua constante simbolice vor fi inlocuite cu valorile lor.

3
3. Urmatorul program (macro_define.cpp) utilizeaza doua constante predefinite cu
macroinstructiunea #define.
#include <stdio.h>
#define TITLU "Acesta este un exemplu de directiva preprocesor"
#define CAPITOL "Macroinstructiunea #define"
void main()
{printf("%s\n", TITLU);
printf(“%s”,CAPITOL);}
Inainte de a incepe compilarea, preprocesorul va inlocui fiecare nume de constanta
cu valoarea ei, ca mai jos:
void main()
{printf("%s\n", "Acesta este un exemplu de directiva preprocesor");
printf(“%s” ,“Macroinstructiunea #define");}

4
Utilizarea constantei predefinite __FILE__
Constanata predefinita __FILE__ este utilizata pentru a memora numele fisierului
sursa curent.
Urmatorul program (constanta_FILE.cpp) ilustreaza modul de utilizare a constantei
__FILE__:
#include <stdio.h>
void main()
{
printf("Programul %s este in versiunea BETA\n", __FILE__);}
Dupa executia programului pe ecran se afiseaza urmatoarele:
Programul constanta_FILE.cpp este in versiunea BETA
Utilizarea constantei predefinite __cplusplus
Dupa cum s-a vazut pana acum, unele dintre instructiunile si comenzile prezentate
sunt valabile si in C si in C++, pe cand altele se aplica numai pentru C++. Constanta
__cplusplus este folosita pentru a testa modul de lucru al compilatorului care poate
fi C++ sau C standard. Daca se utilizeaza un compilator de C standard, constanta va
fi nedefinita.
Observatie: Directiva de preprocesare #ifdef folosita in programul urmator testeaza
daca programul are definit sau nu un identificator sau o constanta simbolica cu
5
numele respectiv.
Urmatorul program (testcpp1.cpp) ilustreaza modul de utilizare a constantei
__cplusplus pentru a determina modul de lucru curent al compilatorului:
#include<conio.h>
#ifdef __cplusplus
#include <iostream.h>
#else
#include <stdio.h>
#endif
void main()
{
#ifdef __cplusplus
cout << "Se utilizeaza C++";
#else
printf("Se utilizeaza C\n");
#endif
getch(); }
Dupa executia programului pe ecran se afiseaza:
Se utilizeaza C++
Nota: Cele mai multe compilatoare accepta optiuni in linia de comanda sau optiuni
de compilare in mediul de programare respectiv, care le indica sa compileze folosind
modul de lucru (limbajul) C++ sau modul de lucru (limbajul) C standard. 6
Utilizarea constantelor predefinite __DATE__ si __TIME__
Constanata predefinita __DATE__ este utilizata pentru a memora un sir de caractere
de forma "Mmm dd yyyy" care contine data calendaristica la care s-a inceput
compilarea.
Constanata predefinita __TIME__ este utilizata pentru a memora un sir de caractere
de forma "hh:mm:ss" care contine ora la care s-a inceput compilarea.
Urmatorul program (const_TIME_DATE.cpp) ilustreaza modul de utilizare a
constantelor __DATE__ si __TIME__:
#include <stdio.h>
#include<conio.h>
void main()
{
printf("Ora la care s-a efectuat compilarea %s \n", __TIME__);
printf("Data la care s-a efectuat compilarea %s \n", __DATE__);
getch();
}
Dupa executia programului pe ecran se afiseaza urmatoarele:
Ora la care s-a efectuat compilarea 14:32:01
Data la care s-a efectuat compilarea Apr 19 2015
7
Utilizarea directivei de preprocesare #define pentru macroinstructiuni cu
parametrii
Macroinstructiunile permit realizarea unor operatii asemanatoare functiilor care
lucreaza cu parametrii. Exista totusi cateva deosebiri.
Cand preprocesorul intalneste, intr-un program, o referire la o macroinstructiune,
aceasta este inlocuita cu instructiunile componente inainte sa inceapa compilarea.
Prin urmare, daca programul utilizeaza de 10 ori o anumita macroinstructiune, vor fi
inserate 10 copii diferite ale macroinstructiunii, printre celelalte instructiuni ale
programului. Rezulta ca dimensiunea programului executabil va creste.
Spre deosebire de macroinstructiuni, atunci cand programul utilizeaza o functie, el
contine numai o copie a codului functiei, ceea ce ii reduce dimensiunea. Cand
utilizeaza o functie, programul executa codul functiei. Totusi, functiile au
dezavantajul prelucrarilor suplimentare pe stiva pe care le implica fiecare apel. De
aceea executia functiei dureaza ceva mai mult decat cea a unei macroinstructiuni
echivalente.
De obicei, macroinstructiunile se folosesc pentru prelucrari care realizeaza un
numar redus de operatii.

8
Crearea propriilor macroinstructiuni cu parametrii
Crearea unei macroinstructiuni cu parametrii se realizeaza cu ajutorul directivei
preprocesor #define.
Sintaxa definitiei unei macroinstructiuni este:
#define <nume_macro>(<lista_nume_parametrii_formali) (<corp_macro>)
unde:
- <nume_macro> - specifica numele unei macroinstructiuni cu parametrii;
- <lista_nume_parametrii_formali> - specifica o lista de identificatori delimitati prin
virgula; fiecare identificator joaca rolul unui argument formal sau inlocuitor
(placeholder) nu ca la functiile C/C++ unde parametrii formali primesc valorile
parametrilor reali din apelul functiei;
- <corp_macro> - specifica setul de instructiuni de executat.
Nota:
1. Nu se plaseaza spatiu intre numele macroinstructiunii si parametrii sai formali.
Daca se lasa spatiu atunci preprocesorul inlocuieste in program si secventa care
reprezinta lista parametrilor formali si setul de instructiuni care reprezinta corpul
macroinstructiunii.
9
2. In corpul macroinstructiunii se poate folosi caracterul punct si virgula (;). Dar
acest caracter trebuie folosit cu grija pentru ca preprocesorul va plasa acest caracter
la fiecare aparitie in cadrul programului.
De exemplu, sa presupunem ca s-a plasat caracterul punct si virgula la sfarsitul
definitiei macroinstructiunii SUMA, asa cum se ilustreaza mai jos:
#define SUMA(x, y) ((x) + (y));
Daca aceasta macroinstructiune se apeleaza intr-o functie cum ar fi printf(), atunci va
rezulta eroare de compilare deoarece preprocesorul pune si punctul si virgula
existenta dupa macroinstructiune.
3. Daca definitia unei macroinstructiuni trebuie sa continue pe linia urmatoare, se
plaseaza un caracter backslash (\) la capatul liniei.
4. In corpul macroinstructiunii identificatorii parametrilor formali trebuie sa fie
inclusi intre paranteze pentru a accepta expresii.
5. Dupa cum se observa din definitia macroinstructiunii de mai sus, aceasta nu are
specificat un tip de data pentru rezultatul pe care il returneaza, ca la functie.

10
Apelul unei macroinstructiuni cu parametrii in cadrul programului se face dupa
sintaxa:
<nume_macro> (<lista_nume_parametrii_actuali>)
unde:
- <lista_nume_parametrii_actuali> - specifica o lista a parametrilor actuali (delimitati
prin virgula), care trebuie sa coincida ca numar si ordine cu fiecare dintre parametrii
formali din definitia macroinstructiunii.
Nota: La apelul macroinstructiunii se poate lasa spatiu intre numele
macroinstructiunii si lista parametrilor actuali
La intalnirea unui apel de macroinstructiune, in cadrul programului, preprocesorul
executa doua seturi de inlocuiri (substituiri):
- mai intai, numele macroinstructiunii si parametrii formali din paranteze, care sunt in
definitia macroinstructiunii, sunt inlocuiti, in program, cu setul de instructiunii din
corpul macroinstructiunii;
- apoi, orice nume de parametru formal intalnit in corpul macroinstructiunii este
inlocuit cu numele parametrului corespunzator care apare in lista parametrilor actuali.

11
Urmatorul program (macro_suma.cpp) utilizeaza macroinstructiunea SUM pentru a
aduna doua valori:
#include <stdio.h>
#include<conio.h>
#define SUM(x, y) ((x) + (y))
void main()
{printf("Aduna 3 + 5 = %d\n", SUM(3, 5));
printf("Aduna 3.4 + 3.1 = %f\n", SUM(3.4, 3.1));
printf("Aduna -100 + 1000 = %d\n", SUM(-100, 1000));
getch();}
In cadrul definitiei macroinstructiunii SUM, x si y reprezinta parametrii formali ai
macroinstructiunii.
Atunci cand preprocesorul intalneste in program un apel al macroinstruciunii cum ar
fi SUM(3, 5) se efectueaza urmatoarele substituiri:
- mai intai, SUM(x, y) cu (x) + (y) si
- apoi, x cu 3 si y cu 5.
In program substituirile vor avea ca rezultat urmatorul cod:
printf("Aduna 3 + 5 = %d\n", ((3) + (5)));
printf("Aduna 3.4 + 3.1 = %f\n",((3.4) + (3.1)) );
12
printf("Aduna -100 + 1000 = %d\n", ((-100) +(1000)));
Urmatorul program (macro_minmax.cpp) foloseste macroinstructiunile MIN si
MAX pentru a calcula minimul si maximul dintre doua valori:
#include <stdio.h>
#include<conio.h>
#define MIN(x, y) (((x) < (y)) ? (x): (y))
#define MAX(x, y) (((x) > (y)) ? (x): (y))
void main()
{printf("Maximul dintre 10.0 si 25.0 este %f\n", MAX(10.0, 25.0));
printf("Minimum dintre 3.4 si 3.1 este %f\n", MIN(3.4, 3.1));
getch();}
Substituirile preprocesorului vor avea ca rezultat urmatorul cod:
printf("Maximul dintre 10.0 si 25.0 este %f\n", (((10.0) > (25.0)) ? (10.0) : (25.0)));
printf("Minimum dintre 3.4 si 3.1 este %f\n", (((3.4) < (3.1)) ? (3.4) : (3.1)));

13
Urmatorul program (creare_macroinstr.cpp) creaza macroinstructiunea cu numele
alocare_dim pentru alocarea dinamica a unui bloc de memorie de n elemente de tip
int sau float.
#include<conio.h>
#include<iostream.h>
#define alocare_dim(tip, n) (tip*)malloc(sizeof(tip)*n)
void main(){
int n, i;
int * intreg_p;
float * real_p;
cout<<"Introduceti nr. de elemente ale tabloului: ";
cin>>n;
intreg_p=alocare_dim(int,n);
if(intreg_p){
cout<< "Introduceti elementele tabloului de numere intregi:"<<endl;
for (i = 0; i < n; i++)
cin>>intreg_p[i]; }
real_p=alocare_dim(float,n);
if(real_p){
cout<< "Introduceti elementele tabloului de numere reale:"<<endl;
for (i = 0; i < n; i++)
cin>>real_p[i]; }
getch(); 14
}
Directiva #include este utilizata pentru a include intr-un program un fisier antet
(header) specific unei biblioteci standard de functii C/C++ sau creat de programator.
Un fisier antet (header) contine prototipuri de functii, declaratii de constante si
definitii de macroinstructiuni. Fisierul antet are extensia .h. Fisierul antet este
specific fiecarei bibliotecii standard de functii C/C++ sau este creat de catre
programator.
Pentru a include intr-un program un fisier antet se utilizeaza directiva
preprocesor #include. Directiva #include are doua formate de sintaxa:
a) #include <<nume_fisier_antet>.h>
b) #include “< nume_fisier_antet>.h”.
In varianta a) compilatorul de C/C++ va cauta respectivul fisier antet mai intai in
propriul sau director de fisiere antet (specificat prin optiuni sau prin variabile de
mediu in functie de compilator). De regula, compilatorul de C/C++ plaseaza fisierele
antet specifice bibliotecilor run-time in subdirectorul include a mediului de
programare respectiv, dar nu este o regula generala.
In varianta b) compilatorul va cauta fisierul antet mai intai in interiorul directorului
curent, iar dupa aceea, daca nu este gasit, in directoarele standard. Forma cu „”
permite si specificarea caii complete catre fisierul inclus; in acest caz, nu se mai face
cautarea si in directoarele standard.
15
Exemple:
1. #include <math.h> - include in program fisierul antet specific bibliotecii de functii
matematice a compilatorului de C/C++, existent in directoarele standard.
2. #include <iostream.h> - include in program fisierul antet specific bibliotecii cu
functii de intrare/iesire a compilatorului C/C++, existent in directoarele standard .
3. #include <stdio.h> - include in program fisierul antet specific bibliotecii cu functii
de intrare/iesire a compilatorului C/C++, existent in directoarele standard.
4. #include “antetul_meu.h” - include in program fisierul antet cu numele
“antetul_meu.h” creat de programator in directorul curent; daca nu este gasit este
cautat apoi in directoarele standard ale compilatorului C/C++.
5. #include “C:\mariana\Limbajul C\functii_proiect.h” – include in program fisierul
antet cu numele “functii_proiect.h” creat de programator in directorul
“C:\mariana\limbajul C”; daca fisierul nu exista nu mai este cautat in alta parte si se
genereaza o eroare de compilare.

16
Compilare conditionata
Compilarea conditionata permite sa se aleaga dintr-un text general partile care se
compileaza impreuna.
Compilarea conditionata se realizeaza folosind constructiile: #ifdef , #ifndef,
#ifdef-else, #if defined.
Acestea pot fi folosite pentru dezvoltarea programelor si pentru scrierea codului mai
portabil de la o masina la alta.
Directivele #ifdef si #ifndef
Pentru a testa daca un anumit identificator (constanta predefinita de compilator,
constante simbolice si macroinstructiuni definite de programator) a fost definit
anterior in program, preprocesorul utilizeaza directiva #ifdef.
Sintaxa directivei este:
#ifdef <nume_simbol>
<set_instructiuni>
#endif
Efectul directivei este: daca simbolul respectiv a fost definit anterior in program,
preprocesorul va efectua instructiunile din <set_instructiuni> pana la intalnirea
instructiunii #endif. 17
Directiva #ifndef se foloseste atunci cand se doreste ca preprocesorul sa efectueze
anumite instructiuni daca programul nu a definit anterior un anumit simbol.
Sintaxa directivei este:
#ifndef <nume_simbol>
<set_instructiuni>
#endif
Urmatoarea instructiune utilizeaza directiva #ifndef pentru a indica preprocesorului
sa defineasca macroinstructiunea _majusc (care returneaza codul ASCII al
caracterului transformat in majuscula din parametrul macroinstructiunii) daca nu a
fost definita una similara in program ca in exemplul urmator:
#include<conio.h>
#include<iostream.h>
#ifndef _majusc
#define _majusc(c)((((c) >= 'a') && ((c) <= 'z')) ? (c) - 'a' + 'A' : c)
#endif
void main()
{
char litera = 'i' ;
cout<<"Codul ASCII pentru: "<< litera<< " este:
"<<_majusc(litera)<<endl ;
18
getch(); }
Directiva #ifdef-else se foloseste atunci cand se doreste ca preprocesorul sa execute
un set de instructiuni daca conditia testata cu #ifdef este adevarata si alt set de
instructiuni daca conditia este falsa.
Sintaxa directivei este:
#ifdef <nume_simbol>
<set_instructiuni_1>
#else
<set_instructiuni_2>
#endif

Intr-un slide anterior s-a prezentat modul de folosire al acestei directive preprocesor
impreuna cu constanta predefinita __cplusplus.

19
Directiva #if defined
Directiva #if defined este folosita tot pentru testarea definirii unui simbol.
Sintaxa directivei este:
#if defined(<nume_simbol>)
<set_instructiuni>
#endif
Aceasta directiva are avantajul ca da posibilitatea de a combina testarile, intrucat este
compusa din directiva #if si operatorul defined.
Urmatoarea directiva #if defined testeaza daca simbolul BIBLIO_M a fost definit si
in acelasi timp daca simbolul FACT_M nu a fost definit anterior in program. Daca
aceasta conditie este adevarata atunci se include fisierul antet “fis_meu.h”:
#if defined(BIBLIO_M ) && !defined(FACT_M)
#include “fis_meu.h”
#endif
Nota: Se poate folosi #if defined pentru a construi conditii care utilizeaza operatorii
logici ai limbajului C/C++ (inclusiv &&, | | si !).
20
Utilizarea unui proiect si a fisierelor antet proprii
O aplicatie C/C++ nu este alcatuita in mod obligatoriu dintr-un singur fisier sursa.
Definitiile functiilor din care este alcatuit programul se pot afla in mai multe fisiere.
Acest lucru permite elaborarea aplicatiilor in echipa, precum si reutilizarea anumitor
functii.
In final, dupa elaborarea tuturor fisierelor sursa, acestea pot fi asamblate, prin
crearea unui proiect.

In mediul de programare
C++ Builder XE5, crearea
unui nou proiect se
realizeaza cu ajutorul
optiunii New -> Other ->
Console Application din
meniul File al mediului de
programare. Se deschide o
fereastra in care se
selecteaza numele
fisierului sursa (.cpp) care
contine functia main () pe
baza caruia se va crea
proiectul intr-un anume
director. 21
Dupa efectuarea pasului mentionat, pe ecran apare fereastra de mai jos.

22
La pasul urmator se redenumeste proiectul (care are exensia .cbproj ) si se salveaza in
directorul in care se doreste sa existe acesta. S-a dat numele
proiect_exemplu1.cbproj.

23
Pentru adaugarea unui fisier-sursa (.c sau .cpp) se selecteaza optiunea Add din
meniul contextual (pop-up), care apare dupa ce se executa clic cu butonul drept pe
nodul proiectului. S-a adaugat fisierul functii_proiect.cpp.

24
Astfel, s-a creat proiectul cu numele proiect_exemplu1.cbproj cu doua fisiere-sursa :
- functii_proiect.cpp , contine doua functii care efectueaza urmatoarele: genereaza
toate numerele prime mai mici decat n prin metoda ciurul lui Eratostene si calculeaza
produsul elementelor de deasupra diagonalei unei matrice patratice cu n linii si n
coloane (functii explicate deja in lectia 8).
- proiect_exemplu1.cpp, contine functia main() in cadrul careia vom apela cele doua
functii. Tot in acest program se citeste numarul pana la care se doreste generarea
numerelor aleatoare si, de asemenea, numarul de linii ale matricei patratice (program
prezentat deja in lectia 8).
Continutul fisierului “functii_proiect.cpp” este:
#include <iostream.h>
void gen_nr_prim (int ciur [], int n)
{
int i, j;
for (i=2; i<n; i++) //initial toate numerele sunt in ciur, presupuse prime
ciur [i] = 1;
for (i=2; i*i<=n; i++)
if (ciur[i]) //i este prim
for (j=2; j*i<n; j++) // se cern toti multiplii lui i
ciur[i*j] = 0;
for (i=2; i<n; i++)
if (ciur[i])
cout << "Numarul prim generat este " << i << endl; 25
}
double prod_sus_dig (int *a[], int n)
{
int i, j;
double p = 1;
for (i=0; i<n-1; i++)
for (j=i+1; j<n; j++)
p = p*a[i][j];
return p;
}
Continutul fisierului “proiect_exemplu1.cpp” este:
#include <iostream.h>
void gen_nr_prim (int *, int );
double prod_sus_dig (int *[], int );
void main ()
{int *a, nr;
int **matr; // adresa de inceput a vectorului de pointeri la linii
int lin, col, aloc = 0;
int inum = 1;
int i, j;
double produs;
cout << "Introduceti numarul n pana la care se vor genera numere prime: ";
cin >> nr;

26
a = new int [nr];
if (a)
{gen_nr_prim (a, nr);
delete a;}
else
cout << “Alocare esuata";
cout << "Introduceti numarul de linii ale matricei patratice "; cin >> lin;
col = lin;
matr = new int *[lin]; // alocare zona de memorie pentru pointerii de linie
if (!matr)
{cout << “Alocare esuata\n";
aloc = 1;}
else
{for (i = 0; i < lin; i++)
{
matr[i] = new int[col]; // alocare zona de memorie pentru elementele fiecariei linii
if (!matr[i])
{cout << “Alocare esuata\n";
aloc = 1;}
else
aloc = 0;}
}

27
if (!aloc)
{
for (i=0; i<lin; i++)
for (j=0;j<col; j++)
matr[i][j]=inum++;
produs = prod_sus_dig (matr, lin);
cout << "Produsul elementelor de deasupra diagonalei principale este " << produs;
delete *matr; //dealocarea zonei elementelor matricei
delete matr; //dealocarea zonei pointerilor de linie
}
}

Pentru stergerea unui fisier-sursa (.c sau .cpp) se selecteaza optiunea Remove From
Project din meniul contextual (pop-up) care apare dupa ce se executa clic cu butonul
drept pe nodul dorit a fi sters din proiect.
Pentru transformarea proiectului in fisier executabil, se selecteaza optiunea Make din
meniul contextual obtinut prin executia cu butonul drept al mouse-ului pe nodul
numelui proiectului. Programul executabil va fi un fisier cu numele proiectului
(proiect_exemplu1.exe) si extensia .exe.

28
Utilizarea unui fisier antet impreuna cu programele C/C++ realizate
Daca o aplicatie informatica realizata in C/C++ contine mai multe functii care se afla
in fisiere-sursa distincte sau in biblioteci rune-time distincte, este util sa se creeze un
fisier antet propriu aplicatiei (cu extensia .h). In acest fisier se pot include declaratiile
tuturor functiilor folosite de aplicatia informatica, constante predefinite sau specifice
aplicatiei si macroinstructiuni proprii aplicatiei.
De exemplu, sa recream proiectul prezentat deja, astfel incat el sa foloseasca si un
fisier antet creat de programator.
Fisierul antet functii_proiect.h se creaza tot cu ajutorul mediului de programare
C++Builder. Acest fisier contine numai declaratiile functiilor prezentate deja, ca mai
jos:
Functii_proiect.h
void gen_nr_prim (int *, int );
double prod_sus_dig (int *[], int );
Adaugarea la proiect a acestui fisier header se face la fel ca pentru orice fisier-sursa.

29
Dupa adaugarea acestui fisier header, proiectul proiect-exemplu2.cbproj arata astfel:

30
Programul principal cu numele proiect_exemplu2.cpp face apel la fisierul antet cu
numele functii_proiect.h, ca mai jos:
#include <iostream.h>
#include <conio.h>
#include "functii_proiect.h"
void main ()
{
//instructiuni program
}
Fisierul-sursa “functii_proiect.cpp” ramane neschimbat.
Apoi proiectul proiect_exemplu2.cbproj se transforma in program executabil.

31
Utilizarea bibliotecior-obiect de functii
Crearea si utilizarea propriilor biblioteci-obiect de functii reprezinta o alta
modalitate de reutilizare a unor functii pentru aplicatii diverse.
Majoritatea compilatoarelor dispun de un program special care permite crearea de
biblioteci de functii. Mediul de programare C++Builder are inglobat programul Tlib
care permite crearea de fisiere biblioteci-obiect de functii (cu extensia .lib).
Crearea si gestionarea unui fisier biblioteca-obiect de functii
Majoritatea programelor care gestioneaza biblioteci-obiect de functii permit
urmatoarelor operatii:
- crearea unei biblioteci;
- adaugarea unuia sau a mai multor fisiere-obiect la biblioteca;
- inlocuirea unui fisier-obiect cu un altul;
- stergerea unuia sau mai multor fisiere-obiect din biblioteca.
Mediul C++Builder realizeaza crearea unei biblioteci-obiect de functii cu ajutorul
unui proiect de tip Static Library.

32
Pentru crearea unui proiect de tip Static Library se procedeaza astfel:
1. Se alege optiunea New->Other a meniului File; pe ecran apare fereastra de mai
jos:

33
2. Se redenumeste proiectul (care are exensia .cbproj ) si se salveaza in directorul in
care se doreste sa existe acesta. S-a dat numele functii_proiect.lib si s-a creat in
directorul lib.
3. Pentru adaugarea fisierelor-sursa se selecteaza optiunea Add din meniul
contextual (pop-up), care apare dupa ce se executa clic cu butonul drept pe nodul
proiectului creat. Astfel, s-au adaugat doua fisiere: gen_nr_prim.cpp (care contine
functia de generare de numere prime) si prod_sus_dig.cpp (care contine functia ce
calculeaza produsul elementelor de deasupra diagonalei principale). Se observa ca nu
se mai foloseste un singur fisier care contine ambele functii ci doua fisiere care apoi
se reunesc intr-un singur fisier cu extensia .lib.
4. Se selecteaza optiunea Make din meniul contextual (pop-up), care apare dupa ce se
executa clic cu butonul drept pe nodul proiectului functii_proiect.lib.
5. Dupa parcurgerea celor patru pasi, biblioteca-obiect (cu numele functii_proiect.lib)
creata este adaugata la fisierul-proiect al aplicatiei (cu numele
proiect_exemplu3.cbproj) prin procedeul deja descris (optiunea Add pe nodul
proiectului).

34
In final fereastra in care au fost create cele doua proiecte arata astfel:

35
Un alt exemplu pentru crearea de proiecte este determinarea punctelor sa dintr-o
matrice prezentata intr-o lectie anterioara.
Proiectul are numele “prelucrari_matrice”si contine:
- fisierul “prelucrari_matrice.cpp” (contine functia main()) care apeleaza trei
functii si afiseaza punctele sa.
- fisierul header “functii_prel_matr.h” care are continutul de mai jos:

int ** citeste_matr(int&,int&);
void afis_matr(int *[],int, int);
char ** puncte_sa(int *[], int, int, int&);

S-a creata un alt proiect de tip Static Library cu numele “functii_proiect.lib”


S-a adaugat la acest proiect trei fisiere sursa:
- citeste_matr.cpp folosit pentru alocarea dinamica a zonei de memorie a
matricei si citirea maticei de la tastatura;
- afis_matr.cpp folosit pentru afisarea matricei;
- puncte_sa.cpp folosit pentru determinarea punctelor sa din matrice.
S-a folosit optiunea Make pentru crearea bibliotecii-obiect (cu numele
functii_proiect.lib).
Apoi aceasta biblioteca statica cu cele trei functii a fost adaugata la proiectul cu
numele “prelucrari_matrice.exe”
36
Codul-sursa al fisierului “prelucrari matrice.cpp” este:
#include <iostream.h>
#include<conio.h>
#include "functii_prel_matr.h"
void main(){
int **a; // adresa pointerilor la linii
char ** t_rezultat; // adresa pointerilor la sirurile de caractere
int lin, col;
int i, j;
int nr_puncte_sa;
a=citeste_matr(lin,col);
if(a){
afis_matr(a, lin, col);
t_rezultat=puncte_sa(a,lin, col, nr_puncte_sa);
if(t_rezultat){
cout<<"punctele sa sunt:"<<endl;
i=0;
while(i<nr_puncte_sa ){
cout<<t_rezultat[i]<<endl;
i++ ;}
cout<<"Numarul de puncte sa = "<<i;
delete *t_rezultat; // dealocarea zonei elementelor sir
delete t_rezultat; // dealocarea zonei pointerilor sirurilor
}
else
cout<<"alocare eronata";
delete *a; //dealocarea zonei elementelor linilor
delete a; } //dealocarea zonei pointerilor de linie
else
cout<<"Alocare esuata"; 37
getch(); }
Codul sursa pentru cele trei fisiere cu functiile apelate de programul principal este:
#include<iostream.h>
int ** citeste_matr(int &n, int &m) {
int **matr;
int aloc;
int i, j;
cout << "Introduceti numarul de linii "; cin >> n;
cout << "Introduceti numarul de coloane: "; cin >> m;
matr = new int *[n];
if (!matr)
{cout<<"Alocare esuata"<<endl;
aloc=0;}
else
{for (i = 0; i < n; i++)
{matr[i] = new int[m];
if (!matr[i])
{cout<<"Alocare esuata"<<endl;;
aloc = 0;}
else
aloc = 1;} }
if (aloc)
{
cout<<"Introduceti elementele de pe linie"<<endl;
for (i=0; i<n; i++)
for (j=0;j<m; j++)
{cout<<"matr["<<i<<","<<j<<"]=" ;
cin>>matr[i][j];}
}
return matr; } 38
#include<iostream.h>
void afis_matr(int *matr[], int n, int m){
int i,j;
for (i=0; i<n; i++)
{for (j=0;j<m; j++)
cout<<matr[i][j]<<" ";
cout<<endl;}
}
#include<iostream.h>
#include<string.h>
char ** puncte_sa(int *matr[], int n, int m, int &nr_sa ) {
int i, j, k;
int aloc=1;
int puncte_sa;
nr_sa=0;
char *p;
char sir[10];
char ** tablou_rezultat;
tablou_rezultat = new char*[50];
if (tablou_rezultat)
for (i = 0; i < 50; i++){
tablou_rezultat[i]=new char[50];
if (tablou_rezultat[i])
aloc=1;
else
aloc=0;
}
else
{cout<<"alocare esuata";
aloc = 0;} 39
if(aloc) {
for (i =0; i < n; i++)
for(j=0;j<m;j++){
puncte_sa = 1;
for(k=0;k<m;k++)
if(matr[i][k]<matr[i][j]) // comparare cu elementele de pe linia i
puncte_sa=0;
for(k=0;k<n;k++)
if(matr[k][j]>matr[i][j]) // comparare cu elementele de pe coloana j
puncte_sa=0;
if(puncte_sa){
//creaza elementele tabloului de siruri de caractere
strcpy(tablou_rezultat[nr_sa],"a[");
itoa(i,sir,10);
strcat(tablou_rezultat[nr_sa],sir);
strcat(tablou_rezultat[nr_sa]," ");
strcat(tablou_rezultat[nr_sa],",");
itoa(j,sir,10);
strcat(tablou_rezultat[nr_sa],sir);
strcat(tablou_rezultat[nr_sa],"]= ");
itoa(matr[i][j], sir, 10);
strcat(tablou_rezultat[nr_sa],sir);
nr_sa++; // numara punctele sa
}
}
}
return tablou_rezultat;
}
40
In final fereastra in care au fost create cele doua proiecte arata astfel:

41
Construirea aplicatiilor cu ajutorul utilitarului MAKE
MAKE este un instrument de programare care ajuta la construirea de aplicatii
complexe (ce contin fisiere cu cod-sursa, fisiere cu cod-obiect, biblioteci, alte fisiere
executabile etc dependente unele de altele) dupa ce s-au facut una sau mai multe
modificari ale fisierelor componente ale aplicatiei.
Utilitarul MAKE.exe simplifica reconstruirea unui fisier executabil dupa ce s-au
efectuat modificari in diferitele module componente ale aplicatiei informatice
complexe (reface atat compilarea cat si link-editarea).
Utilitarul MAKE functioneaza impreuna cu un fisier text ASCII specific aplicatiei.
Acest fisier (cu extensia .mak) specifica diferitele fisiere ale aplicatiei pe care
compilatorul le va utiliza pentru a construi aplicatia si listeaza pasii pe care
compilatorul si link-editorul trebuie sa ii parcurga atunci cand se modifica aplicatia.
De asemenea el verifica si dependentele intre fisierele aplicatiei.
Fisierul de tip make este asemanator programelor, adica, el contine: conditii, reguli
implicite si explicite, macrouri, directive.
Mediile de programare bazate pe Windows, cum ar fi C++Builder sau Microsoft
Visual C++ construiesc si gestioneaza fisierul de tip make atunci cand se creaza
fisierul proiect al aplicatiei si se executa optiunea Make sau Make All.

42
Atunci cind se executa comanda (optiunea) MAKE cu fisierul make corespunzator,
se va examina mai intai linia dependentelor.
Daca fisierul destinatie nu exista sau daca fisierul destinatie este mai vechi decat
oricare alt fisier de care el este dependent (ceea ce inseamna ca s-a modificat unul
dintre fisierele componente dupa ce s-a compilat ultima data fisierul destinatie),
MAKE va executa comanda care urmeaza dupa liniile de descriere a dependentelor
(de regula comanda de recompilare a aplicatiei).

Observatie: Comanda utilitarul MAKE este destul de utilizata in sistemul de operare


Unix, mai ales la instalarea unor pachete de programe care trebuie recompilate
pentru o anumita platforama hardware.

43

S-ar putea să vă placă și