Sunteți pe pagina 1din 139

+

C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL


O
PO
SC ALL – INC SRL

Curs
Programarea Orientată Obiect
SPATARU VIRGIL

++
C POO

26.11.18 0
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
1. Redactarea programelor C
1.1. Generalităţi
Mediul Borland C a fost extins la Visual C şi C++ Builder, adaptate programării
orientate obiect şi interfeţei grafice Windows 95. Limbajul C a fost extins la C++ permiţând
aplicarea conceptelor programării prin abstractizarea datelor şi programării orientate spre
obiecte.
Fişierele sursă pot avea extensia C, CP, sau CPP.
1.2. Structura unui program
Un program C este conţine o funcţie principală (main) şi eventual alte funcţii
secundare, apelate de către funcţia principală, situate la acelaşi nivel (fară imbricare).
Structura unui program este următoarea:
Directive de procesare,
Declaraţii de date globale,
Declaraţii de funcţii, sau doar [ Antete de funcţii (prototipuri) ]
Funcţia principală; 
[ Descrierea funcţiilor (implementări) ]
Se observă că descrierea funcţiilor se poate face fie în întregime înaintea funcţiei
main fie doar prototipul înainte, iar corpul după aceasta.
Comentariile se scriu între caracterele /* şi */ ( ... /* comentariu */ ... ), sau la
nivelul unui rând după caracterele // ( ... // comentariu ).
Înainte de compilare, un program este precompilat, de către un preprocesor, care
permite includerea unor fişier sursă, definirea şi apelul unror macrouri, precum şi o
compilare condiţionată.
Includerea unui fişier sursă (*.h sau *.c) se realizează prin directiva include astfel:
# include “specificator_fişier” // pentru fişiere utilizator
sau
# include <specificator_fişier> // pentru fişiere standard

Exemplu:
#include <stdio.h>; // Standard Input Output Header
#include <iostream.h>; // Console Input, Console Output

26.11.18 1
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Constantele simbolice se definesc cu ajutorul directivei define astfel:
#define Nume_constantă Şir_caractere
Exemplu:
#define Pi 3.141592 // Înlocuieşte Pi cu 3.141592
O constantă simbolică poate fi redefinită sau anulată (#undef Nume_constantă).
1.3. Funcţii
O funcţie este formată dintr-un antet şi un bloc (corp). Ea poate fi apelată dacă a
fost definită în întregime sau doar antetul său.
Antetul unei funcţii are următorul format:
Tip Nume (Listă_parametri_formali)
unde:
 Tip este tipul valorilor funcţiei (codomeniul);
 Nume este un identificator (literă urmată eventual de alte litere sau cifre);
 Listă_parametri_formali conţine parametrii formali separaţi prin ‘,’.

Exemplu: int Min (int a, int b)


{ if (a<b) return a; else return b; }

Observaţie. Prototipul unei funcţii este antetul acesteia urmat de ‘;’ .


Corpul unei funcţii are următoarea structură:
{
Declaraţii
Instrucţiuni
}

Exemple: int Cmmdc(int a, int b) // Cmmdc(a,b)


{
if (b= =0) return a;
else return Cmmdc(b,a % b); // Cmmdc(b,a Mod b);
}

int cmmdc(int a, int b) // cmmdc(a,b)


{ int rest;
do { rest=a%b;
a=b;
b=rest; }
while (rest!=0); // rest  0;
return a;
}

26.11.18 2
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
1.4. Elementele limbajului
Alfabetul limbajului C este format din litere mari şi mici, cifre şi caractere speciale
(\n=CrLf, \t=Tab).
Identificatorii sunt formaţi din literă_ urmată eventual de litere_ sau cifre
(caracterul ‘_’ poate fi utilizat pe post de literă).
Există cuvinte cheie care pot fi utilizate doar în contextul definit (de exemplu case,
float, int, long, return, short, static, structure, switch, union, unsigned, void).
Tipurile predefinite sunt următoarele:
 int (Z  [-215,215-1]),
 short (Z  [-215,215-1]),
 long (Z  [-231,231-1]),
 unsigned (N  [0,216-1]),
 float (Q*  [-3.410-38, 3.41038]),
 double (Q*  [-1.710-308, 1.710308]),
 char (cod ASCII).

Constantele numerice pot fi zecimale (123, 123Long, 111long), octale (077), hexa
(0xabba, 0Xfac), sau flotante (2.71828, 6.023e23, 6.023E23).
Constantele de tip caracter pot fi afişabile ('A', '0', '"') sau funcţionale
('\b'=Backspace, '\r'=Return, '\n'=Newline, '\''=Apostrof, '\\'=Backslash, '\v'=Verticaltab,
'\f'=Salt de pagină, '\0'=Null.
Constantele de tip şir de caractere se scriu între ghilimele ("Mesaj").

Declararea variabilelor simple se face astfel:


Tip Listă_identificatori_de_variabile;
Exemplu:
int i, j; float x,y; char c;

Declararea unui tablou se realizează astfel:


Tip Nume_Tablou [d1] [d 2] ... [di] ... [dn]; // indicele ki: 0 ki<di
Exemple:
float x[100]; x[0]=1; ... x[99]=100; // x este pointer la primul element
int a[2,2]; a[0][0]=1; a[0][1]=2; // a conţine adresa tabloului
a[1][0]=3; a[1][1]=4;

26.11.18 3
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
2. Variabile
Variabilele pot fi statice sau dinamice, locale sau globale.
2.1. Variabile globale
Declararea unei variabile globale se face la începutul unui fişier sursă (în afara
tuturor funcţiilor) şi poate fi referită până la sfârşitul programului (în orice funcţie).
Utilizarea lor în alte fişiere sursă se poate face doar dacă acestea sunt declarate ca variabile
externe:
extern declaraţie_variabilă
Exemplu:
VExterne.Cpp:
#include <stdio.h>;
#include "Fs.h";
float Pi=3.14; // variabilă globală
void main (void)
{ float r;
printf(" Dati raza cercului : "); scanf("%f",&r);
printf(" Lungimea cercului = %f \n",LungC(r));
scanf ("\n");
}

Fs.h:
float LungC (float r)
{
extern float Pi; // variabilă externă
return 2*Pi*r;
}

2.2. Variabile locale


O variabilă locală este utilizabilă (vizibilă) doar în modulul sau în funcţia în care a
fost definită, putând fi alocată dinamic (variabilă automatică, alocată pe stivă) sau static
(variabilă statică, alocată în zona de memorie a programului). Implicit o variabilă locală
este automatică, iar dacă dorim ca aceasta să fie statică, declaraţia ei trebuie să fie precedată
de cuvântul cheie static:
static declaraţie_variabilă
Funcţiile au implicit atributul extern, deci pot fi apelate din alte fişiere sursă, dar
dacă dorim ca acest apel să nu fie permis, atunci se vor declara statice prin scrierea
cuvântului cheie static înaintea antetului acesteia ( static antet_funcţie ) ?!.

26.11.18 4
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
VLocale.Cpp:
#include <stdio.h>;
#include "Sursa.h";
void main (void)
{ int n;
printf(" Dati un numar < 256 : "); scanf("%d",&n);
printf(" Valoarea in Hexa este ");
Print_Hexa(n);
// Print_Byte(n/256); Print_Byte(n%256); !?
scanf ("\n");
}

Sursa.h:
static int Cifra_Hexa (int s)
{
static int c;
if (s<10) c=s+'0';
else c=s+'A'-10; // c=s+'0'+7
return c;
}
static void Print_Byte(int b)
{
static int H = b / 16;
static int h = b % 16;
printf("%c%c",Cifra_Hexa(H),Cifra_Hexa(h));
}
void Print_Hexa(int z)
{
static int HH = z / 256; Print_Byte(HH);
static int hh = z % 256; Print_Byte(hh);
}

2.3. Variabile de tip registru


Există posibilitatea ca într-un registru liber să fie alocată o variabilă care este
utilizată frecvent, penntru a mări viteza de execuţie. În registrii se pot memora parametri
funcţiilor sau variabile automatice de tip int, char sau pointer. Pentru ca o variabilă să fie
memorată într-un registru, declaraţia ei trebuie să fie precedată de cuvântul cheie register:
register declaraţie_variabilă
Exemplu:
float f ( register int i );
{ register int n; register char c; ... }

26.11.18 5
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
2.4. Iniţializarea variabilelor

Variabilele simple se iniţializează printr-o declaraţie de forma:


Tip Identificator_de_variabilă = Expresie

Exemple:

float f ( int n );
{ int i=1;
int m=n/2;
...
}

Tablourile se iniţializează printr-o declaraţie de forma:


Tip Ident_tablou [n] = {Expresie1, Expresie2,..., Expresiem}
unde mn, iar dacă n este omis, atunci n=m.
Exemple:

int X [13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};


int Y [ ] = {1,2,3,4,5,6,7};
int A[3][ ] = { {1,2,3},{4,5},{6} }; // {{1,2,3},{4,5,?},{6,?,?}}

Şirurile de caractere se iniţializează astfel:


char Ident_string [n] = "Şir_caractere"
iar n poate fi este omis.
Exemple:

char Mesaj [100] = "Zarurile vor fi aruncate ...";


char Alt_Mesaj [] = {"Zarurile au fost aruncate !"};

26.11.18 6
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
3. Expresii
O expresie este formată din operanzi, operatori şi paranteze pentru prioritate, şi
are o valoare şi un tip. Asocierea operatorilor se face de la stânga la dreapta, cu excepţia
operatorilor unari şi de atribuire, care se asociază de la dreapta la stânga.
Operanzii pot fi: constante, constante simbolice, variabile simple sau structurate
(tablouri, structuri, sau elemente ale acestora), funcţii sau apeluri de funcţii.
3.1. Operatori

Operatorii, în ordinea descrescătoare a priorităţii sunt următorii:

 ( ) [ ]
  (unar) + (unar) * (unar) & (unar) ! ~ ++   (tip) sizeof
 * / %
 + 
 << >>
 < <= >= >
 == !=
 &
 ^
 |
 &&
 ||
 ?: (ternar)
 = *= /= %= += = <<= >>= &= ^= |=
 ,

Operatorii aritmetici sunt următorii:

+ ,  , * , / , % (mod), pentru adunare, scădere, înmulţire, cât (împărţire), rest.


Exemple:
int i, j ;
int cat = i / j; // 13 / 5 = 2
int rest = i % j; // 13%5 = 3

26.11.18 7
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Operatorii relaţionali sunt următorii:

< , <= , > , >= , == , != , pentru < ,  , > ,  , = ,  , rezultatul (valoarea


expresiei relaţionale) fiind 1 pentru adevărat, iar 0 pentru fals.
Exemple:
int i=1; int j=2 ;
... i<=j ... // == 1
... i==j ... // == 0

Operatorii logici sunt:


! (Not) , && (And) , | | (Or).
Exemplu:
Xor = !x&&y || x&&!y // x Xor y = Not x And y Or x And Not y

Deoarece nu există tipul boolean, valoarea fals este reprezentată prin 0, iar
adevărat prin orice valoare diferită de 0.

Operaţii pe biţi se pot realiza utilizând următorii operatori:


~ (complementul faţă de FFFF, schimbă fiecare bit), << (deplasare la stânga),
>> (deplasare la dreapta), & (And bit cu bit), ^ (Xor bit cu bit), | (Or bit cu bit).

Exemplu:
// ASCII
#include <stdio.h>;
#include <conio.h>;
int Cifra(int c) // cifra hexa: 01...9AB...F
{
if (c<10) return c | '0';
else return (c-9) | '@';
}
int c;
void main (void)
{ textbackground(BLUE); textcolor(WHITE); clrscr();
do { printf(" Dati un caracter #Esc : "); c=getch();
printf(" ... Hexa = %c%c \n",Cifra(c>>4),Cifra(c&0xF)); }
while (c!=0x1B);
}

26.11.18 8
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO

Operaţia de atribuire se realizează astfel:


Var = Expresie; // expresie de atribuire cu tipul Var
Există posibilitatea realizării de atribuiri multiple prin expresii de forma:
Varn = ... = Var2 = Var1 = Expresie;
Mai există o facilitate utilizând o operaţie de atribuire de forma:
Var = Expresie; // unde {+, , *, /,%, &, ^, | , <<, >>}
având semnificaţia:
Var = Var  Expresie;
Exemple:
v = e = 2.7181828; // v = (e = 2.7181828);
x += dx; y  = dy; // x = x+dx; y = y  dy;
n <<= k; // n = n*2k

Operatorii de incrementare / decrementare sunt ‘++’ respectiv ‘’ prin care se


măreşte, respectiv se micşorează, valoarea operandului cu unu.
Aceştia pot fi utilizaţi:
 în forma prefixată:
++ operand ; respectiv  operand ; // valoarea expresiei, după aplicarea lor
 în forma postfixată:
operand ++; respectiv operand ; // valoarea expresiei, înainte de aplicare

Exemple:
a = ++b; // b=b+1; a=b;
a = b ; // a=b; b=b1;

Operatorul de conversie explicită (expresie cast) realizează conversia unui


operand într-un tip precizat astfel:
(Tip) operand ;
Exemplu:
int a=12; int b=5;
float c=a/b; printf(" a Div b = %5.2f \n", c); // a Div b = 2.00
c=(float)a/b; printf(" a / b = %5.2f \n", c); // a / b = 2.40

26.11.18 9
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Conversiile implicite (realizate automat) se fac astfel:
a) charint,
b) floatdouble,
c) (double,*)(double,double)=double,
d) (long,*)(long,long)=long,
e) (unsigned,*)(unsigned,unsigned)=unsigned.

Operatorul pentru dimensiune (sizeof) determină lungimea în octeţi a unei


variabile simple sau structurate, precum şi a unui tip de dată:
sizeof (Data) ;
Exemplu:
int a;
printf(" SizeOf int = %d \n", sizeof(a)); // SizeOf int = 2
printf(" SizeOf short = %d \n", sizeof(short)); // SizeOf short =2

Operatorii condiţionali ? : sunt utilizaţi în construcţii de forma:


Expresie1 ? Expresie2 : Expresie3 ;
Valoarea expresiei rezultat este Expresie2 dacă Expresie1 este nenulă, altfel este Expresie3 .
Exemplu:
Max = a>b ? a : b; // Dacă a>b Atunci Max=a Altfel Max=b;

Operatorul virgulă permite gruparea mai multor expresii într-una singură, aceasta
având valoarea ultimei expresii:

Expresie1 , Expresie2 , ... , Expresien ;


Exemplu:
float x0,y0,r, x, y;
printf(" Dati C(x0,y0,r) = "); scanf("%f %f %f",&x0,&y0,&r); // Cercul C
printf(" Dati P(x,y) = "); scanf("%f %f", &x, &y ); // Punctul P
printf(" %s",((x-=x0, y-=y0, x*=x, y*=y, x+y)==r*r) ? "P e pe C" : "P nu e pe C");

26.11.18 10
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
4. Operaţii de intrare/ieşire

În limbajul C nu există instrucţiuni de intrare/ieşire, aceste operaţii ralizându-se prin


funcţii aflate în bibliotecile standard. Implicit, unui program i se ataşează fişierele stdin
(intrare standard), stdout (ieşire standard ), stderr (ieşire standard pentru erori), stprn (ieşire
pentru imprimantă), stdoux (intrare/ieşire serială).
4.1. Funcţia Printf
Această funcţie realizează afişarea după un şablon, având următorul format:

int printf (Control [, Listă_Expresii]);


unde Control este şablonul (formatul) scris sub forma unui şir de caractere care conţine
mesaje şi specificatori de format corespunzători valorile expresiilor din listă. Un
specificator de format se descrie astfel:
% [–] [m[.n] ] [l] [f]
unde:
 [–] - determină alinierea la stânga, implicită fiind la dreapta,
 [m] - precizează lungimea câmpului,
 [.n] - precizează lungimea părţii zecimale, respectiv numărul de caractere,
 [ l] - conversia se va efectua din format intern long,
 [f] - determină tipul conversiei precizat prin unul din următoarele caractere:
 d - int  zecimal extern,
 o - int  octal extern,
 x - int  hexa extern (0...9,a...f),
 X - int  Hexa extern (0...9,A...F),
 u - unsigned  zecimal extern (fără semn),
 c - binar intern  caracter (char),
 s - string (şir de coduri ASCII terminat cu \0=NUL)  şir de caractere,
 f - float sau double  zecimal extern [m[.n] ], implicit n=6,
 e - float sau double  zecimal extern forma exponenţială (b*10e),
 E - float sau double  zecimal extern forma exponenţială (b*10E),
 g - se alege dintre variantele f sau e reprezentarea minimă,
 G - se alege dintre variantele f sau E reprezentarea minimă.

Funcţia printf returnează numărul de octeţi afişaţi dacă operaţia a decurs corect,
iar în caz contrar -1 (EOF):
if (EOF = = printf (Control , Listă_Expresii)) ... eroare ... ;

26.11.18 11
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
short Zi=1; char Luna[]="Ianuarie"; unsigned An=2003;
float Ina=1.8;
printf(" Zi:%d, Luna:%3.3s., An:%u \n",Zi,Luna,An); // Zi:1, Luna:Ian., An:2003
printf(" Inaltime(m):%4.2f \n",Ina); // Inaltime(m):1.80

4.2. Funcţia Scanf


Această funcţie realizează citirea datelor după un şablon, având următorul format:
int scanf (Control , Listă_Adrese_de_Variabile );
unde Control este şablonul (formatul) scris sub forma unui şir de caractere care conţine
eventual texte (obligatorii la intrare) şi specificatori de format corespunzători tipurilor
variabilelor din listă. Specificatorii de format sunt asemănători celor prezentaţi la funcţia
printf, realizând însă conversiile inverse: % [*] [m] [l] [ f ] , unde:
 [*] - un caracter opţional,
 [m] - precizează lungimea maximă a câmpului,
 [ l] - conversia se va efectua din format intern long,
 [f] - determină tipul conversiei precizat prin unul din următoarele caractere:
 d - int  zecimal extern,
 o - int  octal extern,
 x - int  hexa extern (0...9,a...f),
 X - int  Hexa extern (0...9,A...F),
 u - unsigned  zecimal extern (fără semn),
 c - binar intern  caracter (char),
 s - string  şir de caractere terminat la spaţiu sau dimensiunea m,
 f - float  flotant extern.
Adresele variabilelor de intrare sunt date prin operatorul de adrese & plasat înaintea
identificatorului fiecărei variabile (simple!): [&] Variabilă (nu este necesar pentru tablouri).
Exemplu:
short Zi; char Luna[13]; unsigned An; float Ina;
scanf(" %d %s %u %f ", &Zi, Luna, &An, &Ina); // 1 Ianuarie 2003 1.80

Funcţia scanf returnează numărul de câmpuri citite corect. Sfârşitul de fişier


(Ctrl/Z) poate fi verificat prin valoarea returnată EOF:
if (EOF = = scanf (Control , Listă_Expresii)) ... Sfârşit ... ;
Exemplu:
if (EOF==scanf(" %d %s %u %f", &Zi, Luna, &An, &Ina)) printf("Ctrl/Z");
else { printf(" Zi:%d, Luna:%3.3s., An:%u \n",Zi,Luna,An); printf(" Inaltime(m):%4.2f \n",Ina); }

26.11.18 12
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
4.3. Funcţia PutChar
Această funcţie realizează tipărirea unui caracter al cărui cod ASCII este precizat
printr-o expresie:
putchar (Expresie);
4.4. Funcţia GetChar
Aceasta, returnează codul ASCII al caracterului citit (pentru Ctrl/Z  EOF=-1):
getchar ( );
Exemplu:
char c;
do putchar (((c=getchar())>'Z')? c^' ' : c); // Litere mici  LITERE MARI
while (c!='.'); // se termină cu . 


Litere mici in Litere MARI !   getchar
LITERE MICI IN LITERE MARI ! putchar 
Se termina la . (Punct)   getchar
SE TERMINA LA . putchar 

4.5. Funcţia GetCh e


Funcţia returnează codul caracterului citit direct şi îl afişează (în ecou):
int getche ( );
Exemplu:
do putchar (((c=getche())>'Z')? c^' ' : c); while (c!='.'); // se termină cu .


LLiIt TeErReE mMiIcCiI iInN LLiIt TeErReE MMAARRII..

4.6. Funcţia GetCh


Această funcţie returnează codul caracterului citit (direct) fără ca acesta să mai fie
afişat:
int getch ( );
Exemplu:
do putchar (((c=getch())>'Z')? c^' ' : c); while (c!='.'); // se termină cu .


LITERE MICI IN LITERE MARI. // S-a tastat: Litere mici in Litere MARI.

26.11.18 13
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
5. Instrucţiuni

În limbajul C instrucţiunile se termină cu ; mai puţin cele care se termină cu }.

5.1. Instrucţiunea Vidă


Această instrucţiune se utilizează în situaţia în care este nescerară prezenţa unei
instrucţiuni şi care nu trebuie să execute nimic:

; 
5.2. Instrucţiunea Expresie
Instrucţiunea are formatul general:

Expresie ;
Exemple:
y = (x+1)*(x-1); // Atribuire: v=Expresie;
f(x,y); // Apel de funcţie: f(p1, p2,... , pn);
c++; --c; // Incrementări/Decrementări (Pre/Post fixate)

5.3. Instrucţiunea Compusă


Aceasta este formată dintr-o succesiune de declaraţii (proprii) şi instrucţiuni, incluse
între acolade:
{
Declaraţii
Instrucţiuni
}
Exemplu:
{
int i; // Variabilă locală instrucţiunii;

f (i); // i se poate utiliza doar în această instrucţiune compusă;
} ; // După } nu se pune ;

26.11.18 14
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
5.4. Instrucţiunea If
Structura alternativă cu una sau două ramuri poate fi scrisă astfel:
if (expresie) instructiune1;
[ else instructiune2; ]
Exemplu:
{ P(x,y)  I-ul Cadran (Dacă x sau y este negativ se schimbă semnul )
float x, y;
printf(" Dati P(x,y) = "); scanf("%f %f", &x,&y); // Punctul P
if (x>0) if (y<0) y=-y; // C4 else_; (instrucţiunea vidă)
else { x=-x; // C2 sau C3 (x)
if (y<0) y=-y; // C3 (y)
}
printf(" x=%5.2f, y=%5.2f \n", x,y) ;
} // trebuie pus pentru C1 instrucţiunea vidă: else_;

5.5. Instrucţiunea Switch


Pentru structura alternativă cu mai multe ramuri Case (Select) se utilizează
instrucţiunea Switch:
switch (expresie)
{ case c1 : secvenţă instructiuni 1 [ break; ]
case c2 : secvenţă instructiuni 2 [ break; ]
...
case cn : secvenţă instructiu nin [ break; ]
[ default : secvenţă instructiuni n+1 ]
}

Instrucţiunea break realizează saltul la sfârşitul instrucţiunii switch, iar în absenţa ei


se vor executa şi următoarele secvenţe de instrucţiuni.
Exemplu:
while (scanf("%d %c %d",&o1,&o,&o2)!=EOF) { // O1 o O2
switch (o & 0XFF) {
case '+' : v=o1+o2; break;
case '-' : v=o1-o2; break;
case '*' : v=o1*o2; break;
case '/' : v=o1/o2; break;
default : printf (" Op. necunoscut!%c\n",o); }
printf ("%d%c%d = %d\n",o1,o,o2,v); } // Ctrl/Z

26.11.18 15
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
// Nr.Zile / lună \\
#include <iostream.h>
#include <conio.h>
void main (void)
{ int l,a;
cout << " Dati anul : "; cin >> a;
cout << " Numar de zile ... " << endl;
for (l=1; l<=12; l++) {
cout << l << " : ";
switch (l) {
case 2 : cout << (a&3 ? 28 : 29); break;
case 4 :
case 6 :
case 9 :
case 11 : cout << 30 ; break;
default : cout << 31 ; // break;
} cout << endl;
}
getche();
}

5.6. Instrucţiunea While


Structura repetitivă pretestată poate fi scrisă astfel:
while (expresie) instructiu ne;
Exemplu:
// Program Exemplu While
#include <stdio.h>;
int i,n; long f; // f:=n!
void main (void)
{ printf("\n Dati n : "); scanf ("%d", &n);
i=(f=1)+1; while (i<=n) f*=i++; printf(" %d! = %u \n",n,f);
i=(f=1); while (i< n) f*=++i; printf(" %d! = %u \n",n,f);
scanf("\n");
}

5.7. Instrucţiunea Do_While


Structura repetitivă posttestată poate fi scrisă astfel:
do instructiu ne while (expresie);
Exemplu:
do { r=a%b; a=b; b=r; } while (c); // c!=0
cmmdc=a;

26.11.18 16
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
5.8. Instrucţiunea For

Structura repetitivă Pentru (!) poate fi descrisă astfel:


for (expresie1; expresie2; expresie3) instructiu ne
;
Instrucţiunea are acelaşi efect ca şi:
expresie1; while (expresie2) { instructiu ne; expresie3
;}
Şi invers (vezi while):
for (;expresie;) instructiune ;
Exemplu:
int i,n; long f; // f:=n!
printf("\n Dati n : "); scanf ("%d", &n);
f=1; for ( i=1 ; i<=n; i++) f*=i; printf(" %d! = %u \n",n,f);
f=1; for ( i=1 ; i<=n; ++i) f*=i; printf(" %d! = %u \n",n,f);
f=i=1; for ( ; i<=n; i+=1) f*=i; printf(" %d! = %u \n",n,f);
for (f=i=1; i<=n; ) f*=i++; printf(" %d! = %u \n",n,f);
5.9. Instrucţiunea Break
Această instrucţiune se foloseşte pentru a termina o structură repetitivă:
break;
Exemplu:
for ( ; ; ) { ...
if (expr) break;
... }

5.10. Instrucţiunea Continue


Această instrucţiune realizează saltul la sfârşitul unei structuri repetitive (pentru
while sau do_while la reevaluarea expresiei, iar pentru for la expresie3), având formatul:

continue;
Exemplu:
for (... ;... ; expr3) { ...
if (expr) continue;
... }

5.11. Instrucţiunea GoTo


Această instrucţiune realizează saltul necondiţionat şi fără revenire la instrucţiunea
ce poartă eticheta specificată, având formatul:
goto etichetă ;

Exemplu:

26.11.18 17
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
while (expr1) { ...
if (expr2) goto et;
... }
...
et: ... // instrucţiune

5.12. Apelul unei funcţii


Instrucţiunea de apel a unei funcţii este un caz particular al instrucţiunii expresie:
Nume_funcţie (Listă_parametri_actuali);

O funcţie poate fi apelată şi în cadrul unei expresii dintr-o instrucţiune:


... Nume_funcţie (Listă_parametri_ actuali) ... ;

O funcţie poate fi utilizată doar dacă a fost definită sau cel puţin a fost declarat
prototipul ei într-una din următoarele moduri:
a) Tip_ funcţie Nume_ funcţie (Lista_parametrilor_formali);
b) Tip_ funcţie Nume_ funcţie (Lista_tipurilor_parametrilor_formali);
c) Tip_ funcţie Nume_ funcţie (Void); // nu sunt parametri formali
d) Tip_ funcţie Nume_ funcţie ( ); // nu se fac verificările de tip

Apelul implicit pentru variabile simple (de bază) este prin valoare, iar pentru
tablouri prin referinţă. Apelul prin referinţă se obţine prin intermediul variabilelor de tip
pointer şi a operatorului de adresă &.
Revenirea dintr-o funcţie se poate realiza fie prin instrucţiunea return, fie automat
după ultima instrucţiune a funcţiei (situaţie în care nu se returnează nici o valoare):
return [ expresie ] ;
fiind returnată valoarea expresiei (dacă există).
Ex. 1:
#include <graphics.h> #include <math.h>
int u1,v1, u2,v2; float a, b, c, d ;
int u (float x) { return ((x-a)/(b-a)*(u2-u1)+u1); }
int v (float y) { return ((y-d)/(c-d)*(v2-v1)+v1); }
void InitGraf(void) { int Gd = DETECT, Gm; initgraph(&Gd, &Gm, "c:\\Bc\\Bgi"); }
void ViewPort(int x1,int y1,int x2,int y2) {u1=x1; v1=y1; u2=x2; v2=y2; /*rectangle(u1,v1,u2,v2);*/ }
void Window(float x1,float y1,float x2,float y2) { a=x1; d=y1; b=x2; c=y2; }
void Rectangle(float x1,float y1,float x2,float y2) { rectangle(u(x1),v(y1),u(x2),v(y2)); }
void Bar(float x1,float y1,float x2,float y2) { bar(u(x1),v(y1),u(x2),v(y2)); }
void Linie(float x1,float y1,float x2,float y2) { line(u(x1),v(y1),u(x2),v(y2)); }
void Muta(float x,float y) { moveto(u(x),v(y)); }
void Trag(float x,float y) { lineto(u(x),v(y)); }
void Rot(float &x,float &y, float x0, float y0, float Alfa) { float xp;
xp=(x-x0)*cos(Alfa)-(y-y0)*sin(Alfa)+x0;
y =(x-x0)*sin(Alfa)+(y-y0)*cos(Alfa)+y0; x = xp; }
Ex. 2:
// Ultima cifră nenulă a lui n! \\
#include <iostream.h>;
#include <conio.h>;
int Sf (int& f, int k)

26.11.18 18
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
{ int p=0;
while (!(f%k)) { f/=k; p++; }
return p;
}
main () { clrscr(); int n; int f2=0; int Uc=1;
cout << " n : "; cin >> n;
for (int i=2; i<=n; i++) { int f=i;
f2+=Sf(f,2); f2-=Sf(f,5); Uc=Uc*f%10; }
cout << " Uc= " << Uc*((f2&=3,int(f2?f2*1.4:3))<<1)%10;
getch();
}

Ex. 3:
// Calc. AB, AB \\
#include <iostream.h>;
#include <conio.h>;
int Card(int A[])
{
return A[0];
}
int Apart (int x, int A[])
{
for (int i=1; i<=Card(A); i++) if (x==A[i]) return 1; return 0;
}
void n (int A[], int B[], int C[])
{
C[0]=0;
for (int i=1; i<=Card(A); i++) if (Apart(A[i],B)) C[++C[0]]=A[i];
}
void u (int A[], int B[], int C[])
{ int i;
for (i=0; i<=Card(B); i++) C[i]=B[i];
for (i=1; i<=Card(A); i++) if (!Apart(A[i],B)) C[++C[0]]=A[i];
}
void Tip (char *Mult, int A[])
{ int i; cout << Mult << '{' ;
for (i=1; i<=Card(A); i++) cout << A[i] << ",";
cout << "\b}" << endl;
}
void main (void)
{ clrscr();
int A[]={5, 1,3,5,7,9}; Tip (" A : ",A);
int B[]={5, 1,2,3,4,5}; Tip (" B : ",B);
int AuB[10]; u (A,B,AuB); Tip (" AuB = ",AuB);
int AnB[10]; n (A,B,AnB); Tip (" AnB = ",AnB);
getche();
}

26.11.18 19
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
6. Pointeri

O variabilă p de tip pointer conţine adresa unei variabile a cărei valoare se obţine
utilizând operatorul * (*p = valoarea variabilei de la adresa conţinută în p).
Adresa unei variabile v se poate obţine prin operatorul & (&v = adresa variabilei v),
deci putem atribui unui pointer p adresa unei variabile v astfel:
p = &v;

6.1. Declararea unui Pointer

Definirea unei variabile de referinţă (legată de un Tip) se face astfel:


Tip *Var_Referinţă ;
Deci, tipul referinţă se obţine prin următoarea construcţie:
Tip *
Declararea unui pointer (care conţine o adresă nefiind însă legat de un anumit tip) se
face astfel:
void *Var_Pointer ;
Exemplu:
#include <stdio.h>;
#include <conio.h>;
#include "Crt.Cpp";
int Cifra(int c) { if (c<10) return c | '0'; else return (c-9)|'@'; }
void Cifre(int b) { printf("%c%c",Cifra(b>>4),Cifra(b&0xF)); }
void main (void)
{ int *Pointer_Int; void *p; unsigned *Pointer_Word; int x;
printf(" Dati x : "); scanf("%d",&x);
p=Pointer_Int=&x; Pointer_Word=(unsigned *) p;
printf(" x =%u \n",*Pointer_Word);
printf(" |x|=%d \n",sizeof *Pointer_Word);
printf(" |&x|=%d \n",sizeof Pointer_Word);
printf("*(&x)=");
Cifre(*Pointer_Word>>8); Cifre(*Pointer_Word&0xFF);
printf("\n");
getch();
}
Date: Dati x : 43962 Date: Dati x : -1
Rezultate : x =43962 Rezultate : x = 65535
|x| =2 |x| =2
|&x|=2 |&x|=2
*(&x)=ABBA *(&x)=FFFF

6.2. Operaţii cu Pointeri


Aceste operaţii sunt operaţii cu adresele conţinute în variabilele de tip pointer.

26.11.18 20
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
6.2.1. Incrementare / Decrementare
Aceste operaţii măresc/miocşorează valoarea de adresă spre următorul element (cu o
valoare egală cu lungimea tipului referit):
Var_Pointer + + ; Var_Pointer – – ;
Exemplu:
int Zile[]={31,28,31,30,31,30,31,31,30,31,30,31 }; int *Pointer_Int; int Luna; // 0,1,...,11
printf(" Dati luna (1-12):"); scanf("%d",&Luna);
Pointer_Int=&Zile[Luna]; Pointer_Int--; // &Zile[Luna-1]
printf(" Nr.Zile =%d \n",*Pointer_Int);

6.2.2. Adunare / Scădere a unui număr întreg


Aceste operaţii măresc/miocşorează valoarea de adresă spre alt element (cu o
valoare egală cu n · lungimea tipului referit).
Var_Pointer + n
Exemplu:
int Zile[]={0,31,28,31,30,31,30,31,31,30,31,30,31 }; int *Pointer_Int; int Luna;
printf(" Luna (1-12) : "); scanf("%d",&Luna);
Pointer_Int=Zile+Luna; printf(" Nr.Zile=%d \n",*Pointer_Int);
Pointer_Int=Zile; printf(" Nr.Zile=%d \n",*(Pointer_Int+Luna));

6.2.3. Comparare
Doi pointeri ale elementului aceluiaşi tablou pot fi comparaţi utilizând operatorii
relaţionali. Valoarea NULL marchează faptul că un pointer nu referă nici un element.
... p1 < p2 ... ; ... p1 = = p2 ... ; ... p1 != p2 ... ; ... p = = NULL ...;
Exemplu:
int Zile[]={0,31,29,31,30,31,30,31,31,30,31,30,31 }; int *luna; int Zi,Luna,An, NrZile;
printf(" Zi, Luna, An : "); scanf("%d %d %d",&Zi,&Luna,&An);
if (An&3) Zile[2]=28; if ((Zi>Zile[Luna]) || (Luna>12)) luna=NULL; else luna=Zile;
if (luna!=NULL) { NrZile=Zi; do NrZile+=*(luna++); while (luna<Zile+Luna);
printf(" A %d zi a anului \n",NrZile); }
else printf(" Data calendaristica incorecta! \n");

6.2.4. Diferenţă
Diferenţa a doi pointeri ai aceluiaşi tablou dă ca rezultat diferenţa indicilor.
Exemplu:
int Zile[]={0,31,29,31,30,31,30,31,31,30,31,30,31 }; int *luna; int Zi,Luna,An, Ziua;
printf(" An, A câta zi din an:"); scanf("%d %d",&An,&Ziua); if (An&3) Zile[2]=28;
for (luna=Zile+1; Ziua>*luna; luna++) Ziua–=*luna;
printf(" Zi:%d, Luna:%d, An:%d \n",Ziua,luna–Zile,An);

26.11.18 21
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
// Operaţ ii cu pointeri \\
#include <iostream.h>
#include <conio.h>
void Tip (int *x, int n)
{ int *p=x;
while ( p-x < n ) cout << *(p++); cout << endl;
}
void main (void)
{ clrscr();
int x[]={11,22,33,44,55,66,77}; int *p,*q;
p=x; q=&x[7];
while (q-p) cout << *(p++); cout << endl;
int &f=x[7]; p=&x[0]; q=&f;
while (q>p) cout << *(p++); cout << endl;
p=x;
while (p-x<7) cout << *(p++); cout << endl;
p=x; int n = (sizeof x) / (sizeof (int));
while ( p-x < n ) cout << *(p++); cout << endl;
p=x;
for (int i=1; i<=n; i++) cout << *(p+i-1); cout << endl;
Tip (x,n); getche();
}

6.3. Alocare dinamică a memoriei


Pentru alocarea / dealocarea variabilelor dinamice sunt utilizate următoarele două
funcţii definite în fişierele alloc.h şi stdlib.h:
 malloc, care returnează adresa zonei alocate de lungime dată n sau NULL dacă nu se

poate efectua alocarea:


void *malloc (unsigned n);
 free, care eliberează o zonă alocată, precizată prin adresa (pointerul) ei :
void *free (void *adresă);
Exemplu:
#include <stdio.h>;
#include <malloc.h>;
#include <conio.h>; #include "Crt.Cpp";
int Cifra(int c) { if (c<10) return c | '0'; else return (c-9)|'@'; }
void Cifre(int b) { printf("%c%c",Cifra(b>>4),Cifra(b&0xF)); }
void main (void)
{ unsigned *Pointer_Word;
Pointer_Word=(unsigned *) malloc(sizeof (unsigned));
printf(" Dati x : "); scanf("%d",Pointer_Word);
printf(" x =%u \n",*Pointer_Word);
printf(" |x|=%d \n",sizeof *Pointer_Word);
printf(" |&x|=%d \n",sizeof Pointer_Word);
printf("*(&x)="); Cifre(*Pointer_Word>>8); Cifre(*Pointer_Word&0xFF); printf("\n");
free(Pointer_Word); getch();
}

6.4. Pointeri la funcţii

26.11.18 22
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Numele unei funcţii fiind un pointer la acea funcţie, ea poate fi parametru actual, şi
evident trebuie descrisă ca parametru formal:
... tip (*f ) ( ), ...
Exemplu:
// Pointeri la func ţii (1) \\
#include <graphics.h> #include <stdlib.h> #include <stdio.h>
#include <conio.h> #include <math.h> #include "Graf.h" #define Pi 3.1415926
float Sin (float x) { return sin (x); } float Cos (float x) { return cos (x); }
float Sqr (float x) { return pow (x,2);} float Sqrt(float x) { return sqrt(x); }
void Grafic(float(*f)(float),float a,float b,int u1,int v1,int u2,int v2)
{ float x, p, c,d, y; ViewPort (u1,v1,u2,v2); rectangle (u1,v1,u2,v2); p=(b-a)/(u2-u1)*5;
x=a; c=d=(*f)(x); do { x+=p; y=(*f)(x); if (y<c) c=y; else if (y>d) d=y; } while (x<b);
Window(a,d,b,c); x=a; MoveTo(x,(*f)(x)); do { x+=p; LineTo(x,(*f)(x)); } while (x<b);
}
void main(void)
{ InitGraph ();
Grafic (Sin, -Pi,Pi,10,10, (int) getmaxx()/2-5, (int) getmaxy()/2-5);
Grafic (Cos, -Pi,Pi,(int) getmaxx()/2+5,10,getmaxx()-10, (int) getmaxy()/2-5);
Grafic (Sqr, -Pi,Pi,10,(int) getmaxy()/2+5, (int) getmaxx()/2-5, getmaxy()-10);
Grafic (Sqrt, 0,Pi,(int) getmaxx()/2+5,(int) getmaxy()/2+5,getmaxx()-10, getmaxy()-10);
getch(); closegraph();
}

Următorul exemplu construieşte un tabel cu valorile a patru funcţii dintr-un interval


dat [a,b] pentru o diviziune precizată (n):

// Pointeri la func ţii (2) \\


#include <iostream.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
double X(double x) { return x; }
typedef double (*Pointer_la_Functie)(double);
Pointer_la_Functie Functia[] = { X, sin, cos, tan };
char* Functii = {" x Sin Cos Tg "};
int Nr_Functii=3;
void main(void)
{ clrscr();
double a,x,b; int n;
cout << " Dati a,b, n : "; cin >> a >> b >> n; clrscr();
cout << Functii << endl << endl;
for (int i=0; i<=n; i++) {
x=a+(b-a)/n*i;
for (int j=0; j<=Nr_Functii; j++)
printf ("%7.2f",(*Functia[j])(x));
cout << endl;
} getch();
}

26.11.18 23
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
6.5. Utilizarea parametrilor din linia de comandă
Apelul unui program poate fi însoţit de o listă de parametri:
> Nume_Program Listă_Parametri 

care se poate accesa scriind antetul funcţiei principale astfel:


main ( int ArgC, char *ArgV [ ] )
unde:
 ArgC este o variabilă întreagă care conţine numărul de parametri plus unu (!),

 ArgV este un tablou care conţine adresele parametrilor din listă:

 ArgV[0] - pointer la Nume_Program (!),


 ArgV[1] - pointer la primul parametru,
 ...
 ArgV[ArgC-1] - pointer la ultimul parametru
Exemplu:
#include <stdio.h>; #include <stdlib.h>; // Calendar 2003
void main (int ArgC, char *ArgV[])
{ char *Sapt[]={"Luni","Marti","Miercuri","Joi","Vineri","Sambata","Duminica"};
int Zile[]={31,28,31,30,31,30,31,31,30,31,30,31};int Zi,Luna,luna;
if (ArgC==3) { Zi=atoi(ArgV[1]); Luna=atoi(ArgV[2]);
for (luna=1; luna<Luna; luna++) Zi+=Zile[luna-1];
printf(" %s \n",Sapt[(Zi+1)%7]);
}
else printf (" Dati in linia de comada ziua si luna (din 2003) ! \n");
} // >Calendar 15 3

6.6. Declararea c o n s t antelor


O altă modalitate de a defini o constantă este modificatorul Const astfel:
[ Tip ] const Nume [ = Valoare ] ; sau const [ Tip ] Nume [ = Valoare ] ;
Unui parametru formal declarat cu modificatorul Const nu i se mai poate schimba
valoarea în subprogramul respectiv.
Exemplu:
#include <stdio.h>; #include <conio.h>;
int Cifra(const int c)
{ const char Zero='0'; int const C40H=0x40;
if (c<10) return c | Zero; else return (c-9)|C40H;
}
void main (void)
{ const Blue=BLUE; const White=WHITE; const C0F=0xF; const Esc=0x1B; int c;
textbackground(Blue); textcolor(White); clrscr();
do { printf(" Dati un caracter #Esc : "); c=getch();
printf(" ... Hexa = %c%c \n",Cifra(c>>4),Cifra(c&C0F)); }
while (c!=Esc);
}

6.7. S t i va

26.11.18 24
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Prin stivă înţelegem o listă cu disciplina Last In First Out pentru care vom defini
următoarele trei funcţii:
 Push - adaugă un element în stivă,

 Pop - extrage un element din stivă,


 Clear - iniţializarea stivei (stivă vidă),

 Vida - verifică dacă stiva este vidă:

26.11.18 25
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO

// Fact.Cpp \\
// Stiva.h \\
#include <stdio.h>
#include <conio.h> #define DimMax 13
#include "Stiva.h" static int Stiva[DimMax]; static Next=0;
void main(void) void Push(int x)
{
{
if (Next<DimMax) Stiva[Next++]=x;
int n; unsigned long f;
else printf(" Depasire stiva \n");
printf(" Dati n : "); scanf("%d",&n); }
Clear(); while (n) Push(n--); int Pop()
f=1; while (!Vida()) f*=Pop(); { if (Next>0) return Stiva[--Next];
printf(" n! = %15lu \n",f); else { printf(" Stiva vida \n"); return 0; }
getch(); }
} void Clear() { Next=0; }
int Vida() { return (Next= =0); }

7. Recursiviate
Există posibilitatea de a defini o funcţie prin ea însăşi (recursiv).
Exemplu:
#include <conio.h> #include <iostream.h>
#define Max (x,y) (x>y ? x : y)
int a[100];
int Maxim(int n)
{
if (n= =1) return a[1];
else return Max (Maxim(n-1),a[n]);
}
void main(void)
{ int i,n; clrscr();
cout << " Dati n : "; cin >> n;
cout << " Dati A : ";
for (i=1; i<=n; i++) cin >> a[i];
cout << " Max.= " << Maxim(n);
getch();
}

26.11.18 26
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
8. Tipuri de date
Există posibilitatea de a defini noi tipuri de date şi chiar de a le denumi.

8.1. Definirea unui tip de dată (typedef)


Asignarea unei denumiri unui tip de dată se realizează astfel:
typedef tip Denumire_Tip ;
Exemplu:
typedef int Integer ; typedef float Real ;
Integer i,j; Real X[10];

8.2. Tipul enumerare (enum)


Definirea acestui tip se face astfel:
enum [Denumire] { Id0 [=Expr0], Id1[=Expr1],..., Idn[=Exprn] } [Listă_Var];

Implicit Expr0=0, iar Expri=Expri-1+1, iar dacă se declară o listă de variabile având
acest tip atunci denumirea tipului enumerare definit poate lipsi.
Exemplu:
#include <stdio.h>; // 2003 \\
#include <conio.h>;
enum { False, True } Zi_Lucratoare;
enum ZileSapt { Luni, Marti, Miercuri, Joi, Vineri, Sambata, Duminica };
enum ZileSapt Zi_Sapt; // sau ZileSapt Zi_Sapt;
void main (void)
{
int Zile[]={31,28,31,30,31,30,31,31,30,31,30,31};
int Zi,Luna,luna;
printf(" Zi, Luna : "); scanf("%d %d",&Zi,&Luna);
for (luna=1; luna<Luna; luna++) Zi+=Zile[luna-1];
Zi_Sapt=Luni; Zi=(Zi+1)%7; while (Zi--) Zi_Sapt++; // sau Zi_Sapt=Zi_Sapt+1;
if (Zi_Sapt<Sambata) Zi_Lucratoare=True;
else Zi_Lucratoare=False;
if (Zi_Lucratoare) printf(" Este o zi lucratoare \n");
else printf(" Este o zi libera \n");
getch();
}

26.11.18 27
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
8.3. Definirea unei structuri (struct)
Definirea unei structuri (înregistrări) se face astfel:
struct [Denumire] { Listă_Declaraţii_Câmpuri } [Listă_Var];

Dacă se declară o listă de variabile având acest tip atunci denumirea structurii poate
lipsi.
Referirea componentelor unei structuri se face astfel:
Denumire. Componentă;
Exemplu:
#include <stdio.h>;
#include <conio.h>;
typedef float Real;
struct Punct { Real x, y; };
struct Cerc { Punct Centru;
Real Raza; };
Real Sqr(Real x)
{ return x*x; }
void main (void)
{
Punct O = { 0, 0 }; Cerc C;
printf(" \n Cerc : "); scanf("%f %f %f",&C.Centru.x,&C.Centru.y,&C.Raza);
printf(" \n C(x0,y0,r)= %5.2f %5.2f %5.2f",C.Centru.x,C.Centru.y,C.Raza);
if (Sqr(C.Centru.x-O.x)+Sqr(C.Centru.y-O.y)<=Sqr(C.Raza)) printf(" \n C contine O");
else printf(" \n C nu cont.O");
getch();
}

Referirea componentelor unei structuri definită printr-o variabilă de tip referinţă


(pointer) se efectuează:
( *Var_Ref ). Componentă; sau Var_Ref >Componentă;
Exemplu:
...
struct Cerc { float x, y; float Raza; };
void TipCerc( Cerc *C)
{ printf(" \n C(x,y,r)= %5.2f %5.2f %5.2f", ( * C).x, ( * C).y, C  > Raza); }
void main (void)
{ Cerc C={1,2,3}; TipCerc(&C); }

26.11.18 28
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
8.4. Redefinirea unei date (union)
Redefinirea unei zone de memorie se poate face în cadrul unei uniuni astfel:
union [Denumire] { Listă_Declaraţii } [Listă_Var];
Toate componentele aflate în Listă_Declaraţii ocumă aceeaşi zonă de memorie (se
suprapun), lungimea uniunii fiind dată de maximul lungimilor declaraţiilor .
Referirea componentelor unei uniuni se face astfel:
Denumire. Componentă;
sau pentru o variabilă de tip referinţă:
( *Var_Ref ). Componentă; sau Var_Ref >Componentă;
Exemplu:
...
union U { float Real;
long unsigned Hexa; } x;
int Cifra(int c) { if (c<10) return c|'0'; else return (c-9)|'@'; }
void Cifre(int b) { printf("%c%c",Cifra(b>>4),Cifra(b&0xF)); }
void Print(unsigned x) { Cifre(x>>8); Cifre(x&0xFF); }
void main (void)
{ do { printf(" Dati un numar : "); scanf("%f",&x.Real); printf(" ... Hexa = ");
Print (x.Hexa>>16); Print(x.Hexa&0xFFFF); printf(" ... \n"); }
while (x.Hexa!=0); getch();
}

8.5. Câmpuri de biti


Există posibilitatea definirii unei structuri ale cărei câmpuri să fie formate dintr-o
secvenţă de biţi consecutivi (ai unui cuvânt). Aceste câmpuri au tipul unsigned având
fiecare o lungime precizată (în număr de biţi):
struct [Denumire] { Câmp0; Câmp1; ... ; Câmpn; } [Listă_Var];
unde câmpurile Câmpi sunt de forma:
unsigned [ Nume_Câmpi ] : Lungimei
Exemplu:
#include <stdio.h>;
struct Camp_Biti { unsigned B__0__3 : 4; unsigned B__4__7 : 4;
unsigned B__8_11 : 4; unsigned B_12_15 : 4; };
union { int Intreg; Camp_Biti Cifre_Hexa; } x ;
void Cifra(int c) { if (c<10) printf ("%c",c|'0'); else printf ("%c",(c-9)|'@'); }
void main (void)
{ do { printf(" Dati un numar : "); scanf("%d",&x.Intreg); printf("Hexa=");
Cifra(x.Cifre_Hexa.B__0__3); Cifra(x.Cifre_Hexa.B__4__7);
Cifra(x.Cifre_Hexa.B__8_11); Cifra(x.Cifre_Hexa.B_12_15); printf(" \n"); }
while (x.Intreg!=0);
}

26.11.18 29
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
9. Structuri de date dinamice
Pentru a implementa structura liniară (lista simplu înlănţuită) şi structura de tip
arbore binar vom apela la structuri definite recursiv.
9.1. Listă simplu înlănţuită ordonată
Considerăm o listă nevidă fiind formată din primul element şi sublista aflată la adresa
de legătură memorată în fiecare element pe lângă informaţia propriuzsă.
În exemplul următor vom crea o listă care va conţine monoamele unui polinom în
ordinea descrescătoare a gradelor. Un element din listă va conţine pe lângă informaţia
propriuzisă (coeficientul şi gradul monomului) şi adresa următorului monom (adresa
sublistei). De exemplu, pentru polinomul P(x)=120x12+77x7+130x3+22x2 lista va conţine
patru elemente având informaţiile (20,12); (77,7); (130,3); (22,2), indiferent de ordinea
introducerii monoamelor. Deoarece coeficienţii sunt nenuli, introducerea datelor se termină
la primul coeficient nul.

#include <stdio.h>
#include <alloc.h>
#include <iostream.h>
#define Nil (NULL)
struct Monom { int Coef, Grad ; };
struct Elem { Monom Inf; Elem* Leg; };
typedef Elem* Polinom; // Listă de monoame ordonate decrescător după grad
int Citit(Monom &M)
{ cin >> M.Coef; if (M.Coef) cin >> M.Grad; return M.Coef;
}
void Ado(Polinom &P, Monom M)
{ int lung=sizeof(Elem); Polinom Nou;
if ((P==Nil)|(P->Inf.Grad<M.Grad)) {Nou=(Polinom) malloc(lung);
Nou->Inf=M; Nou->Leg=P; P=Nou;}
else Ado(P->Leg,M);
}
void Cre(Polinom &P)
{ Monom M; P=Nil;
while (Citit(M)) Ado(P,M);
}
void Tip(Polinom P)
{ if (P!=Nil) { cout << P->Inf.Coef << "X^" << P->Inf.Grad;
if (P->Leg!=Nil) cout << "+" ; Tip (P->Leg); }
}
void main (void)
{ Polinom P;
cout << " P (Coef,Grad) : "; Cre (P);
cout << " Polinomul P(X)="; Tip (P);
getchar();
}
Date : P (Coef,Grad) : 120 12 22 2 77 7 130 3 0 
Rezultate : Polinomul P(X)=120X^12+77X^7+130X^3+22X^2

26.11.18 30
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
// Listă simplă ordonată crescător \\
#include <iostream.h> #include "Crt.Cpp"
typedef int Info;
struct Elem;
typedef Elem* Lista;
struct Elem {Info Inf; Lista Urm;};
int Citit(Info& inf)
{ cin >> inf; return inf; }
void Ado(Lista& L, Info inf)
{ if (L && (L->Inf<inf)) Ado(L->Urm,inf);
// else {Lista Nou=new Elem; Nou->Inf=inf; Nou->Urm=L; L=Nou;} //sau
else {Elem el={inf,L}; Lista Nou = new Elem (el); L=Nou;}
}
void Cre(Lista& L)
{ Info El; L=NULL; while (Citit(El)) Ado(L,El); }
void Tip(Lista L)
{ if (L) {cout << L->Inf << ','; Tip(L->Urm); } cout << "\b."; }
void main (void)
{ ClrScr();
Lista L;
cout << " Lista : "; Cre (L);
cout << " Lista = "; Tip (L); Readln();
}

9.2. Abori binari


Considerăm că un arbore binar nevid este format din rădăcină, subarbore stâng şi
subarbore drept.
Exemplu:
// Arbore ordonat, traversat în inordine \\
#include <iostream.h> #include "Crt.Cpp"
typedef int Info;
struct Nod; typedef Nod* Arb; struct Nod {Info Inf; Arb LegSt,LegDr;};
int Citit(Info& inf)
{ cin >> inf; return inf; }
void Ado(Arb& A, Info inf)
{ if (A) if (inf<A->Inf) Ado(A->LegSt,inf); else Ado(A->LegDr,inf);
else { A=new Nod; A->Inf=inf; A->LegSt=NULL; A->LegDr=NULL;}
}
void Ado(Arb& A, Info inf)
{ if (A) if (inf<A->Inf) Ado(A->LegSt,inf);
else Ado(A->LegDr,inf);
// else { A=new Nod; A->Inf=inf; A->LegSt=NULL; A->LegDr=NULL;} //sau
else { Nod n={inf,0,0}; A=new Nod (n); }
}
void Cre(Arb& A)
{ Info El; A=NULL; while (Citit(El)) Ado(A,El); }
void Ino(Arb A)
{ if (A) { Ino(A->LegSt); cout << A->Inf << ','; Ino(A->LegDr); } }
void main (void)
{ Arb A; ClrScr();
cout << " Arb : "; Cre (A); cout << " Arb = "; Ino (A); Readln();
}

26.11.18 31
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor se citeste un arbore genealogic ascendent (dând pentru fiecare
persoană nume părinţilor), apoi se va reprezenta grafic arborele construit într-o fereastră
ecran precizată (u1,v1,u2,v2). Distanţa dintre două nivele se calculează ţinând cont de
adâncimea arborelui.
#include <stdio.h>
#include <alloc.h>
#include <string.h>
#include <iostream.h>
#include <graphics.h>
#include <conio.h>
typedef char TInf [13] ;
struct Nod { TInf Inf ; // Radacină \\
Nod* Ls; Nod* Ld; // Sub.St, Sub.Dr
} ;
typedef Nod* Arb;
int Citit(TInf &Inf)
{ cin >> Inf; return (Inf[0]!='.'); }
void Gen(Arb &A)
{ TInf Inf; int Lung=sizeof(Nod);
if (Citit(Inf)) { A=(Arb) malloc(Lung);
strcpy (A->Inf,Inf); // A->Inf=Inf;
cout << " Mama lui " << Inf << " : "; Gen(A->Ls);
cout << " Tatal lui " << Inf << " : "; Gen(A->Ld); }
else A=NULL;
}
void Repr_Grafic(Arb A, int u1, int v1, int u2, int v2, int p)
{ int m;
if (A!=NULL) { m=(u1+u2)/2;
if (v1>20) lineto(m,v1-13);
ellipse(m,v1,0,360,31,13);
outtextxy(m,v1,A->Inf);
moveto(m-2,v1+13);
Repr_Grafic(A->Ls,u1,v1+p,m,v2,p); // St
moveto(m+2,v1+13);
Repr_Grafic(A->Ld,m,v1+p,u2,v2,p); } // Dr
}
int Max (int a, int b)
{ return (a>b ? a : b); }
int Adi(Arb A)
{ if (A==NULL) return -1; else return Max(Adi(A->Ls),Adi(A->Ld))+1; }
void main (void)
{ Arb A;
cout << " Arbore genealogic ascendent pentru : "; Gen (A);
int Gd = DETECT, Gm; initgraph(&Gd, &Gm, "c:\\Bc\\Bgi");
settextjustify(CENTER_TEXT,CENTER_TEXT);
Repr_Grafic(A,50,20,getmaxx()-50,getmaxy()-20,(getmaxy()-40)/Adi(A));
getchar(); closegraph();
}

26.11.18 32
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
10. Utilizarea fişierelor
Prelucrarea fişierelor se poate efectua la două nivele:
 Nivelul inferior - face apel direct la sistemul de operare;
 Nivelul superior - utilizează proceduri speciale pentru operaţii de intrare/ieşire.

10.1. Nivelul inferior


Prelucrările la acest nivel permit următoarele cinci operaţii:

10.1.1. Deschiderea unui fişier (Open/Creat)

int open ( const char * c a l e , int acces ) ;


unde:
 c a l e - este specificatorul de fişier,
 acces - poate fi o combinaţie (utilizând operatorul ‘|’) a următoarelor valori:
O_RDONLY (fişier deschis numai pentru citire), O_WRONLY sau O_CREAT (numai
pentru scriere - creare), O_RDWR (citire/scriere), O_APPEND (deschis pentru
adăugare la sfârşit), O_BINARY (pentru prelucrare binară), O_TEXT (pentru fişier de
tip text).

Dacă deschiderea fişierului s-a realizat corect, atunci funcţia returnează o valoare
întreagă reprezentând descriptorul de fişier (LUN, care va fi utilizat în continuare la celelelte
operaţii efectuate asupra acestui fişier), iar în caz de nereuşită se va returna valoarea -1.
Pentru a putea utiliza funcţia Open trebuie incluse fişierele header io.h şi fcntl.h.
Exemplu:
...
int Lun;
Lun = open (“Fisier.Dat”,ORDONLY);
...

Pentru crearea unui fişier se va apela funcţia Creat:


int creat ( const char * c a l e , int mod ) ;
unde:
 mod - poate lua una dintre valorile: S_IREAD (fişierul se poate citi), S_IWRITE
(scriere în fişier), S_IEXEC (execuţia programului din fişierul specificat).
Pentru a putea utiliza funcţia Creat trebuie incluse fişierele io.h şi stat.h.
Fişierele text sunt implicite.

26.11.18 33
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
10.1.2. Citirea dintr-un fişier (Read)

int read ( int L u n , void *buffer, unsigned lung ) ;


unde:
 L u n - este descriptorul definit la deschidere (0= STDIN, 1=STDOUT, 2=STDERR,
3=STDPRN, 4=STDAUX),
 buffer - este zona de memorie în care se citeşte,
 l u n g - este lungimea (în octeţi) a înregistrării citite.
Funcţia returnează numărul de octeţi citiţi (cel mult l u n g ), 0 la sfărşit, sau -1 în caz
de eroare. Automat, după o citire (a articolului curent) se trece la următorul articol, implicit
prima poziţionare fiind la început de fişier (acces secvenţial).
Pentru a utiliza funcţiile Read, Write, LSeek sau Close trebuie inclus fişierul io.h.

10.1.3. Scrierea într-un fişier (Write)

int write ( int L u n , void *buffer, unsigned lung ) ;

Funcţia returnează numărul de octeţi scrişi în fişier, reprezentând lungimea


articolului = l u n g , sau -1 în caz de eroare.

10.1.4. Poziţionarea într-un fişier (LSeek)


Această funcţie permite accesul aleator printr-un apel de forma:
long lseek ( int L u n , long *deplasament, int origine ) ;
unde:
 deplasament - reprezintă numărul de octeţi peste care se deplasează capul de
citire/scriere,
 origine - reprezintă punctul din care se măsoară deplasament- ul (0=începutul
fişierului, 1=poziţia curentă, 2=sfârşitul fişierului).
Funcţia returnează poziţia curentă faţă de începutul fişierului, sau -1 la eroare.

10.1.5. Închiderea unui fişier (Close)

int close ( int L u n ) ;


Funcţia returnează 0 la o închidere corectă, sau -1 la eroare.

10.1.6. Stergerea unui fişier (UnLink)

int unlink (const char * c a l e ) ;


Funcţia returnează 0 la o ştergere corectă, sau -1 la eroare.

26.11.18 34
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemple:
// Creare \\
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main (void)


{
int Lun;
clrscr();
Lun=open("Fis.Txt",O_CREAT|O_TEXT);
if (Lun!=-1)
{
cout << "Open ..." << endl;
write(Lun,"Primul...\n",10);
write(Lun,"Al Doilea\n",10);
}
else cout << " Open Incorect ! ";
close(Lun);
getchar();
}

// Citire \\
#include <io.h>
#include <fcntl.h>
#include <stdio.h>
#include <conio.h>
#include <iostream.h>

void main (void)


{
int Lun;
char Rand[10];
textmode(1); textbackground(BLUE);
textcolor(WHITE); clrscr();
Lun=open("Fis.Txt",O_TEXT);
if (Lun!=-1)
{
read(Lun,Rand,10); cout << Rand;
read(Lun,Rand,10); cout << Rand;
}
else cout << " Open Incorect ! ";
close(Lun);
getchar();
}

26.11.18 35
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
10.2. Nivelul superior
La acest nivel sunt posibile următoarele operaţii:

10.2.1. Deschiderea unui fişier (FOpen)

FILE * fopen ( const char * c a l e , const char * mod ) ;


unde:
 mod - poate fi “r” pentru deschidere în citire, “w” pentru scriere, “a” pentru
adăugare, “r+” pentru modificare (citire/scriere), “rb” pentru citire binară, “wb”
pentru scriere binară, sau “r+b” pentru citire/scriere binară.
Dacă la deschiderea fişierului s-a ales modul “w” sau “a”, fişierul va fi creat (recreat).
Funcţia returnează un pointer spre tipul FILE definit în fişierul stdio.h, iar în caz de
nereuşită se va returna valoarea NULL (stdin, stdout, stderr, stdaux şi stdprn sunt pointeri
spre tipul FILE permiţând transferuri fără a fi necesară deschiderea sau închiderea lor).
Exemplu:
...
FILE * Pf;
Pf = fopen (“Fisier.Dat”,”w”);
...

10.2.2. Prelucrarea pe caractere a unui fişier (PutC, GetC)

int putc ( int c , FILE * Pf ) ;


unde:
 c - este codul caracterului scris,
 Pf - este valoarea returnată la deschidere sau stdin, stdout, stderr, stdaux, stdprn.
Funcţia returnează valoarea lui c sau -1 la eroare.

int getc (FILE * Pf ) ;

Funcţia returnează codul caracterului citit, sau valoarea EOF la sfârşitul fişierului,
sau -1 la eroare.

Exemplu:
#include <stdio.h>
void main (void)
{ int c;
while ((c=getc(stdin))!=EOF) putc(c,stdout);
}

26.11.18 36
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
10.2.3. Închiderea unui fişier (FClose)

int fclose ( FILE * Pf ) ;

Funcţia returnează 0 la închiderea corectă a fişierului sau 1 la eroare.

10.2.4. Citirea/Scrierea cu format (FScanF, FPrintF)

int fscanf ( FILE * Pf , control, listă_variabile) ;

Parametrii control şi listă_variabile au aceeaşi semnificaţie ca şi pentru funcţia scanf.


Funcţia returnează numărul de câmpuri citite sau EOF.

int fprintf ( FILE * Pf , control, listă_expresii) ;

Funcţia returnează numărul de caractere scrise în fişier sau -1 la eroare.


Ex.1:
// Creare fişier text cu Nume, Prenume \\
#include <stdio.h>
#include <conio.h>
int Citit(char *x, char*y)
{ printf (" Nume prenume : "); return (scanf(" %s%s",x,y)!=EOF); }
void main (void)
{ char Nume[25], Prenume[15]; clrscr();
FILE *Pf=fopen("Fis_Text.Dat","w");
while (Citit(Nume,Prenume)) fprintf(Pf,"%s %s\n",Nume,Prenume);
fclose (Pf); getche();
}

Ex.2:
// Creare fişier text cu format (articole : (Den, Cant, Preţ)) \\
#include <stdio.h>
#include <conio.h>
void main (void)
{ FILE *Produse; int n=0; int Eof;
char Den[20]; textmode(1);
int Cant; textbackground(BLUE);
float Pret; textcolor(WHITE);
clrscr();
if (Produse=fopen("Fis_Form.Txt","w")) {
do {
printf (" Articolul %d \n",++n);
printf (" - Den. : "); Eof=(scanf("%s",Den)==EOF); if(!Eof){
printf (" - Cant.: "); scanf ("%d",&Cant);
printf (" - Pret : "); scanf ("%f",&Pret);
fprintf(Produse,"%-20s%4d%7.2f\n",Den,Cant,Pret);} }
while (!Eof); fclose (Produse); }
else printf (" Open incorect"); getchar();
}

26.11.18 37
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Listare fişier text \\
#include <stdio.h>
#include <conio.h>
void main (void)
{ FILE *Produse; int n=0;
char Den[20]; textmode(1);
int Cant; textbackground(BLUE);
float Pret; textcolor(WHITE);
clrscr();
if (Produse=fopen("Fis_Form.Txt","r")) {
while (fscanf(Produse,"%s%d%f",Den,&Cant,&Pret)!=EOF) {
printf (" Articolul %d : \n",++n);
printf (" - Den. : %-20s \n",Den);
printf (" - Cant.: %4d \n",Cant);
printf (" - Pret : %7.2f \n",Pret); }
fclose (Produse); }
else printf (" Fisier Absent"); getchar();
}

10.2.5. Intrări/Ieşiri de şiruri de caractere (FGetS, FPutS)

char * fgets ( char *s, int n, FILE * Pf ) ;


unde:
 s - zona receptoare (tablou de tip char de dimensiune  n, terminat cu NUL=’\0’),
 n-1 - număr maxim de caractere (n-1),
Funcţia returnează adresa şirului s, sau la EOF returnează NULL.
int fputs ( char *s, FILE * Pf ) ;
Funcţia returnează codul ultimului caracter scris sau -1 la eroare.

Următorul program înlocuieşte cuvintele din fişierul F_Niv_S.Cpp aflate în partea


stângă a dicţionarului Dicţio.Txt cu cele corespunzătoare din partea dreaptă, rezultatul fiind
depus în fişierul F_Niv_S.Pas, aşa cum se poate vedea în schema de mai jos.

Fin_Niv_S.Cpp Dictio.Txt

Traduce

Fin_Niv_S.Pas

26.11.18 38
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Traduce Fişier text - String \\
#include <stdio.h> #include <conio.h>
#include <iostream.h> #include <process.h>
#include <string.h>
int Length(char* s)
{ return strlen(s); }
/*
int Pos(char* s, char* S)
{ for (int i=0; i<Length(S); i++) { int Ok=1;
for (int j=0; j<Length(s); j++)
if (S[i+j]!=s[j]) { Ok=0; break; }
if (Ok) return i; } return -1;
} */
int Pos(char* s, char* S)
{
char* p = strstr(S,s); return p ? p-S : -1;
}
/*
void Delete(char* s, int p, int n)
{ while (n) { n--; for (int i=p; i<Length(s); i++) s[i]=s[i+1]; }
} */
void Delete(char* s, int p, int n)
{
for (int i=p; i<Length(s); i++) s[i]=s[i+n];
}
/*
void Insert(char* s, char *S, int p)
{ for (int l=0; l<Length(s); l++) {
for (int i=Length(S); i>=p+l; i--) S[i+1]=S[i]; S[p+l]=s[l]; }
} */
void Insert(char* s, char *S, int p)
{ int m=Length(s); int n=Length(S);
if (p>n) p=n; else if (p<0) p=0;
for (int i=n; i>=p; i--) S[i+m]=S[i];
char* ps=S+p; while (*s) *ps++=*(s++);
}
void Subst (char* x, char* y, char* S)
{ int p=Pos(x,S);
if (p>=0) { Delete(S,p,Length(x)); Insert(y,S,p); }
}
void main (void)
{ clrscr();
const Dd=20; typedef char Cuv[Dd]; struct Per { Cuv St, Dr; };
Per Dictio[20]; int NrCuv=1;
FILE *Dic; Dic=fopen("Dictio.Txt","r");
if (Dic==NULL) { cout << "Dictio ?"; getche(); exit(1); }
while (EOF!=fscanf(Dic,"%s%s",Dictio[NrCuv].St,Dictio[NrCuv].Dr))
cout << NrCuv << " : " << Dictio[NrCuv ].St
<< " -> " << Dictio[NrCuv++].Dr << endl;
fclose(Dic); NrCuv--; getche();
FILE *FisI, *FisE;
FisI=fopen("F_Niv_S.Cpp","r"); FisE=fopen("F_Niv_S.Pas","w");
if (FisI==NULL) { cout << "Fisier ?"; getche(); exit(1); }
const Dm=100; char Rand[Dm];
while (fgets(Rand,Dm,FisI)) { // !=NULL
for (int i=1; i<=NrCuv; i++)
while (Pos(Dictio[i].St,Rand)>=0)
Subst(Dictio[i].St,Dictio[i].Dr,Rand);
fputs(Rand,FisE); cout << Rand; }
fclose(FisI); fclose(FisE); getche();
}

10.2.6. Poziţionarea într-un fişier (FSeek, FTell)

int fseek (FILE * Pf, long deplasamnet, int origine ) ;

26.11.18 39
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
unde deplasamnet şi origine au aceeaşi semnificaţie ca şi la funcţia lseek.
Funcţia fseek returnează 0 la poziţionare corectă sau o valoare 0 la eroare.

long ftell ( FILE * Pf );


Funcţia ftell returnează poziţia curentă (faţă de începutul fişierului, în octeţi).

10.2.7. Prelucrarea fişierelor binare (FRead, FWrite)


Acest tip de prelucrare permite transferul mai multor articole aflate într-o zonă
tampon astfel:
unsigned fread (void *Pzt, unsigned dim, unsigned nrart, FILE * Pf) ;
unde:
 Pzt - este adresa zonei tampon,
 dim - reprezintă lungimea unui articol,
 nrart - reprezintă numărul de articole care se transferă (citesc),

unsigned fwrite (const void *Pzt, unsigned dim, unsigned nrart, FILE * Pf) ;
Ambele funcţii returnează numărul de articole transferate sau -1 la eroare.
Exemple:
#include <stdio.h>
typedef struct { char Den[10];
int Cant;
float Pret;
} Articol;
void main (void)
{ FILE *Pf; Articol Art; int n,i;
if ((Pf=fopen("Fis_Tip.Dat","wb")) == NULL) printf (" Open incorect");
printf ("\n Numarul de articole : "); scanf ("%d",&n);
for (i=1; i<=n; i++) {
printf (" Articolul %d : \n",i);
printf (" - Den. : "); scanf ("%s", Art.Den );
printf (" - Cant.: "); scanf ("%d",&Art.Cant);
printf (" - Pret : "); scanf ("%f",&Art.Pret);
fwrite (&Art,sizeof(Articol),1,Pf); }
fclose (Pf); getchar();
}
...
{...
if ((Pf=fopen("Fis_Tip.Dat","rb")) == NULL) printf (" Open incorect");
...
for (i=1; i<=n; i++) {
fread (&Art,sizeof(Articol),1,Pf);
printf("Articolul %d : \n",i); printf("- Den. : %s\n", Art.Den );
printf("- Cant.: %d\n", Art.Cant); printf("- Pret : %f\n", Art.Pret); } fclose (Pf);
}

26.11.18 40
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
11. Funcţii standard

11.1. Macrouri de clasificare


Macrourile din această categorie (aflate în fişierul ctype.h) verifică dacă un caracter
este de un anumit tip:
int isascii (int ca r ); ca r  [0,127] ?
int isalpha (int ca r ); ca r este codul unui caracter alfanumeric ?
int isalnum (int ca r ); ca r este codul unei litere ?
int isupper (int ca r ); ca r este codul unei litere mari ?
int islower (int ca r ); ca r este codul unei litere mici ?
int isdigit (int ca r ); ca r este codul unei cifre zecimale ?
int isxdigit (int ca r ); ca r este codul unei cifre hexa ?
int isgraph (int ca r ); ca r este codul unui caracter afişabil ?
int isprint (int ca r ); ca r este codul unui caracter imprimabil ?
int isspace (int ca r ); ca r este spaţiu, tab, Cr, Lf, Vt sau Np ?

11.2. Macrouri de transformare a simbolurilor


Macrourile din această clasă (aflate în fişierul ctype.h) transformă un caracter astfel:
int toascii (int ca r ); ca r  [0,127] (returnează ultimii 7 biţi)
int toupper (int ca r ); ca r  literă mare (transformă din l în L)
int tolower (int ca r ); ca r  literă mică (transformă din L în l)

11.3. Conversii
Funcţiile care urmează (aflate în fişierul stdlib.h) realizează conversii fară format.

Format intern  Format (zecimal ) extern


int atoi (const char *pt r ); binar (int)  zecimal extern
long atol (const char *pt r ); binar (long)  zecimal extern
double atof (const char *pt r );virgulă flotantă (dublă precizie)  zecimal extern
Format extern  Format intern
char *itoa (int v, char *s, int b); s  v b (valoarea v de tip int, scrisă în baza b)
char *ltoa (long v, char *s, int b); s  v b (valoarea v de tip long scrisă în baza b)

26.11.18 41
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
11.4. Funcţii de prelucrare a şirurilor de caractere
Funcţiile din această categorie se află în fişierul string.h.
11.4.1. Copiere (Str[n]Cpy)
char * str[n]cpy (char *destinaţ ie, const char *sursa [, unsigned n ]) ;
unde sursa este copiată în destinaţ ie, eventual doar primii n octeţi (cel mult n).
11.4.2. Concatenare (Str[n]Cat)
char * str[n]cat (char *destinaţ ie, const char *sursa [, unsigned n ]) ;
unde sursa este copiată la sfârşitul destinaţ iei, eventual doar primii n octeţi ai sursei.
11.4.3. Comparare (Str[n][i]Cmp)
int str[n][i]cmp (char *şir 1 , const char *şir 2 [, unsigned n ]) ;
unde şir 1 este comparat cu şir2 (eventual doar primii n octeţi, şi eventual ignorând diferenţa
dintre literele mari şi cele mici), iar rezultatul comparării este un număr negativ dacă
şir1<şir2, este un număr pozitiv dacă şir1>şir2 sau zero dacă şir1=şir2.

11.4.4. Lungimea unui şir (StrLen)


unsigned strlen (char *şir) ;
returnează lungimea şirului (de caractere, fără caracterul NUL care îl termină).

11.5. Funcţii de calcul


Aceste funcţii se află în fişierul math.h (abs şi labs şi în stdlib.h *):
Prototip Semnificaţie double log (double x ); ln(x)
double sin (double x ); sin(x) double log10 (double x ); lg(x)
double cos (double x ); cos(x) double ceil (double x ); [x]
double asin (double x ); arcsin(x) double floor (double x ); trunc(x)
double acos (double x ); arccos(x) double fabs (double x ); |x|
double atan (double x ); arctg(x) int abs (int x ); * |x|
double sinh (double x ); sh(x) long labs (long x ); * |x|
double cosh (double x ); ch(x) double atan2 (double y, double x ); arctg(y/x)
double tanh (double x ); th(x) double pow (double x, double y ); xy
double sqrt (double x ); x double cabs (struct complex z ); |z|
double exp (double x ); ex double poly (double x, int n, double a [] ); P(x)

11.6. Funcţii pentru controlul proceselor


Următoarele funcţii se află în fişierele stdlib.h şi process.h .
Prototip Semnifica ţie
void abort (void);  termină un program la eroare

26.11.18 42
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
void exit (int cod_retur);  termină un program returnând un cod de retur
int system (const char *comandă);  execută o comandă şi returnează cod_retur (0=Ok).

11.7. Funcţii pentru timp


Aceste funcţii se referă la dată şi oră, şi sunt definite în fişierul dos.h împreună cu
următoarele două tipuri:

struct date { struct time {


int da_year; unsigned char ti_min;
int da_day;
unsigned char ti_hour;
unsigned char ti_hund;
int da_mon; unsigned char ti_sec;
} }

Semnifica ţie Prototip


 Citeşte Data curentă : void getdate (struct date *Data);
 Modifică Data curentă : void setdate (const struct date *Data);
 Citeşte Ora Exactă : void gettime (struct time *OraExactă);
 Modifică Ora Exactă : void settime (const struct time *OraExactă);

Exemplu:
#include <stdio.h>; // Timp : Data, Ora \\
#include <dos.h>;
void main (void)
{ struct date DataC; getdate(&DataC);
struct time OraEx; gettime(&OraEx);
printf(" Data : %2d %2d %4d \n", DataC.da_day,DataC.da_mon,DataC.da_year);
printf(" Ora : %2d:%2d:%2d \n", OraEx.ti_hour,OraEx.ti_min,OraEx.ti_sec);
}

11.8. Funcţii diverse


Aceste funcţii sunt definite în fişierul conio.h:

Prototip Semnificaţie  Wait (sec)


3. void sleep (unsigned sec );
1. void clrscr (double x ); Clear Screen  4. void sound (unsigned Hz ); Sound (Fr)
2. void delay (unsigned ms ); Wait (ms)  5. void nosound (void ); NoSound

26.11.18 43
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
12. Ecranul în mod text
Există posibilitatea de a defini următoarele moduri de lucru:
void textmode ( int mod ) ;

unde mod poate fi C40 (=1 pentru 40 coloane), C80 (=3 pentru 80 coloane), C4350
(=64 pentru 43/50 linii), şi altele.
Definirea unei ferestre ecran (implicit este tot ecranul) se realizează astfel:
void window ( int u 1 , int v 1 , int u 2 , int v 2 ) ;
Ştergerea unei ferestre ecran:
void clrscr (void) ;
Poziţionarea cursorului:
void gotoxy ( int x, int y) ; // col, lin
Poziţia cursorului:
int wherex ( void ) ; // col

int wherey ( void) ; // lin

Un caracter poate fi afişat pe ecran clipitor (BLINK=1), pe o culoare de fond (0-7)


şi într-o anumită culoare de scriere (0-15), culorile posibile fiind următoarele:

Colori închise Colori deschise


0 = BLACK 8 = DARKGRAY
1 = BLUE 9 = LIGHTBLUE
2 = GREEN 10 = LIGHTGREEN
3 = CYAN 11 = LIGHTCYAN
4 = RED 12 = LIGHTRED
5 = MAGENTA 13 = LIGHTMAGENTA
6 = BROWN 14 = YELLOW
7 = LIGHTGRAY 15 = WHITE

Culoarea de fond se poate stabili prin funcţia:


void textbackground ( int cul f ) ; // cul f  {0,...,7}
Culoarea de scriere se poate schimba printr-un apel de forma:
void textcolor ( int cul s ) ; // cul s  {0,...,15}

13. Ecranul în mod grafic


Trecerea în modul grafic:
void far initgraph ( int far * graphdriver, int far * graphmode, char far * path) ;

26.11.18 44
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Ieşirea din modul grafic:
void closegraph (void) ;
Setarea / Citirea culorii de fond:
void far setbkcolor (int cul f ) ; / int far getbkcolor (void ) ;
Setarea / Citirea culorii de scriere:
void far setcolor (int cul s ) ; / int far getcolor (void ) ;
Alte funcţii:
Semnifica ţie Funcţii
 Număr de pixeli ( Oriz./Vert.) getmaxx (); getmaxy ();
 Coordonatele LPR (Ultimul Punct Referit ) getx (); gety ();
 Mută LPR (Abs./Rel.) moveto (x,y); moverel (dx,dy);
 Trasează segment din LPR lineto (x,y); linerel (dx,dy);
 Trasează segment line (x1,y1, x2,y2);
 Desenează dreptunghi rectangle (x1,y1, x2,y2);
 Desenează cerc circle (x,y,r);
 Scrie mesaj [ din LPR ] outtext[xy] ([x,y,] mesaj);
 Pagină activă / Pagină vizuală setactivepage (pag); setvisualpage (pag);
Exemple:
#include <graphics.h> // Graficul unei suprafeţe \\
#include "graf.h"
# i n c l u d e < s t d l i b . h > # i n c l u d e < s t d i o . h > # i n c l u d e < con i o. h > # i n c l u d e < m a t h . h >
float Sqr (float x) { return x*x; }
float z (float x, float y) { return sin(Sqr(x)+Sqr(y)); } // z=f(x,y)
void main(void)
{ float x; float y; float px; float py; int i; int j; int n=40; int m=40;
InitGraf (); ViewPort (10,10,getmaxx()-10,getmaxy()-10);
float l=3; float x1=-l; float x2=l; float y1=-l; float y2=l; // Dom (x,y)
DefPr(1./2,1); // DefPr (r,a)
a=PrX(x1,z(x1,y1)); b=a; c=PrY(y1,z(x1,y1)); d=c;
for (i=0; i<=m; i++) for (j=0; j<=n; j++) {
x=x1+(x2-x1)*i/m; y=y1+(y2-y1)*j/n;
px=PrX(x,z(x,y)); py=PrY(y,z(x,y));
if (px<a) a=px; else if (px>b) b=px;
if (py<c) c=py; else if (py>d) d=py;
};

26.11.18 45
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Window(a,d,b,c); setbkcolor(BLUE);
for (i=0; i<=m; i++) {
x=x1+(x2-x1)*i/m; y=y1;
Muta(PrX(x,z(x,y)),PrY(y,z(x,y)));
for (j=1; j<=n; j++) {
y=y1+(y2-y1)*j/n;
Trag(PrX(x,z(x,y)),PrY(y,z(x,y)));
} } setcolor(YELLOW);
for (j=0; j<=n; j++) {
y=y1+(y2-y1)*j/n; x=x1;
Muta(PrX(x,z(x,y)),PrY(y,z(x,y)));
for (i=1; i<=m; i++) {
x=x1+(x2-x1)*i/n;
Trag(PrX(x,z(x,y)),PrY(y,z(x,y)));
} }
getch(); closegraph();
}

#include <graphics.h> // Graficul unei curbe \\


#include <conio.h>
#include <math.h>
#include "graf.h"
float x (float t) { return cos(t); }
float y (float t) { return sin(t); }
float z (float t) { return t / 10; }
void main(void)
{ float t, px,py; float t1=-50; float t2=50; float p=0.1; float Raza=0.5; float Alfa=1;
InitGraf (); setgraphmode(1); ViewPort (20,20,getmaxx()-20,getmaxy()-20);
DefPr(Raza,Alfa); // Pr.||(Raza,Alfa)
t=t1; a=PrX(x(t),z(t)); b=a; c=PrY(y(t),z(t)); d=c;
for (t=t1+p; t<=t2; t+=p*2) {
px=PrX(x(t),z(t)); py=PrY(y(t),z(t));
if (px<a) a=px; else if (px>b) b=px;
if (py<c) c=py; else if (py>d) d=py;
};
Window(a,d,b,c); int Pag=0; setbkcolor(BLUE);
enum { Rosu, Verde } Sem = Verde;
do { clearviewport(); outtextxy(10,10,"Q OP"); outtextxy(10,20,"A");
t=t1; Muta(PrX(x(t),z(t)),PrY(y(t),z(t)));
for (t=t1+p; t<=t2; t+=p)
{Trag(PrX(x(t),z(t)),PrY(y(t),z(t)));}
setvisualpage(Pag); Pag=1-Pag; setactivepage(Pag);
char Rasp=getch();
switch (Rasp&0x5F) {
case 'A' : Raza-=0.01; break; case 'Q' : Raza+=0.01; break;
case 'P' : Alfa-=0.01; break; case 'O' : Alfa+=0.01; break;
default : closegraph(); Sem=Rosu; }
DefPr(Raza,Alfa);
} while (Sem==Verde);
}

// Graf.h \\
#include <graphics.h>
#include <math.h>

26.11.18 46
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
int u1,v1, u2,v2; // ViewPort
float a, b, c, d ; // Window
float Raza, Alfa; // Pr (r,)
int u (float x) { return ((x-a)/(b-a)*(u2-u1)+u1); }
int v (float y) { return ((y-d)/(c-d)*(v2-v1)+v1); }
void InitGraf(void)
{ int Gd = DETECT, Gm; initgraph(&Gd, &Gm, "c:\\Bc\\Bgi"); }
void ViewPort(int x1,int y1,int x2,int y2)
{ u1=x1; v1=y1; u2=x2; v2=y2; /* rectangle(u1,v1,u2,v2);*/ }
void Window(float x1,float y1,float x2,float y2)
{ a=x1; d=y1; b=x2; c=y2; }
void Muta(float x,float y)
{ moveto(u(x),v(y)); }
void Trag(float x,float y)
{ lineto(u(x),v(y)); }
void DefPr(float r, float a)
{ Raza=r; Alfa=a; }
float PrX (float x, float z)
{ return x+Raza*z*cos(Alfa); }
float PrY (float y, float z)
{ return y+Raza*z*sin(Alfa); }

26.11.18 47
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
14. Facilităţi C++
Limbajul C++ oferă în plus faţă de limbajul C unele facilităţi noi. Un avantaj
important îl constituie noţiunea de clasă (prin care se defineşte un TAD), iar acestea pot
forma o ierarhie, deci putem vorbi de o programare orientată obiect.

14.1. Extensii ale limbajului C


În C++ există un nou tip de comentariu (deja utilizat în exemplele anterioare):
... // Comentariu
Dacă în limbajul C declaraţiile erau scrise înainte de instrucţiuni, în C++ ele pot fi
scrise oriunde.
Dispozitivelor standard de intrare-ieşire li s-au ataşat streamurile standard cin
(pentru stdin) şi respectiv cout (pentru stdout), care permit efectuarea operaţiilor de intrare-
ieşire aplicând operatorul >> streamului cin, respectiv << streamului cout. Ierarhiile
necesare sunt în fişierul iostream.h .
Exemplu:
#include <stdio.h>; #include <conio.h>;
#include <iostream.h>;
void main (void)
{ int i; cout << " Dati i : "; cin >> i;
cout << " Val. i = " << i << endl; // endl=<Cr>
double x; cout << " Dati x : "; cin >> x;
cout << " x + i = " <<x+i<< endl;
char s[10]; cout << " Dati s : "; cin >> s;
cout << " Sir. s = " << s << endl; getch();
}

Dacă în C conversia explicită se poate efectua prin (tip) expresie, în C++ se poate
realiza şi prin tip (expresie).
Exemplu:
#include <stdio.h>; #include <conio.h>;
#include <iostream.h>;
void main (void)
{ char c;
cout << " Dati c : "; cin >> c;
cout << " Car. c = " << c << endl;
cout << " Val. c = " << (int) c << endl;
cout << " Val. c = " << int (c) << endl;
void *p; p=&c;
cout << " Val. c = " << *(int *) p << endl;
typedef int * Pint;
cout << " Val. c = " << * Pint (p)<< endl; // Conţinutul adresei
getch(); // la care se află un întreg
}

26.11.18 48
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
14.2. Operatori

14.2.1. Operatorul de rezoluţie (::)


Acest operator (::) se utilizează când dorim să referim o variabilă globală redefinită
într-o funcţie, astfel:
:: Variabilă
Exemplu:
#include <conio.h>;
#include <iostream.h>;
unsigned x; // Variabile Globale (::)
char y[10];
int i=99;
void main (void)
{ clrscr();
unsigned x; // Variabile Locale
int y;
cout << " Dati doua numere : "; cin >> ::x >> x;
cout << " Cele doua numere = " << ::x << ' ' << x << endl;
cout << " Cele doua numere = " << ++::x << ' ' << --x << endl;
cout << " Cele doua numere = " << ::x << ' ' << x << endl;
cout << " Dati nume,varsta : ";
cin >> ::y >> y;
cout << " Numele si varsta = " << ::y << ',' << y << endl;
for (int i=11; i<::i; ::i-=11) cout << i <<"::"<< ::i << endl;
getche();
}

14.2.2. Operatorul de adresă (&)


Acest operator (&) se poate utiliza şi pentru a defini un tip referinţă printr-
declaraţie de forma tip & (asemănător cu o construcţie de forma tip *, pentru pointer).
Cu ajutorul acestui operator putem redenumi o variabilă, putem realiza un apel prin referinţă
sau putem să declarăm o variabilă de referinţă astfel:
tip & parametru_formal // par. ref. (adresă)
tip & nume_var_ref ; // var. de tip referinţă

26.11.18 49
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemple:
#include <conio.h>; // Redefinirea unei variabile
#include <iostream.h>;
void main (void)
{ int a[1]; int * b = a; int & c = a[0];
cout << " Dati a : "; cin >> a[0];
cout << " a,b,c = " << a[0] << *b << c << endl;
int x; int * y = &x; int & z = *y; int & w = x;
cout << " Dati x : "; cin >> x;
cout << " x,y,z,w = " << x << *y << z << w << endl; getch();
}

#include <conio.h>; // Redefinirea unei func ţii


#include <iostream.h>;
#include <math.h>;
typedef double Functie (double);
void main (void)
{ Functie & Sin=sin; double x;
cout << " Dati x : "; cin >> x;
cout << "Sin(" << x << ")=" << Sin(x) << endl; getch();
}

#include <conio.h>; // Apel prin Referinţă


#include <iostream.h>;
void suma (int x,int y,int *z) // x,y  z
{ *z = ++x * ++y; }
void Suma (int x,int y,int &z) // x,y  z
{ z = ++x * ++y; }
void main (void)
{ int x,y,z;
cout << " Dati x,y : "; cin >> x >> y;
suma(x,y, &z); cout << "(x+1)*(y+1)=" << z << endl;
Suma(x,y, z); cout << "(x+1)*(y+1)=" << z << endl; // mai simplu!
getch();
}

14.2.3. Operatorii de alocare/dealocare (New/Delete)


Operatorul de alocare New se poate folosi în oricare dintre următoarele trei variante:
new tip
new tip ( Valoare_de_intiţializare_a_variabilei_dinamice )
new tip [ Numărul_de_variabile_dinamice_alocate ]
Dealocarea se realizează astfel:
delete Variabilă_de_referinţă ;
sau
delete [ Numărul_de_var_dinamice_alocate ] Variabilă_de_referinţă ;
Exemplu:
#include <stdio.h>; #include <conio.h>; #include <iostream.h>;
void main (void)
{

26.11.18 50
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
int *i = new int;
cout << " Dati v : "; cin >> *i;
cout << " v = " << *i << endl;
int *j;
j = new int (*i);
cout << "*i ==*j = " << *j << endl;
delete i;
delete j;
int *r; r = new int [2];
cout << " Dati v1 : "; cin >> * r;
cout << " Dati v2 : "; cin >> *(r+1);
cout << " v1 = " << * r << endl;
cout << " v2 = " << *(r+1)<< endl;
delete r; getch();
}

În exemplul următor se va utiliza o matrice A cu număr variabil de coloane şi o


matrice B utilizând adresele liniilor:
#include <iostream.h>; #include "Crt.Cpp"
typedef int Tip;
const n=4;
void main ()
{ ClrScr();
Tip* A[n+1], *p; int i,j;
for (i=1; i<=n; i++) {
p = A[i] = new Tip [i+1];
for (j=1; j<=i; j++) *(++p)=i*10+j;
}
for (i=1; i<=n; i++) { p=A[i]; cout << " " << i << " : ";
for (j=1; j<=i; j++) cout << *p++ << ' ';
cout << endl;
}
for (i=1; i<=n; i++) { cout << " " << i << " : ";
for (j=1; j<=i; j++) cout << *(*(A+i)+j) << ' '; // Aij
cout << endl;
}
int B[n+1][n+1];
for (i=1; i<=n; i++)
for (j=1; j<=n; j++) B[i][j]=i*10+j;
for (i=1; i<=n; i++) { cout << " " << i << " : ";
for (j=1; j<=n; j++) cout << *(*(B+i)+j) << ' '; // Bij
cout << endl;
} Readln();
} // R e z u l t a t e :
1 : 11
2 : 21 22
3 : 31 32 33
4 : 41 42 43 44
1 : 11
2 : 21 22
3 : 31 32 33
4 : 41 42 43 44
1 : 11 12 13 14
2 : 21 22 23 24
3 : 31 32 33 34
4 : 41 42 43 44

26.11.18 51
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
14.3. Structură, uniune şi enumerare
Referirea acestor tipuri se poate face în C++ fără a mai fi nevoie de cuvântul
corespunzător struct, union, respectiv enum. De asemenea, parametrii şi valoarea unei
funcţii pot fi structuri, pointeri la structuri sau referinţe la structuri. Sunt permise şi
atribuiri de structuri.
Referirea componentelor unei uniuni anonime din interiorul unei structuri se face la
fel ca şi referirea componentelor structurii, iar prima componentă se poate iniţializa.
În C++, variabilelor de tip enumerare nu se mai pot atribui decât valori ale acestui
tip (nu şi numerele asociate acestor elemente).
Exemple:
#include <stdio.h>; #include <conio.h>; #include <iostream.h>;
typedef float Real;
enum Figura { punct, cerc };
struct Punct { Real x, y; };
struct Cerc { Punct Centru;
Real Raza; };
struct Obiect { Figura FIG;
union { Punct PUNCT;
Cerc CERC;
}; };
Obiect Translatat ( Obiect o, Punct T )
{ o.PUNCT.x = o.PUNCT.x + T.x;
o.PUNCT.y = o.PUNCT.y + T.y;
return o;
}
void main (void)
{ Punct P = { 3,7 };
Obiect O = { punct, { 1,2 } };
Obiect C; C.FIG=cerc; C.CERC.Centru=O.PUNCT; C.CERC.Raza=10;
Obiect D; D=Translatat(C,P);
cout << " D(" << D.CERC.Centru.x << ","
<< D.CERC.Centru.y << ","
<< D.CERC.Raza << ")" << endl; getch();
}

26.11.18 52
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO

// Simetrizeaza cel mai apropiat punct fata de origine \\


#include <iostream.h>
#include "crt.h"
struct Punct { float x, y;
Punct& CitP ();
void TipP ();
float D2 () { return x*x + y*y; }
Punct& SimO () { x=-x; y=-y; return *this; }
};
Punct& Punct::CitP () { cin >> x >> y; return *this; }
void Punct::TipP () { cout << x << ' ' << y << endl; }
Punct& ApropO( Punct& P, Punct& Q ) { return P.D2()<Q.D2() ? P : Q; }
void main (void)
{ ClrScr();
cout << " P : "; Punct P; //P.CitP();
cout << " Q : "; Punct Q; //Q.CitP();
cout << " M = "; ApropO(P.CitP(),Q.CitP()).SimO().TipP();
cout << " P = "; P.TipP();
cout << " Q = "; Q.TipP();
Readln()
;
}

// Simetrizeaza cel mai apropiat punct fata de origine \\


#include <iostream.h>
#include "crt.h"
struct Punct { float x, y;
Punct () { cin >> x >> y; }
void TipP() { cout << x << ' ' << y << endl; }
float D2 () { return x*x + y*y; }
Punct& SimO();
};
Punct& Punct::SimO() { x=-x; y=-y; return *this; }
Punct& ApropO (Punct& P, Punct& Q) { return P.D2()<Q.D2() ? P : Q; }
void main (void)
{ ClrScr();
cout << " P : "; Punct P=Punct();
cout << " Q : "; Punct Q=Punct();
cout << " M = "; ApropO(P,Q).SimO().TipP();
cout << " P = "; P.TipP();
cout << " Q = "; Q.TipP();
Readln()
;
}

26.11.18 53
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
15. Funcţii C++

15.1. Funcţii Inline


Aceste macrouri se pot defini astfel:
# define nume m ( Listă_parametri_formali ) şir_caractere
Apelurile macrourilor se vor înlocui cu şirul de caractere precizat, fără a face
verificări de tipuri, ceea ce poate conduce la erori.
Aceste erori pot fi eliminate dacă utilizăm funcţiile inline, caz în care se vor face
conversiile de tip necesare. Aceste funcţii se declară prin scrierea cuvântului inline la
începutul antetului, aşa cum se pate vedea în exemplele următoare:
Ex. 1:
#include <conio.h>; #include <iostream.h>;
#define Abs_G(x) (x)> 0 ? (x) : -(x) // Gresit !
#define Abs_g(x) ( x > 0 ? x : - x ) // gresit !
#define Abs_c(x) ( (x)> 0 ? (x) : -(x) ) // Macro corect
inline long Abs (long x) // Functie Inline
{
return x > 0 ? x : - x ;
}
void main (void)
{ long x;
cout << " x : " ; cin >> x; long y=-x;
cout << " |x| = " << Abs_G(x); cout << endl;
cout << " |x| = " << Abs_g(x) << endl;
cout << " |x| = " << Abs_c(x) << endl;
cout << " |x| = " << Abs (x) << endl;
cout << " |10-y| = " << Abs_G(10-x); cout << endl;
cout << " |10-y| = " << Abs_g(10-x) << endl;
cout << " |10-y| = " << Abs_c(10-x) << endl;
cout << " |10-y| = " << Abs (10-x) << endl; getch();
}

Ex. 2:
#include <iostream.h>;
#define max( x, y) (x>y ? x : y) // Gresit !
inline int Max(int x, int y) // F.Inline
{ return (x>y ? x : y); }
void main (void)
{ int x,y,z;
x=5; y=2; z=max(++x,++y); cout <<" max("<<x<<','<<y<<")="<<z<< endl;
x=5; y=2; z=Max(++x,++y); cout <<" Max("<<x<<','<<y<<")="<<z<< endl;
}
// Rezultatele
max(7,3)=7 !
Max(6,3)=6

26.11.18 54
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO

15.2. Funcţii de tip referinţă


Antetul unei funcţii cu valoare de tip referinţă este:

tip & numef ( Listă_parametri_formali )


Exemplu:
#include <time.h>; #include <stdlib.h>; #include <conio.h>; #include <iostream.h>;

int & Alba_Neagra ( int & Albe, int & Negre ) // Ref. la int
{ if (random(2)) return Albe; // Ref. la Albe
else return Negre; // Ref. la Negre
}
void main (void)
{ int Albe=0; int Negre=0; int i,n; randomize();
cout << "Dati n:"; cin >> n;
for(i=1;i<=n;i++) Alba_Neagra(Albe,Negre)++; // Inc(Albe/Negre)
cout <<"Albe ="<< Albe << endl;
cout <<"Negre="<< Negre<< endl;
getch();
}

În următorul exemplu se doreşte modificarea coordonatelor celui mai apropiat punct


(dintre P şi Q) faţă de origine (nu doar coordonatele simetricului lui P sau Q):
// Simetrizează cel mai apropiat punct faţă de origine
#include <iostream.h>
#include "crt.h"
struct Punct { float x, y; };
float D2 ( Punct P ) { return P.x*P.x + P.y*P.y; }
Punct SimO ( Punct& P ) { P.x=-P.x; P.y=-P.y; return P; }
Punct& ApropO( Punct& P, Punct& Q ) { return D2(P) < D2(Q) ? P : Q; }
Punct CitP ( ) { Punct P; cin >> P.x >> P.y; return P; }
void TipP ( Punct P ) { cout << P.x << ' ' << P.y << endl; }

void main (void)


{ ClrScr();
cout << " P : "; Punct P = CitP ();
cout << " Q : "; Punct Q = CitP ();
cout << " M = "; TipP (SimO (ApropO(P,Q)) );
cout << " P = "; TipP (P);
cout << " Q = "; TipP (Q);
Readln();
}

26.11.18 55
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Ex. Referinţă \\
#include <iostream.h>; #include "Crt.Cpp"
void suma (int x,int y,int *z)
{ *z = ++x * ++y; }
void Suma (int x,int y,int &z)
{ z = ++x * ++y; }
int* max (int& x, int& y)
{ return ( x > y ? &x : &y ); }
int& Max (int& x, int& y)
{ return ( x > y ? x : y ); }
struct Punct { int x,y; };
Punct Atrib (int x, int y)
{ Punct P; P.x=x; P.y=y; return P; }
Punct sim (Punct P)
{ P.x=-P.x; P.y=-P.y; return P; }
Punct& Sim (Punct& P)
{ P.x=-P.x; P.y=-P.y; return P; }
Punct* Psim(Punct P)
{ P.x=-P.x; P.y=-P.y; return &P; }
void Tip (Punct P)
{ cout << " P(" << P.x << ',' << P.y << ')' << endl; }
void main (void)
{ int x,y,z; ClrScr();
cout << " Dati x,y : "; cin >> x >> y;
suma(x,y,&z); cout << " (x+1)*(y+1) = " << z << endl;
Suma(x,y, z); cout << " (x+1)*(y+1) = " << z << endl;
cout << " x,y = " << x << ' ' << y << endl;
cout << " max(x,y)+1 = " << ++ *max(x,y) << endl;
cout << " x,y = " << x << ' ' << y << endl;
cout << " Max(x,y)+1 = " << ++ Max(x,y) << endl;
cout << " x,y = " << x << ' ' << y << endl;
Punct P=Atrib(x,y); Tip(P);
Tip(sim(P)); Tip(P);
Tip(Sim(P)); Tip(P);
cout <<"P(x,y)=("<< sim(P) .x <<','<< Sim(P) . y <<')'<< endl;
cout <<"P(x,y)=("<<(*Psim(P)).x <<','<< Psim(P)->y <<')'<< endl;
Readln();
} // R e z u l t a t e :
Dati x,y : 1 5
(x+1)*(y+1) = 12
(x+1)*(y+1) = 12
x,y = 1 5
max(x,y)+1 = 6
x,y = 1 6
Max(x,y)+1 = 7
x,y = 1 7
P(1,7)
P(-1,-7)
P(1,7)
P(-1,-7)
P(-1,-7)
P(x,y)=(1,7)
P(x,y)=(-1,-7)

26.11.18 56
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
15.3. Supraîncărcarea funcţiilor
Această proprietate dă posibilitatea utilizării unor funcţii având acelaşi nume, dar
diferite (înrudite, cu antete diferite).
Exemple:
#include <math.h>; #include <complex.h>; #include <conio.h>; #include <iostream.h>;
double ArcTg (double x) { return atan (x); }
double ArcTg (double y, double x) { return atan2(y,x); }
double ArcTg (complex z) { return real (atan(z)); }
void main (void)
{ complex w(1,0);
cout << " Pi = " << 4*ArcTg(1.0) << endl;
cout << " Pi = " << 2*ArcTg(1,0) << endl;
cout << " Pi = " << 4*ArcTg( w ) << endl; getch();
}

// Roteste un Triunghi in jurul unui Punct \\


#include "graf.h"
#include <conio.h>
struct Punct { float x,y; };
struct Triunghi { Punct A,B,C; };
Punct Init (float x, float y);
Triunghi Init (Punct A, Punct B, Punct C);
void Translat (Punct& P, Punct Q);
void Translat (Triunghi& T, Punct Q);
void Rot (Punct& P, float Alfa, Punct Q);
void Rot (Triunghi& T, float Alfa, Punct Q);
Punct Init (float x, float y) { Punct P = {x,y}; return P; }
Triunghi Init (Punct A, Punct B, Punct C){ Triunghi T; T.A=A; T.B=B; T.C=C; return T; }
void Translat (Punct& P, Punct Q) { P.x+=Q.x; P.y+=Q.y; }
void Translat (Triunghi& T, Punct Q) { Translat(T.A,Q); Translat(T.B,Q);
Translat(T.C,Q); }
void Rot (Punct& P,Punct Q,float Alfa) { Rot(P.x,P.y,Q.x,Q.y,Alfa);
Rot(P.x,P.y,Q.x,Q.y,Alfa); }
void Rot (Triunghi& T,Punct Q,float Alfa){ Rot(T.A,Q,Alfa); Rot(T.B,Q,Alfa);
Rot(T.C,Q,Alfa); }
void Muta(Punct P) { Muta(P.x,P.y); }
void Trag(Punct P) { Trag(P.x,P.y); }
void Des (Punct P) { circle(u(P.x),v(P.y),3);}
void Des (Triunghi T) { Muta(T.A); Trag(T.B); Trag(T.C); Trag(T.A);}
void main(void)
{
Punct P = Init(10,10);
Triunghi ABC = Init(Init(5,5),Init(20,7),Init(8,12));
InitGraf(); ViewPort (20,10,getmaxx()-20,getmaxy()-10);
setbkcolor(BLUE); setwritemode(XOR_PUT);
Window (-10,20,30,-10);
Linie (-10, 0,20, 0);
Linie ( 0,20, 0,-10);
char Esc=0x1b; float Alfa; char
Rasp='o';
Des(P);
do { Des(ABC); if (Rasp=='o') Alfa=0.1; else Alfa=-
0.1;
Rot(ABC,P,Alfa); }
while ((Rasp=getche())!=Esc);
closegraph();
}

26.11.18 57
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO

15.4. Iniţializarea parametrilor formali


Parametrii formali pot avea o valoare implicită, dacă aceştia lipsesc din lista
parametrilor actuali, valoare dată de o expresie. În lista parametrilor formali, cei cu valoare
implicită (iniţializaţi) se vor scrie ultimii astfel:

tip nume = expresie


Exemplu:
#include <stdio.h>; #include <conio.h>; #include <iostream.h>;
struct Obiect { float x,y; float r; };
int ELipsa () { return -1; }
int Este_Punct (Obiect o) { return o.r==ELipsa(); }
Obiect Init( float x0=0, float y0=0, float raza=ELipsa() )
{ Obiect o;
o.x=x0; o.y=y0; o.r=raza;
return o;
}
Tip ( Obiect o )
{ if (Este_Punct(o)) cout << " Punct ( "; else cout << " Cerc ( ";
cout << o.x << "," << o.y;
if (Este_Punct(o)) ; else cout << "," << o.r;
cout << " ) " << endl;
}
main ()
{
Obiect O=Init(); Tip(O); // Originea (0,0)
Obiect A=Init(7); Tip(A); // A  Ox (7,0)
Obiect P=Init(1,2); Tip(P); // P  R2 (1,2)
Obiect C=Init(3,4,5); Tip(C); // Cerc (3,4, 5)
getch();
}

În exemplul care urmează se poate vedea cum se pot folosi parametrii impliciţi
pentru a declara punctul O(0,0), un punct A pe axa Ox, un punct P în plan (R2), un cerc C
(în plan), extremităţile unui segment din spaţiu (Q,RR 3), precum şi segmentele QR şi RO:
#include <stdio.h>;
#include <conio.h>;
#include <iostream.h>;
struct Punct { float x,y,z; };
Punct Init( float x0=0, float y0=0, float z0=0 )
{ Punct P;
P.x=x0; P.y=y0; P.z=z0;
return P;
}
void Tip ( Punct P )
{
cout << " P(" << P.x <<','<< P.y <<','<< P.z <<')'<< endl;
}

26.11.18 58
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
struct Segment { Punct A, B; } ;
Segment Init ( Punct A, Punct B = Init() )
{
Segment AB = {{A.x,A.y,A.z},{B.x,B.y,B.z}};
return AB;
}
void Tip ( Segment AB )
{
cout << " Segment : \n"; Tip(AB.A); Tip(AB.B);
}
void main ()
{ clrscr();
Punct O=Init(); Tip(O); // Originea
(0,0,0)
Punct A=Init(7); Tip(A); // A e Ox
(7,0,0)
Punct P=Init(1,2); Tip(P); // P e R2
(1,2,0)
Punct C=Init(3,4,5); Tip(C); // Cerc
(3,4,5)
Punct Q =Init(1,2,3); // Q e R3
Punct R =Init(4,5,6); // R e R3
Segment QR=Init(Q,R); // QR e R3
Tip(QR);
Segment RO=Init(R);
Tip(RO);
getche();
}

15.5. Funcţii membru pentru Structuri


Acestea se declară în cadrul structurii ca fincţii inline sau prototipuri (urmând
în acest caz descrierea lor cu ajutorul operatorului de rezoluţie (::).
// Simetrizeaza cel mai apropiat punct fata de origine \\
#include <iostream.h>
#include "crt.h"
struct Punct { float x, y;
Punct& CitP ();
void TipP ();
float D2 () { return x*x + y*y; }
Punct& SimO () { x=-x; y=-y; return *this; }
};
Punct& Punct::CitP () { cin >> x >> y; return *this; }
void Punct::TipP () { cout << x << ' ' << y << endl; }
Punct& ApropO( Punct& P, Punct& Q ) { return P.D2()<Q.D2() ? P : Q; }
void main (void)
{ ClrScr();
cout << " P : "; Punct P; //P.CitP();
cout << " Q : "; Punct Q; //Q.CitP();
cout << " M = "; ApropO(P.CitP(),Q.CitP()).SimO().TipP();
cout << " P = "; P.TipP();
cout << " Q = "; Q.TipP();
Readln()
;
}

// Simetrizeaza cel mai apropiat punct fata de origine \\

26.11.18 59
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
#include <iostream.h>
#include "crt.h"
struct Punct { float x, y;
Punct () { cin >> x >> y; }
void TipP() { cout << x << ' ' << y << endl; }
float D2 () { return x*x + y*y; }
Punct& SimO();
};
Punct& Punct::SimO() { x=-x; y=-y; return *this; }
Punct& ApropO (Punct& P, Punct& Q) { return P.D2()<Q.D2() ? P : Q; }
void main (void)
{ ClrScr();
cout << " P : "; Punct P=Punct();
cout << " Q : "; Punct Q=Punct();
cout << " M = "; ApropO(P,Q).SimO().TipP();
cout << " P = "; P.TipP();
cout << " Q = "; Q.TipP();
Readln()
;
}

16. Tip Abstract de Dată


Programarea modulară permite protejarea datelor prin memorie statică, (accesul la
date se poate efectua doar din locul declarării până la sfârşitul modulului, nu şi în afara lui).
Un tip abstract de dată (Domeniu, Operaţii) conţine o interfaţă (“Tad.h”) şi o
implementare (“Tad.Cpp”). Programul (“Program.Cpp”) care utilizează acest tip abstract
de dată va avea acces doar la modulul de interfaţă, aşa cum se poate vedea în schema de
mai jos:

Compilare
Program.Cpp Program.Obj

Link-editare
Tad.h Program.Exe

Compilare
Tad.Cpp Program.Obj

În proiect (meniul Project) vor fi incluse fişierele Program.Cpp şi Tad.Cpp.

26.11.18 60
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor, pentru Tad Mulţime, fişierele vor fi PMult.Cpp, Mult.h şi
Mult.Cpp:
// PMult.Cpp \\
#include <conio.h>
#include <iostream.h>
#include "Mult.h"
void main (void)
{ clrscr();
Multime A, B, C, D;
Init(A); Init(B); Init(C); Init (D);
cout << " A : "; CitM(A);
cout << " A = "; TipM(A);
//cout << "|A|: " << A->card << endl; // Nu se p.!
cout << "|A|: " << Card(A) << endl; // Se p.!
cout << " B : "; CitM(B);
cout << " B = "; TipM(B);
Init(C); Inters(A,B,C); cout << "AnB: "; TipM(C);
Init(D); Reun (A,B,D); cout << "AuB: "; TipM(D);
cout << (Inclus(A,B) ? " A<=B " : " !A<=B ");
cout << (Egale (A,B) ? " A==B " : " A<>B ");
getche();
}

// Mult.h \\
#include "ElMult.h" // Sunt definite elementele mulţimii
struct Cet;
typedef Cet *Multime;
void Init (Multime &A);
int Card (Multime A);
int E_Vida (Multime A);
void Vida (Multime A);
void AdEl (TEl x, Multime A);
void CitM (Multime A);
void TipM (Multime A);
int Apart (TEl x, Multime A);
void Inters (Multime A, Multime B, Multime C);
void Dif (Multime A, Multime B, Multime C);
void Reun (Multime A, Multime B, Multime C);
int Inclus (Multime A, Multime B);
int Egale (Multime A, Multime B);
Multime DifEl (Multime A, TEl a);
Multime Difer (Multime A, Multime B);

// PMult.Cpp \\
#include <iostream.h>
#include <conio.h>
#include "ElMult.h"
#include "Mult.h"
typedef struct Cet { int card;
TEl Elem[Cm];
};

26.11.18 61
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
int Card (Multime A)
{ return A->card; }
void CitM (Multime A)
{ cin >> A->card;
if (Card(A)>Cm-2) cout << Card(A) << Cm << "!"; else
for (int i=1; i<=Card(A); i++) cin >> A->Elem[i];
cout << endl;
}
void TipM (Multime A)
{ for (int i=1; i<=Card(A); i++) cout << A->Elem[i] << ",";
cout << "\b\n";
}
int Apart (TEl x, Multime A)
{ for (int i=1; i<=Card(A); i++) if (x==A->Elem[i]) return 1;
return 0;
}
void Inters (Multime A, Multime B, Multime C)
{ Vida(C);
for (int i=1; i<=Card(A); i++) if (Apart(A->Elem[i],B)) AdEl(A->Elem[i],C);
}
void Dif (Multime A, Multime B, Multime C)
{ int i;
Vida(C);
for (i=1; i<=Card(A); i++) if (!Apart(A->Elem[i],B)) AdEl(A->Elem[i],C);
}
Multime DifEl (Multime A, TEl a)
{
if (Apart(a,A)) { Multime D; Init(D); AdEl(a,D); Dif(A,D,D); return D; }
else return A;
}
Multime Difer (Multime A, Multime B)
{
Multime D; Init(D); Dif(A,B,D); return D;
}
Multime Difer (Multime A, Multime B)
{
Multime D; Init(D); Dif(A,B,D); return D;
}
void Reun (Multime A, Multime B, Multime C)
{ int i;
*C=*A; Multime B_A; Init(B_A); Dif(B,A,B_A);
for (i=1; i<=Card(B_A); i++) AdEl(B_A->Elem[i],C);
// destroy B_A;
}
int Inclus (Multime A, Multime B)
{ int i;
for (i=1; i<=Card(A); i++) if (!Apart(A->Elem[i],B)) return 0; return 1;
}
int Egale (Multime A, Multime B)
{
return Inclus(A,B) && Inclus(B,A);
}
int Egale (Multime A, Multime B)
{
return Inclus(A,B) && Inclus(B,A);
}

26.11.18 62
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
void AdEl(TEl x, Multime A)
{
if (!Apart(x,A))
if (Card(A)>Cm-2) {cout << Card(A) << Cm << "!"; getch();} else
A->Elem[++(A->card)]=x;
}
void Vida(Multime A)
{
A->card=0;
}
void Init(Multime &A)
{
A = new Cet; Vida(A);
}
int E_Vida(Multime A)
{
return (A->card)==0;
}

// ElMult.h \\
#define Cm 255
typedef int TEl; // Tipul elementelor mulţimii

Un tip abstract de dată realizează o unificare (printr-o grupare de tip struct) între
date (date membru) şi operaţiile (funcţii membru) lor caracteristice. Funcţiile membru sunt
considerate de tip inline iar definirea lor în afara structurii se face prin operatorul de
rezoluţie (::). În acest mod însă nu se realizează o protecţie a datelor (accesul la date se
poate face şi prin alte funcţii, nu numai prin cele membru), această protecţie putând fi
realizată (aşa cum vom vedea în cele ce urmează) cu ajutorul claselor.
Exemplu:
#include <stdio.h>; #include <conio.h>; #include <iostream.h>;
#define Pi 3.141592
struct Cerc { float x,y;
float r;
void Init (float x0, float y0, float raza)
{ x=x0; y=y0; r=raza;}
float Lung ();
float Aria ();
};
float Cerc::Lung () { return 2*Pi*r; }
float Cerc::Aria () { return Pi*r*r; }
void main (void)
{ Cerc C; C.Init(1,2,3);
cout << "C(" << C.x << "," << C.y << "," << C.r << ")" << endl;
cout << "Aria = " << C.Aria() << endl;
cout << "Lung = " << C.Lung() << endl; getch();
}

26.11.18 63
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
17. P rogramare o rientată o biect ( O O P )

OOP este o metodă de implementare în care:


a) Obiectele sunt elementele de bază,
b) Orice obiect este o instanţă a unei clase,
c) Clasele sunt legate (asociate) unele cu altele prin moştenire.
Un limbaj este orientat obiect dacă:
a) Utilizează obiecte,
b) Obligă obiectele să aparţină unei clase,
c) Permite moştenirea.
Limbajul C++ oferă noţiunea de clasă, prin care se pot forma ierarhii, deci putem
vorbi de o programare orientată obiect (OOP).
OOP înseamnă realizarea unor programe alcătuite dintr-o mulţime de obiecte care
interacţionează pentru a rezolva problema propusă, şi permite reutilizarea elementelor
descrise (a interfeţei şi a codului).
Un obiect are o stare şi un comportament (operaţii descrise în interfaţa obiectului)
aceste două componente fiind definite prin datele membru (variabile de instanţă) şi
respectiv prin funcţiile membru (metode).
OOP utilizează ormătoarele concepte:
clasa - implementarea unui TAD,
obiectul - instanţa unei clase,
 metoda - mesajul prin care se asigură interfaţa (operaţiile).

OOP are următoarele caracteristici (proprietăţi) de bază:

 încapsularea - gruparea datelor şi a operaţiilor definite pentru acestea, precum şi protecţia


acestor date (ele neputând fi accesate decât prin funcţiile membru).
 moştenirea - păstrarea elementelor (date şi funcţii ale) unei clase (de bază), cu definirea
de noi elemente construind o nouă clasă (derivată), formând în felul acesta
ierarhii de clase. Moştenirea poate fi şi multiplă dacă o clasă moşteneşte
mai multe clase.
 polimorfism - redefinirea (supraîncărcarea) operaţiilor (funcţiilor). Într-o ierarhie pot fi
mai multe funcţii cu acelaşi nume, deci va fi efectuată operaţia
corespunzătoare obiectului care o apelează. Determinarea operaţiei se
poate face la compilare (legare statică) sau la execuţie (legare dinamică,
prin funcţii vituale).

26.11.18 64
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
17.1. Definirea Claselor
O clasă se declară ca şi o structură, înlocuind cuvântul struct cu class. Protecţia
datelor se defineşte scriind modificatorul dorit (private, protected sau public) urmat de ‘:’.
Descrierea unei clase conţine atât datele membru (variabilele de instanţă) cât şi
funcţiile membru (metodele), precizând pentru acestea gradul de protecţie, astfel:
class Nume_clasă {
{ [ Modificator_de_protecţie: ] Listă_membrii }
};

unde:
Modificator_de_protecţie  { private, protected, public} , private fiind implicit,
 private nu permite accesul din afara clasei, –
 protected permite accesul din clasele derivate, #
 public permite accesul din afara clasei; +
 Listă_membrii  { Listă_declaraţii_date_membru, Listă_ declaraţii _funcţii_membru }

Datele de tip private (–) pot fi accesate doar de funcţiile membru sau funcţii
prietene (friend). O funcţie membru a unei clase poate fi funcţie prietenă a altei clase, iar
dacă toate sunt prietene, atunci se poate declara clasă prietenă (friend). //  Vezi C8
Fiecare obiect al unei clase deţine un set de date membru (variabile de instanţă).
Funcţiile membru publice pot fi utilizate din orice funcţie din program, pe când cele
private doar din funcţiile membru ale clasei.
Definirea funcţiilor membru (metodelor) se poate realiza:
a) imediat (complet, antet plus corp) în definiţia clasei (ca funcţie inline) dacă funcţia nu
conţine multe instrucţiuni şi nu conţine structuri repetitive (apelul nu se face prin salt cu
revenire), astfel:
class Nume_clasă { …
Tip_funcţie Nume_metodă ( ... ) { . . . }; // antet+corp

};
b) ulterior (dacă a fost declarat în definiţia clasei doar prototipul funcţiei), utilizând
operatorul de rezoluţie (de scop) astfel:
Tip_funcţie Nume_clasă :: Nume_metodă ( ... ) // :: operatorul de
rezoluţie
{ . . . }; // corpul funcţiei

26.11.18 65
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
// Clasa Punct \\
// ----------------------------- \\
# include <conio.h>
# include <iostream.h>
class Punct { float x, y; // private: (x,y) e
R2
public:
Punct ( ) { x=0; y=0; }
Punct (float x0, float y0) { x=x0; y=y0; }
Punct (Punct& P) { x=P.x; y=P.y; }
void CitP (char* Mes);
void TipP (char* Mes);
Punct& SimPb ( );
};
void Punct::CitP (char* Mes) { cout << Mes; cin >> x >> y ; }
void Punct::TipP (char* Mes) { cout << Mes << x <<' '<< y << endl; }
Punct& Punct::SimPb( ) { float z=x; x=y; y=z; return *this; }
void main (void)
{
. . .
}

Un obiect este o instanţă a unei clase (o variabilă de tipul clasei). Fiecare obiect
aparţine unei singure clase (aceasta putând avea mai multe obiecte).
Obiectele unei clase se declară astfel:
Clasă Listă_Obiecte;
Exemplu:
// Obiecte Punct \\
// ----------------------------- \\
# include <conio.h>
# include <iostream.h>
class Punct {
. . .
};
. . .
void main (void)
{ clrscr(
);
Punct O,A(1,2);
O.TipP(" O = ");
A.TipP(" A = ");

Punct B1; B1.CitP(" B1: ");


Punct B2 (B1.SimPb());
B2.TipP(" B2= ");
getche(
);
}

26.11.18 66
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Alocarea (şi iniţializarea) obiectelor se face cu o funcţie membru specifică numită
constructor (cu numele Clasă) iar dealocarea cu o funcţie destructor (cu numele ~Clasă).
Exemplu:
// Constructori - Destructori \\
// ---------------------------- \\
# include <dos.h>
# include <math.h>
# include <conio.h>
# include <graphics.h>
# include <iostream.h>
# define Cale "c:\\BorlandC\\Bgi"

class Grafic { int Gd, Gm;


public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale);}
~Grafic( ) { closegraph(); }
};

class Punct { float x, y; // private: (x,y) e R2


public:
Punct ( ) { x=0; y=0; }
Punct (float x0, float y0) { x=x0; y=y0; }
Punct (Punct& P) { x=P.x; y=P.y; }
Punct (int, int, int);
~Punct ();

int X0 () { return int(x); }


int Y0 () { return int(y); }
Punct& Transl(Punct&);
};

Punct:: Punct(int x0,int y0,int c) { x=x0; y=y0; setcolor(c); circle(x,y,5);}


Punct::~Punct( ) { setcolor(BLACK); circle(x,y,5);}

Punct& Punct::Transl(Punct& T) { x+=T.x; y+=T.y; return *this; }


void main (void)
{
Grafic Mod(DETECT);
Punct C(getmaxx()/2,getmaxy()/2,WHITE); getche(); // Centru
for (float Alfa=-1.57;Alfa<4.71;Alfa+=0.01)
{ float Raza=100;
Punct M(Raza*cos(Alfa),Raza*sin(Alfa));
Punct P=M.Transl(C);
Punct D(P.X0(),P.Y0(),YELLOW); delay(5);
} getche();
}

26.11.18 67
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Componentele claselor (datele şi funcţiile membru) se referă prin operatorul  sau
>, ca şi în cazul unei structuri. Funcţiile membru referă direct componentele clasei (fără
aceşti operatori, utilizând poinetrul this declarat automat ca pointer la obiectul curent).
Exemplu:
// Operatorii  şi  > \\
// ---------------------------- \\
# include <dos.h>
# include <math.h>
# include <conio.h>
# include <graphics.h>
# include <iostream.h>
# define Cale "c:\\BorlandC\\Bgi"

class Grafic { int Gd, Gm;


public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale);}
~Grafic( ) { closegraph(); }
};

class Punct { float x, y;


public:
Punct ( ) { x=0; y=0; }
Punct (float x0, float y0) { x=x0; y=y0; }
Punct (const Punct& P) { x=Px; y=Py; }

Punct (int, int, int);


~Punct ();
Punct* Init (float x0, float y0) { x=x0; y=y0; return this; }
int X0 () { return int(x); }
int Y0 () { return int(y); }
Punct* Transl(const Punct*);
};

Punct:: Punct(int x0,int y0,int c) { x=x0; y=y0; setcolor(c); circle(x,y,5);}


Punct::~Punct( ) { setcolor(BLACK); circle(x,y,5);}

Punct* Punct::Transl(const Punct* T){ x+=T >x; y+=T >y; return this; }

void main (void)


{
Grafic Mod(DETECT);
Punct* C = new Punct(getmaxx()/2,getmaxy()/2,WHITE); getche();
float Raza=100;
Punct* M = new Punct; // M  C
for (float Alfa=-1.57;Alfa<4.71;Alfa+=0.02) {
M=M >Init(Raza*cos(Alfa),Raza*sin(Alfa))  >Transl(C);
Punct *P=new Punct(M >X0(),M >Y0(),YELLOW); delay(3); // Desen. P
delete P; } // Sterge P
delete M; getche();
delete C; getche();
}

26.11.18 68
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
17.2. Constructori şi Destructori

Un obiect este creat de un constructor al clasei şi este şters (distrus) de către


destructor.
Constructorii permit iniţializarea obiectelor cu (mai multe) funcţii membru omonime
(având acelaşi nume cu clasa şi care diferă prin lista parametrilor formali), fără a returna o
valoare. Constructorul este apelat automat la crearea unui obiect. O clasă trebuie să
conţină cel puţin doi constructori:
 un constructor implicit (fără parametri, care iniţializează obiectele cu o valoare
implicită),
 un constructor de copiere (care iniţializează cu valoarea unui obiect existent, de acelaşi
tip).

Exemplu:
// Constructori String \\
# include <Conio.h>
# include <String.h>
# include <Iostream.h>
class String { char* s;
public:
String (); // Constructor implicit
String (const String&); // Constructor de copiere
String (const char*); // Constructor de conversie
String& operator=(const String&); // Operator de atribuire
~String (); // Destructor
int Length (); // Lungimea sirului
void Print (); // Tipareste sirul
};
String::String () { s=new char; s[0]=0; }
String::String (const String& S) { s=new char[S.Length( )+1];strcpy(s,S.s);}
String::String (const char* S) { s=new char[ strlen(S)+1];strcpy(s,S); }
String& String::operator=(const String& S)
{ if (s!=S.s) {delete []s; s=new char[S.Length()+1]; strcpy(s,S.s);}
return *this;}
String::~String () { delete []s;}
int String::Length () { return strlen(s); }
void String::Print () { cout << s << endl; }
void main ()
{ clrscr();
String Vid;
Vid.Print ();
String Prop (" Constructori pentru clasa String.");
Prop.Print();
String Rand(Prop);
Rand.Print();
String Rind=Rand;
Rind.Print();
getche();
}

26.11.18 69
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Antetul unui constructor al unei clase ce conţine ca date membru obiecte alte altor
clase este de forma:
Clasă (Listă_par_formali) : Obiect1(Listă_par_formali1),...,Obiectn(Listă_par_formalin)
Exemplu:
#include <stdio.h>; #include <conio.h>; #include <iostream.h>;
class P3D { float x,y,z;
public:
P3D () {x=0;y=0;z=0;}
P3D (float x0, float y0, float z0) {x=x0;y=y0;z=z0;}
void Tip(){ cout <<"P("<<x<<","<<y<<","<<z<<")"<<endl; }
};
class Cerc { P3D x_y_r;
public:
Cerc () { };
Cerc (float x0, float y0, float z0) : x_y_r(x0,y0,z0) { }
Cerc (P3D C) { x_y_r=C; }
Cerc (const Cerc & C0) { x_y_r = C0.x_y_r; }
void Tip(){ cout << " Cerc "; x_y_r.Tip();}
};
void main (void)
{ Cerc O; O.Tip(); // Constructor implicit P3D O(0,0,0)
Cerc C(4,5,6); C.Tip(); // Constructor pentru obiect P3D
P3D P(1,2,3); P.Tip(); // Constructor P3D
Cerc D(P); D.Tip(); // Constructor Cerc
Cerc E(D); E.Tip(); getch(); // Constructor de copiere
}

Destructorii realizează automat dealocarea obiectelor globale la sfârşitul


programului, iar a celor locale la sfârşitul funcţiei. Obiectele alocate dinamic (cu new) se
vor dealoca cu operatorul delete. Numele destructorului este compus din caracterul ~
urmat de numele clasei ( ~ Cl as ă ( ) ). Destructorii nu returnează o valoare.
Exemplu:
#include <iostream.h>;
class Cerc { float x,y,r;
public:
Cerc (float x0, float y0, float r0)
{cout << "Alocare ..." << endl; x=x0;y=y0;r=r0;}
~Cerc ()
{cout << "Dealocare..." << endl; }
void Tip ()
{cout << " C("<<x<<","<<y<<","<<r<<")" << endl; }
};
void main (void)
{
Cerc C(1,2,3); C.Tip();
}
// Rezultatele afişate:
Alocare ...
C(1,2,3)
Dealocare...

26.11.18 70
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor se poate urmării momentul în care acţionează constructorul şi
destrucorul:
/ / Obiecte alocate dinamic ( operatorul d e l e t e )

#include <string.h>;
#include <iostream.h>;

class Natural { char* Numar;


public:
Natural (char* Nr);
~Natural ();
};

Natural::Natural(char* Nr)
{ Numar = new char[strlen(Nr)+1];
strcpy(Numar,Nr);
cout << " Constr.Ob. ..." << Numar << endl;
}

Natural::~Natural()
{ cout << " ... Distr.Ob. " << Numar << endl;
delete Numar;
}

void f(Natural x)
{ cout << " ... f(x) ... " << endl; }

Natural x("123");

void main (void)


{ cout << "*Start*" << endl;
Natural y("456"); f("789");
cout << "*Stop*" << endl;
}

// Rezultatele afişate:
Constr.Ob. ...123
*Start*
Constr.Ob. ...456
Constr.Ob. ...789
... f(x) ...
... Distr.Ob. 789
*Stop*
... Distr.Ob. 456
... Distr.Ob. 123

26.11.18 71
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
18. Specificarea claselor – Limbajul UML(Unified Modeling Language)

UML specifică entităţile (clasele) dintr-un program şi relaţiile dintre ele astfel:
 Specificarea entităţilor :

 numele clasei,
 date membru - protecţie nume_dată : tip
 funcţii membru - protecţie nume_funcţie (tip par.formali) : tip_funcţie
( protecţie poate fi – (private), # (protected) sau + (public) ).

numele claseidate Punct- x : float


- y : float+ Punct ( )
membrufuncţii membru + Punct (Punct&)
Exemplu:
+~Punct ( )

 Specificarea relaţiilor dintre clase :

 relaţia de asociere : // prietenie

 relaţia de derivare : // moştenire

Punct- x : float Persoană- Nume : String+


- y : float+ Punct ( ) Persoană ( )
+ Punct (Punct&) + Persoană (Persoană &)
+~Punct ( ) +~Persoană ( )

Segment- A : Punct Student- Facultate:


- B : Punct+ Segment ( ) String
+ Segment (Segment&) - Varstă : int+ Student
+~Segment ( ) ()
+ Student (Student &)
+~Student ( )

26.11.18 72
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
19. F u n c ţ i i ş i C l a s e P r i e t e n e ( F r i e n d )
O funcţie este prietenă cu o clasă dacă are acces la datele membru private ale
acelei clase. O funcţie prietenă poate fi o funcţie globală sau chiar o funcţie membru a
altei clase.
O clasă este prietenă cu o altă clasă dacă ea are acces la datele membru ale
acesteia.
O funcţie, respectiv o clasă prietenă se declară utilizând cuvântul friend astfel:
a) friend Tip_funcţie Nume_funcţie ( Listă_parametri_formali ); // Funcţie friend globală
b) friend Tip_funcţie Nume_clasă::Nume_funcţie(Listă_par._formali); // Funcţie friend membru
c) friend Nume_clasă; // Clasă friend

Următorul exemplu, nu este corect, deoarece elementul C.y nu este accesibil:


// Funcţie friend membru
# include <math.h> #include <iostream.h>
class Punct { float x,y; // private:
public: Punct ( ) { x= 0, y= 0; }
Punct (float x0, float y0) { x=x0, y=y0; }
};
class Cerc { Punct C; float r;
public: Cerc (Punct O, float raza) { C=O, r=raza;}
int TaieOx() { return fabs(C.y)<r; }
//inaccesibil
};
void main ()
{ Punct C(10,10); Cerc c(C,4);
if (c.TaieOx()) cout << " Cercul c intersecteaza axa Ox ";
else cout << " Cercul c nu intersecteaza axa Ox ";
} // secret world

O soluţie pentru a rezolva această problemă, ar putea fi declararea funcţiei membru


TaieOx ca funcţie prietenă a clasei Punct. Această modificare nu este suficientă deoarece
clasa Cerc nu a fost încă (deja!) definită, deci aceasta trebuie mai întâi declarată, iar pentru
că aceasta referă clasa Punct vom declara (pur şi) simplu clasa Punct pentru a putea referi
centrul cercului ca pointer la Punct. Pentru că y nu este dată membru pentru cerc,
funcţia TaieOx nu poate fi definită imediat, ci doar ulterior, după declararea completă a
clasei Punct.
// Funcţie friend membru
# include <math.h> #include <iostream.h>
class Punct;
class Cerc { Punct* C; float r;
public: Cerc (Punct O, float raza) { *C=O; r=raza;}
int TaieOx();
};
class Punct { float x,y;
public: Punct ( ) { x= 0, y= 0; }
Punct (float x0, float y0) { x=x0, y=y0; }
friend int Cerc ::TaieOx();
};
int Cerc::TaieOx() { return fabs(C->y)<r; }
void main ()
{ Punct C(10,10); Cerc c(C,14);
if (c.TaieOx()) cout << " Cercul c intersecteaza axa Ox ";
else cout << " Cercul c nu intersecteaza axa Ox ";
}

26.11.18 73
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemple:
// Functie globala friend \\
# include <dos.h>
# include <conio.h>
# include <graphics.h>
# include <iostream.h>
# define Cale "c:\\BorlandC\\Bgi"
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale);}
~Grafic( ) { closegraph(); }
};
class Punct { int x, y;
public: Punct (int x0=0,int y0=0) { x=x0; y=y0;
putpixel(x,y,x+y);}
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(x,y); }
void Trag () { lineto(x,y); }
~Punct () { }
friend Punct Mijloc(Punct,Punct); // Functii globale
friend Punct Afin (Punct,Punct,float); // friend
};
Punct Mijloc (Punct A, Punct B) { Punct M (int((A.x+B.x)/2),
int((A.y+B.y)/2));
return M; }
Punct Afin (Punct A, Punct B,float t) { Punct M (int((1-t)*A.x+t*B.x+0.5),
int((1-t)*A.y+t*B.y+0.5));
return M; }
class Segment{Punct A, B; // Capetele Segm.
public:
Segment ( ) : A(), B() { }
Segment (Punct P, Punct Q) { A=P; B=Q;
A.Muta();B.Trag(); }
Segment (Segment& AB) { A=AB.A; B=AB.B; }
~Segment () { A.Muta();B.Trag(); }
Punct Mijlocs () { return Mijloc(A,B);} // ::Mijloc
Punct Afins (float t) { return Afin(A,B,t);} // ::Mijloc
};
void main (void)
{
Grafic Mod(DETECT); setwritemode(XOR_PUT); setbkcolor(BLUE);
Punct* A = new Punct (300,100); // A
Punct* B = new Punct (100,300); // B
Punct* C = new Punct (500,300); // C
Segment* AB = new Segment (*A,*B); // AB
Segment* BC = new Segment (*B,*C); // BC
Segment* CA = new Segment (*C,*A); // CA
for (float Alfa=0; Alfa<1; Alfa+=0.01)
{ Punct* P=new Punct(AB->Afins(Alfa));
Punct* Q=new Punct(CA->Afins(Alfa));
Segment*PQ = new Segment (*P,*Q);
PQ->Mijlocs(); delay(22); // [Punct M=]
delete PQ; delete P; delete Q;
} delete AB; delete A; delete B; getche();
delete BC; delete CA;
}

26.11.18 74
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Functie membru friend \\
# include <dos.h>
# include <math.h>
# include <conio.h>
# include <graphics.h>
# include <iostream.h>
# define Cale "c:\\BorlandC\\Bgi"
float Sqr (int x) { return float(x)*x; }
int Sqrt (float x) { return ceil (sqrt(x)+0.5); }
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale);
setbkcolor(BLUE); }
~Grafic( ) { getche(); closegraph(); }
};
class Punct;
class Segment{Punct *A, *B; // Capetele Segm.
public:
Segment ( ) : A(), B() { }
Segment (Punct*,Punct*);
Segment (Segment&);
~Segment ();
Punct Mijloc ();
};
class Punct { int x, y;
public: Punct (int x0=0,int y0=0) { x=x0; y=y0;
putpixel(x,y,x+y);}
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(x,y); }
void Trag () { lineto(x,y); }
~Punct () { }
friend Punct Segment::Mijloc();
};
Segment:: Segment (Punct *P, Punct *Q) { A=P; B=Q; A->Muta(); B->Trag(); }
Segment:: Segment (Segment& AB) { A=AB.A; B=AB.B; }
Segment::~Segment ( ) { A->Muta(); B->Trag(); }
Punct Segment::Mijloc() { Punct M ( int((A->x+B->x)/2),
int((A->y+B->y)/2));
return M; }
void main (void)
{ Grafic Mod(DETECT); setwritemode(XOR_PUT); int Lung=400;
Punct* O = new Punct; // Originea
Punct* X = new Punct(Lung);
Punct* Y = new Punct(0,Lung);
Segment* OX = new Segment(O,X); // Axa Ox;
Segment* OY = new Segment(O,Y); // Axa Ox;
for (int x=1; x<Lung; x++)
{ Punct* P = new Punct (x);
Punct* Q = new Punct (0,Sqrt(Sqr(Lung)-Sqr(x)));
Segment* PQ = new Segment(P,Q);
PQ->Mijloc(); delay(9);
delete PQ; delete P; delete Q;
} getche();
delete OX; delete OY; delete O; delete X; delete Y;
}

26.11.18 75
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Clasa friend \\
# include <dos.h> # include <math.h> # include <conio.h> # include <graphics.h> # include <iostream.h>
# define Cale "c:\\BorlandC\\Bgi"
struct palettetype pal; float Pi=3.1416, Alfa;
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale);
getpalette(&pal); }
~Grafic( ) { getche(); closegraph(); }
};
class Punct { int x, y;
public: Punct (float x0=0,float y0=0) { x=int(x0);y=int(y0); }
Punct (float x0,float y0,int c)
{x=int(x0+0.5);y=int(y0+0.5);putpixel(x,y,c);}
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(x,y); }
void Trag () { lineto(x,y); }
~Punct () { }
friend Segment;
friend Cerc;
friend Triunghi;
};
class Segment{Punct A, B; int Cul; // Capetele Segm.
public: Segment ( ) : A(), B() { }
Segment (Punct P, Punct Q){ Cul=getcolor();setcolor (Cul);
A=P; B=Q; A.Muta();B.Trag(); }
Segment (Segment& AB) { A=AB.A; B=AB.B; }
~Segment () { setcolor(Cul);A.Muta();B.Trag(); }
Punct Mijloc ();
friend Triunghi;
};
Punct Segment::Mijloc () { Punct M(int((A.x+B.x)/2),int((A.y+B.y)/2)); return M;}
class Cerc { int x, y, r;
public: Cerc (int x0=0,int y0=0,int r0){ x=x0;y=y0;r=r0; circle(x,y,r);}
Cerc (Punct P, int r0) { x=P.x; y=P.y; r=r0; circle(x,y,r);}
Cerc (Cerc& C) { x=C.x; y=C.y; r=C.r; }
Punct PeCerc(float a){ Punct M(x+r*cos(a),y-r*sin(a)); return M;}
~Cerc () { /*circle(x,y,r);*/ }
};
class Triunghi { Punct A, B, C; // Varfuri
public:
Triunghi ( ) : A(), B(), C() { }
Triunghi (Punct,Punct,Punct);
Triunghi (Triunghi& ABC) { A=ABC.A; B=ABC.B; C=ABC.C;}
Punct CentruGr(){ Punct G((A.x+B.x+C.x)/3,(A.y+B.y+C.y)/3,15);
return G; }
~Triunghi (){}
};
Triunghi::Triunghi(Punct P,Punct Q,Punct R) { A=P; B=Q; C=R;
setcolor(YELLOW); Segment AB(A,B); Segment BC(B,C); Segment CA(C,A);
setcolor(LIGHTBLUE); Segment AAP(A,BC.Mijloc());
Segment BBP(B,CA.Mijloc());Segment CCP(C,AB.Mijloc());
int Cf=int((Pi-fabs(Alfa-Pi))/Pi*63); // r g b
setrgbpalette(pal.colors[BLUE], 0, 0, Cf);
setrgbpalette(pal.colors[YELLOW], 63 ,63-Cf,0);
setrgbpalette(pal.colors[LIGHTBLUE], 0, Cf, 63);
setrgbpalette(pal.colors[WHITE], Cf, Cf, Cf);
delay(int(pow((fabs(Alfa-Pi)+0.3)*Pi,2))); }
void main (void)
{ Grafic Mod(DETECT); setwritemode(XOR_PUT); setbkcolor(BLUE);
Punct O(300,250); Cerc c(O,200); // centru, cerc
float uA=Pi/2, uB=Pi+Pi/6, uC=-Pi/4;
for (Alfa=0; Alfa<2*Pi; Alfa+=0.01) {
Triunghi ABC(c.PeCerc(Alfa+uA),c.PeCerc(Alfa+uB),c.PeCerc(Alfa+uC));
ABC.CentruGr(); }
}

26.11.18 76
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
20. M e m b r i s t a t i c i ( S t a t i c ) // $ :
Fiecare obiect dintr-o clasă deţine toate datele membru (atributele) acesteia. Există
însă posibilitatea ca toate instanţele unei clase să deţină anumite atribute comune tuturor
obiectelor clasei respective. Aceşti membri (date, funcţii) statici au acelaşi regim de
protecţie ca şi ceilalţi membrii.

20.1. Atribute (Date membru) Statice // $ :


Datele membru statice, care urmează să fie utilizate de către toate obiectele clasei,
se definesc prin specificatorul static astfel:
class Nume_clasă { …
static Listă_Declaraţii_date_membru ; // $ :

};

Datele membru statice, se declară (se iniţializează) explicit în afara clasei:


Tip_dată_membru Nume_clasă :: Dată_membru [ = Valaore ];

Referirea (utilizarea) datelor membru statice se poate face astfel:


a) … Nume_clasă ::Dată_membru … // Referire naturală (globală) la clasă
b) … Obiect  Dată_membru … // Referire particulară la un obiect
c) … Pointer_Obiect >Dată_membru … // Referire particulară prin pointer

În următorul exemplu, se numără câte Puncte sunt utlizate la un moment dat în


program, utilizând ca dată comună pentru toate punctele (întreaga clasă) Nr_Ob:

// Membru Static
# include <conio.h>
# include <iostream.h>

class Punct { float x, y;


public:
Punct () { x=0; y=0; Nr_Ob++; }
Punct (float x,float y) { this->x=x;
this->y=y; Nr_Ob++; }
Punct (Punct& P) { x=P.x; y=P.y;Nr_Ob++; }
~Punct () { Nr_Ob--; }
static int Nr_Ob; // $:
};

int Punct::Nr_Ob=0; // se iniţializează

26.11.18 77
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
void main (void)
{ Punct A,B; clrscr();
cout << "Initial:" << Punct::Nr_Ob << endl;
for (int i=1; i<=5; i++) {
Punct M(i,i); Punct Q(M);
cout << "i>> "<<i<<":"<< Punct::Nr_Ob <<endl;
if (i%2==0) {
Punct* N=new Punct(i,i); Punct R(*N);
cout <<"i<<"<<i<<":"<< Punct::Nr_Ob <<endl; // Cl::Static.
cout <<"i<<"<<i<<":"<< R .Nr_Ob <<endl; // Ob .Static!
cout <<"i<<"<<i<<":"<< N->Nr_Ob <<endl; // Ob->Static!
delete N;
}
cout << "i..." <<i<< ":"<< Punct::Nr_Ob <<endl; }
cout << "Final..." << Punct::Nr_Ob << endl; getche();
}

În exemplul următor, sunt utilizaţi membri statici a,b,c,d pentru a memora domeniul
minim care conţine toate punctele curbei (definite parametric) care se desenează:

// Membri Statici
# include <math.h> # include <conio.h> # include <graphics.h>
# define Cale "c:\\BorlandC\\Bgi"
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale); setbkcolor(BLUE);}
~Grafic( ) { getche(); closegraph();} };
int u (float);
int v (float);
class Punct { float x, y;
public: Punct () { x=0; y=0; }
void Atrib (float x,float y) { this->x=x; if (x<a) a=x; else
if (x>b) b=x;
this->y=y; if (y<c) c=y; else
if (y>d) d=y; }
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(u(x),v(y)); }
void Trag () { lineto(u(x),v(y)); }
~Punct () { }
static float a,b, c,d; // Fereastra Reală
};
float Punct::a, Punct::d, Punct::b, Punct::c; // Fereastra Reală
int u1=110, v1=20, u2=500, v2=430; // Fereastra Ecran
int u (float x) { return ((x-Punct::a)/(Punct::b-Punct::a)*(u2-u1)+u1); }
int v (float y) { return ((y-Punct::d)/(Punct::c-Punct::d)*(v2-v1)+v1); }
float x (float t) { return cos(2*t)*cos(t); } // x(t)
float y (float t) { return cos(4*t)*sin(t); } // y(t)
void main (void)
{ int i,n=1000; float Pi=3.14153; Grafic Mod(DETECT);
Punct P[1001];
Punct::b=Punct::a=x(0);
Punct::d=Punct::c=y(0);
for (i=0; i<=n; i++) { float Alfa=2*Pi*i/n; P[i].Atrib(x(Alfa),y(Alfa));}
P[0].Muta(); setcolor(WHITE);
for (i=1; i<=n; i++) P[i].Trag();
}

26.11.18 78
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
20.2. Metode (Funcţii membru) Statice // $ :
Metodele (Funcţiile membru) statice, acţionează doar asupra atributelor statice
(ale claselor), deci nu pot acţiona asupra atributelor obiectului curent (deoarece nu li se
transmite poinetrul this). De asemenea ele pot apela doar metodele statice. Pot însă
acţiona asupra atributelor unui anumit obiect prin operatorii  sau >. Metodele statice, se
definesc prin specificatorul static astfel:
class Nume_clasă { …
static Tip_funcţie Nume_funcţie ( Listă_par_formali ) … // $ :

};
Referirea (utilizarea) metodelor statice se face astfel:
a) … Nume_clasă :: Funcţie_membru (Listă_par_actuali)… // Referire naturală la clasă
b) … Obiect  Funcţie_membru (Listă_par_actuali) … // Referire la un obiect
c) … Pointer_Obiect > Funcţie_membru (Listă_par_actuali)… // Referire prin pointer
În următorul exemplu, se determină fereastra reală (definită prin cele două puncte
diagonal opuse St_Sus, Dr_Jos) utilizând funcţiile statice MinX, MaxX, MinY, MaxY pentru a
determina domeniul minimal care include punctele din grafic.
// Funcţii Statice
# include <math.h> # include <conio.h> # include <graphics.h>
# define Cale "c:\\BorlandC\\Bgi"
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale); setbkcolor(BLUE);}
~Grafic( ) { getche(); closegraph();} };
int u (float); int v (float);
class Punct { float x, y;
public: Punct () { x=0; y=0; }
void Atrib (float x,float y){ this->x=x; if (x<MinX()) St_Sus.x=x; else
if (x>MaxX()) Dr_Jos.x=x;
this->y=y; if (y<MinY()) Dr_Jos.y=y; else
if (y>MaxY()) St_Sus.y=y; }
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(u(x),v(y)); }
void Trag () { lineto(u(x),v(y)); }
~Punct () { }
static Punct St_Sus, Dr_Jos; // Fereastra Reala
static float MinX() { return St_Sus.x; } // Metodă Statică
static float MaxX() { return Dr_Jos.x; } // Metodă Statică
static float MinY() { return Dr_Jos.y; } // Metodă Statică
static float MaxY() { return St_Sus.y; } // Metodă Statică
};
Punct Punct::St_Sus, Punct::Dr_Jos; // Fereastra Reala
int u1=110, v1=20, u2=500, v2=430; // Fereastra Ecran
int u (float x) { return ((x-Punct::MinX())/(Punct::MaxX()-Punct::MinX())*(u2-u1)+u1); }
int v (float y) { return ((y-Punct::MaxY())/(Punct::MinY()-Punct::MaxY())*(v2-v1)+v1); }
float x (float t) { return cos(2*t)*cos(t); }// x(t)
float y (float t) { return cos(4*t)*sin(t); }// y(t)
void main (void)
{ int i,n=1000; float Pi=3.14153; Grafic Mod(DETECT);
Punct P[1001]; P[0].Atrib(x(0),y(0));
Punct::St_Sus=Punct::Dr_Jos=P[0];
for (i=1; i<=n; i++) { float Alfa=2*Pi*i/n; P[i].Atrib(x(Alfa),y(Alfa));}
P[0].Muta(); setcolor(WHITE); for (i=1; i<=n; i++) P[i].Trag();
}

21. Pointeri la Metode

O metodă a unei clase poate fi referită (apelată) şi printr-un pointer la ea.

26.11.18 79
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
 Definirea unui pointer la o metodă se poate face astfel:
Tip_funcţie (Nume_clasă :: *Nume_Pointer ) ( Listă_par_formali ) // sau cu typedef

 Iniţializarea unui pointer la o metodă se poate realiza astfel:


Nume_Pointer = & Nume_clasă :: Nume_Metodă; // se pot realiza şi la definire

 Referirea unui pointer la o metodă (apelarea metodei) :


… (Nume_Obiect . *Nume_Pointer ) ( Listă_par_actuali ) …

De exemplu, pentru programul anterior, modificările necesare pentru a putea apela


cele două metode Muta şi Trag ale clase Punct pot fi următoarele:

// Pointeri la metode

class Punct { float x, y;
public: Punct () { … }
void Atrib …
Punct (Punct& P) {… }
void Muta () { moveto(u(x),v(y)); }
void Trag () { lineto(u(x),v(y)); }
~Punct () { }
static Punct St_Sus, Dr_Jos;
static float MinX() { return St_Sus.x; } // Metodă Statică

};

void main (void)


{ …
typedef void (Punct :: *P_Met)(); // Definire
P_Met Pm[2] = {&Punct::Muta,&Punct::Trag}; // Iniţializare

// sau:
// void (Punct :: *Pm[2])() = {&Punct::Muta,&Punct::Trag}; // Def+Ini

(P[0].*Pm[0])(); setcolor(WHITE); // Apel Muta


for (i=1; i<=n; i++) (P[i].*Pm[1])(); // Apel Trag
}

26.11.18 80
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Un alt exemplu, care utilizează pointeri la metode (Triun, Drept şi Romb) este
următorul:

// Pointeri la *Metode
# include <math.h>
# include <conio.h>
# include <graphics.h>
# define Cale "c:\\BorlandC\\Bgi"
class Grafic { int Gd, Gm;
public: Grafic(int gd) { Gd=gd; initgraph(&Gd,&Gm,Cale); setbkcolor(BLUE);}
~Grafic( ) { getche(); closegraph();} };
int u (float);
int v (float);
class Punct { float x, y;
public: Punct () { x=0; y=0; }
void Atrib (float x,float y) { this->x=x; if (x<MinX()) St_Sus.x=x; else
if (x>MaxX()) Dr_Jos.x=x;
this->y=y; if (y<MinY()) Dr_Jos.y=y; else
if (y>MaxY()) St_Sus.y=y; }
Punct (Punct& P) { x=P.x; y=P.y; }
void Muta () { moveto(u(x),v(y)); }
void Triun () { setcolor(WHITE); Muta();
moverel(0,-3); linerel(-2,5);
linerel(4,0); linerel(-2,-5);}
void Drept () { setcolor(LIGHTRED); Muta();
moverel(-2,-2); linerel(0,4);
linerel(4,0); linerel(0,-4);linerel(-4,0);}
void Romb () { setcolor(YELLOW); Muta();
moverel(0,-3); linerel(-2,3);
linerel(2,3); linerel(2,-3);linerel(-2,-3);}
~Punct () { }
static Punct St_Sus, Dr_Jos; // Fereastra Reala
static float MinX() { return St_Sus.x; }
static float MaxX() { return Dr_Jos.x; }
static float MinY() { return Dr_Jos.y; }
static float MaxY() { return St_Sus.y; }
};
Punct Punct::St_Sus, Punct::Dr_Jos; // Fereastra Reala
int u1=110, v1=20, u2=500, v2=430; // Fereastra Ecran
int u (float x) { return ((x-Punct::MinX())/(Punct::MaxX()-Punct::MinX())*(u2-u1)+u1); }
int v (float y) { return ((y-Punct::MaxY())/(Punct::MinY()-Punct::MaxY())*(v2-v1)+v1); }
float x0 (float t) { return cos(4*t)*cos(t); } // x(t)
float y0 (float t) { return cos(2*t)*sin(t); } // y(t)
float x1 (float t) { return cos(2*t)*cos(t); } // x(t)
float y1 (float t) { return cos(4*t)*sin(t); } // y(t)
float x2 (float t) { return cos(t); } // x(t)
float y2 (float t) { return sin(t); } // y(t)

void main (void)


{ int i,j, n=300; float Pi=3.14153; Grafic Mod(DETECT);
Punct P[3][301];
typedef float (*Functie)(float);
Functie x[3]={&x0,&x1,&x2} ,y[3]={&y0,&y1,&y2};
for (j=0; j<=2; j++) P[j][0].Atrib((*x[j])(0),(*y[j])(0));
Punct::St_Sus=Punct::Dr_Jos=P[0][0];
for (j=0; j<=2; j++) for (i=0; i<=n; i++) {
float Alfa=2*Pi*i/n; P[j][i].Atrib((*x[j])(Alfa),(*y[j])(Alfa)); }
void (Punct::*Desen[3])()={&Punct::Triun,&Punct::Drept,&Punct::Romb};
for (j=0; j<=2; j++) for (i=0; i<=n; i++) (P[j][i].*Desen[j])();
} // Mummers Dance

26.11.18 81
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
22. Supraîncărcarea operatorilor
Anumite operaţii se pot exprima mult mai bine prin operatori. Nu se pot defini
operatori noi, dar se pot supraîncărca cei existenţi ( +, <, ++, +=, >, [ ], ( ), new, delete,
…, mai puţin operatorii *, :: , ?: ), fără a modifica însă aritatea, prioritatea sau
asociativitatea.
Supraîncărcarea se poate face cu:
a) funcţii membru - numărul parametrilor fiind egal cu aritatea operatorului minus unu,
deoarece un operand este chiar obiectul curent pentru care se apelează metoda (acesta
putând fi referit prin pointerul this),
b) funcţii prietene - numărul parametrilor fiind egal cu aritatea operatorului.

Redefinirea unui operator se realizează printr-o funcţie (prietenă sau membru) al


cărei nume este compus din cuvântul operator urmat de operatorul propriuzis (+, <, …) .

Exemplu:
// Op erat ori de c on c at en are + & \\
# include <Conio.h>
# include <String.h> # include <Iostream.h>
class String { char* s;
public:
String (); // Constructor implicit
String (const String&); // Constructor de copiere
String (const char*); // Constructor de conversie
String& operator=(const String&); // Operator de atribuire
String operator+(String&); // Operator + (concatenare) a)
friend String operator&(String&,String&); // Operator & (concatenare) b)
~String (); // Destructor
int Length (); // Lungimea sirului
void Print (); // Tipareste sirul
};
String::String () { s=new char; s[0]=0; }
String::String (const String& S) { s=new char[S.Length( )+1];strcpy(s,S.s);}
String::String (const char* S) { s=new char[ strlen(S)+1];strcpy(s,S); }
String& String::operator=(const String& S)
{ if (s!=S.s) {delete []s; s=new char[S.Length()+1]; strcpy(s,S.s);} return *this; }
String String::operator+(String& S) // funcţie membru a)
{ char* sS=new char[this->Length()+S.Length()+1];
strcpy(sS,s); strcpy(sS+this->Length(),S.s); String Rez(sS); delete sS; return Rez; }
String::~String () { delete []s;}
int String::Length () { return strlen(s); }
String operator&(String& s,String& S) // funcţie prietenă b)
{ char* sS=new char[s.Length()+S.Length()+1];
strcpy(sS,s.s); strcpy(sS+s.Length(),S.s); String Rez(sS); delete sS; return Rez; }
void String::Print () { cout << s << endl; }
void main ()
{ clrscr();
String Nume("Popescu"), Prenume("Ionel");
String Nume_Prenume=Nume+" "+Prenume;
Nume_Prenume.Print();
String Prenume_Nume=Prenume&" "&Nume;
Prenume_Nume.Print(); getche();
}

26.11.18 82
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
22.1. Operatorul de asignare (atribuire) şi iniţializare (=)

Operatorul de atribuire (=) se poate utiliza şi pentru obiecte, acesta fiind


supraîncărcat implicit şi realizează copierea datelor membru. Dacă însă datele membru
sunt referinţe (pointeri) la nişte variabile dinamice, atunci prin copiere se vor obţine două
obiecte care referă acceaşi zonă de memorie, iar la dealocare se va elibera aceeaşi zonă de
două ori, iar alta niciodată, ceea ce ne obligă, în această situaţie, la redefinirea
(supraîncărcarea) acestui operator. Prin aceasta, conţinutul variabilelor dinamice sunt
identice, dar la adrese diferite, astfel încât dacă un obiect îşi modifică valorile, celălalt obiect
rămâne neschimbat.

Pentru o declaraţie de tipul Clasă Obiect; se va apela constructorul implicit, sau


cel cu toţi parametrii impliciţi, iar pentru o declaraţie de forma Clasă Obiect=Ob; se va
apela constructorul de copiere (şi nu operatorul de atribuire) ca şi la o declaraţie de forma
Clasă Obiect(Ob); . Constructorul de copiere se mai poate apela dacă parametrul unei
funcţii este un obiect sau dacă funcţia returnează un obiect.

Exemplu:

// C l asa Nu m ar Nat u ral (Op. = ) \\


# include <Conio.h>
# include <String.h>
# include <Iostream.h>

class Natural { char* s;


int Lung(unsigned long);
public:
Natural ( ); // Constructor implicit
Natural (const Natural&); // ... de copiere
Natural (unsigned long); // ... de conversie

Natural& operator= (const Natural&); // Operator de atribuire


Natural operator+ (const Natural&); // Operator de adunare
Natural operator- (const Natural&); // Operator de scadere

int operator< (const Natural&); // ... relational <


int operator<=(const Natural&); // ... ... <=
int operator> (const Natural&); // ... ... >
int operator>=(const Natural&); // ... ... >=
int operator==(const Natural&); // ... ... ==
int operator!=(const Natural&); // ... ... <>

~Natural (); // Destructor


int Length (); // Numarul de cifre
void Input (); // Citeste numar
void Print (); // Tipareste numar
};

26.11.18 83
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Natural::Natural ( ) { s=new char[2]; s[0]='0'; s[1]=0; }
Natural::Natural (const Natural& S)
{ s=new char[strlen(S.s)+1];strcpy(s,S.s);}
Natural::Natural (unsigned long S)
{ int n=Lung(S); s=new char[n+1]; s[n]=0;
for(int i=n-1;i>=0;i--) {s[i]=S%10+48; S/=10;} }
Natural& Natural::operator = (const Natural& S)
{ if (s!=S.s) { delete []s; s=new char[strlen(S.s)+1]; strcpy(s,S.s);}
return *this; }
char* Suma (const char*, const char*);
Natural Natural::operator + (const Natural& S)
{ Natural Sum; Sum.s=Suma(s,S.s); return Sum; }
char* Dif(const char*, const char*);
Natural Natural::operator - (const Natural& S)
{ Natural D; D.s=Dif(s,S.s); return D; }
int Natural::operator< (const Natural& S)
{ if (strlen(s)<strlen(S.s)) return 1; else
if (strlen(s)>strlen(S.s)) return 0; else return strcmp(s,S.s)<0; }
int Natural::operator<=(const Natural& S) { return !(*this>S); }
int Natural::operator> (const Natural& S) { return S< *this; }
int Natural::operator>=(const Natural& S) { return S<=*this; }
int Natural::operator==(const Natural& S) { return strcmp(s,S.s)==0; }
int Natural::operator!=(const Natural& S) { return strcmp(s,S.s)!=0; }
int Natural:: Length () { return strlen(s); }
void Natural:: Print () { cout << s << endl; }
void Natural:: Input () { char* x=new char[100]; cin >> x;
delete []s; s=new char[strlen(x)+1];
strcpy(s,x); delete x; }
Natural::~Natural() { delete []s; }
int Natural::Lung(unsigned long n)
{ if (n<10) return 1; else return Lung(n/10)+1;}
char* Suma (const char* a, const char *b)
{ int m=strlen(a), n=strlen(b), i=m-1, j=n-1, t=0; if (m<n) return Suma(b,a);
char* c=new char[m+1]; c[m]=0;
for ( ; i>=0; i--) {
if (j>=0) c[i]=a[i]+b[j]+t-48; else c[i]=a[i]+t;
if(c[i]>'9'){ c[i]-=10; t=1 ; } else t=0; j--; }
if (!t) return c;
char* d=new char[m+2]; for (i=0,d[0]='1'; i<=m; i++) d[i+1]=c[i];
delete []c; return d;
}
char* Dif (const char* a, const char *b)
{ int m=strlen(a), n=strlen(b), i=m-1, j=n-1, t=0;
char* c=new char[m+1]; c[m]=0;
for ( ; i>=0; i--) {
if (j>=0) c[i]=a[i]-b[j]-t+48; else c[i]=a[i]-t;
if(c[i]<'0'){ c[i]+=10; t=1 ; } else t=0; j--; }
char *d=c; while((*d=='0') && *(d+1)) d++;
strcpy(c,d); return c;
}
void main ()
{ clrscr();
Natural a,b;
cout << " a : "; a.Input();
cout << " b : "; b.Input();

cout << " a+b = "; (a+b).Print(); ;


cout << "|a-b|= "; if (a>=b) (a-b).Print(); else
(b-a).Print(); getche();
}

26.11.18 84
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
22.2. Operatorii de atribuire += , = , * = , /=
Aceşti operatori (+=, =, *=, /=) nu sunt supraîncărcaţi automat, deci dacă dorim
să-i utilizăm va trebui să îi redefinim (aşa cum se poate vedea în exemplul următor
supraîncărcarea operatorilor +=, =).

Exemplu:
// C l asa Nu m ar Nat u ral (Op. +=, -= ) \\
# include <Conio.h>
# include <String.h> # include <Iostream.h>
class Natural { char* s;
int Lung(unsigned long);
public:
Natural ( ); // Constructor implicit
Natural (const Natural&); // ... de copiere
Natural (unsigned long); // ... de conversie
Natural& operator= (const Natural&); // Operator de atribuire
Natural operator+ (const Natural&); // Operator de adunare
Natural operator- (const Natural&); // Operator de scadere
Natural& operator+=(Natural&); // ... de ad.&.atr.
Natural& operator-=(Natural&); // ... de sc.&.atr.
int operator< (const Natural&); // ... relational <
int operator<=(const Natural&); // ... ... <=
int operator> (const Natural&); // ... ... >
int operator>=(const Natural&); // ... ... >=
int operator==(const Natural&); // ... ... ==
int operator!=(const Natural&); // ... ... <>
~Natural (); // Destructor
int Length (); // Numarul de cifre
void Print (); // Tipareste numar
};
Natural::Natural ( ) { … }
Natural::Natural (const Natural& S) { … }
Natural::Natural (unsigned long S) { … }
Natural& Natural::operator= (const Natural& S){ … }
char* Suma (const char* a, const char *b) { … }
char* Dif (const char* a, const char *b) { … }
Natural Natural::operator+ (const Natural& S){ Natural Sum; Sum.s=Suma(s,S.s); return Sum;}
Natural Natural::operator- (const Natural& S){ Natural D; D.s=Dif(s,S.s); return D;}
Natural& Natural::operator +=(Natural& S){return *this = *this + S;}
Natural& Natural::operator -=(Natural& S){return *this = *this - S;}
int Natural::operator< (const Natural& S) { … }
int Natural::operator<=(const Natural& S) { … }
int Natural::operator> (const Natural& S) { … }
int Natural::operator>=(const Natural& S) { … }
int Natural::operator==(const Natural& S) { … }
int Natural::operator!=(const Natural& S) { … }
int Natural:: Length () { … }
void Natural:: Print () { … }
Natural::~Natural() { … }
int Natural::Lung(unsigned long n) { … }
void main ()
{ Natural a(125),b(175); clrscr();
while (a!=b) if (a>b) a-=b; else b-=a;
if (a==1) cout << " Prime intre ele ";
else { cout << "Cmmdc="; a.Print(); } getche();
} 

26.11.18 85
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
22.3. Operatorii de incrementare (++) şi decrementare ( )
Continuând cu exemplul anterior, dorim să suparaîncărcăm operatorii de
incrementare si decrementare, mai întâi cei prefixaţi (++x, x), unde nu sunt probleme
deosebite, apoi ce postfixaţi (x++, x). Pentru a supraîncărca şi operatorii de
incrementare postfixaţi vom adăuga câte o funcţie membru având un parametru de tip int
(care nu se va folosi, şi care automat la un apel va lua valoarea zero).

Exemplu:
// C l asa Nu m ar Nat u ral (Op . ++x, - - x, x+ +, x- -) \\
# include <Conio.h>
# include <String.h> # include <Iostream.h>
class Natural { char* s;
int Lung(unsigned long);
public:
Natural ( ); // Constructor implicit
Natural (const Natural&); // ... de copiere
Natural (unsigned long); // ... de conversie
Natural& operator= (const Natural&); // Operator de atribuire
Natural operator+ (const Natural&); // Operator de adunare
Natural operator- (const Natural&); // Operator de scadere
Natural& operator ++(); // ... prefixat incr
Natural operator ++(int); // ... postfixat ...
Natural& operator --(); // ... prefixat decr
Natural operator --(int); // ... postfixat ...
int operator < (const Natural&); // ... relational <
~Natural (); // Destructor
int Length (); // Numarul de cifre
ostream& Tip (ostream& S); // cout << x…
istream& Cit (istream& S); // cin >> x…
};
Natural::Natural ( ) { … }
Natural::Natural (const Natural& S) { … }
Natural::Natural (unsigned long S) { … }
Natural& Natural::operator= (const Natural& S){ … }

Natural Natural::operator+(const Natural& S) { … }
Natural Natural::operator-(const Natural& S) { … }
int Natural::operator< (const Natural& S) { … }
Natural::~Natural() { … }
Natural& Natural::operator++() { return *this=*this+1; } // ++x
Natural& Natural::operator--() { return *this=*this-1; } // --x
Natural Natural::operator++(int){ Natural x(*this); *this=*this+1; return x;} // x++
Natural Natural::operator--(int){ Natural x(*this); *this=*this-1; return x;} // x--
ostream& Natural::Tip (ostream& S) { S << s; return S; } // cout
istream& Natural::Cit (istream& S) { char* x=new char[256]; S>>x; delete[]s;
s=new char[strlen(x)+1]; strcpy(s,x); delete x; return S; } // cin
ostream& operator << ( ostream& S, Natural s ) { return s.Tip(S); } // <<
istream& operator >> ( istream& S, Natural& s ) { return s.Cit(S); } // >>
void main ()
{ Natural i, n=1001, k; clrscr();
cout << " Limita : "; cin >> k;
for (i=101; i<n; i++) if (i<k) cout << i << endl; getche();
}

26.11.18 86
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
23. Conversii utilizator
Conversiile sunt executate automat dacă:
a) operanzii nu sunt de acelaşi tip (char, enum  int  double, ..., iar la atribuire se face
conversia valoarii expresiei în tipul variabilei);
b) parametrul actual nu are tipul parametrului formal (se face conversia primului);
c) tipul valorii returnate de o funcţie diferă de tipul acesteia (se face conversia valorii).

23.1. Conversii implicite


23.1.1. Conversia dintr-un tip predefint într-un tip abstract
Conversiile dintre un tip predefinit şi un tip abstract se pot realiza printr-un
constructor care să conţină un parametru având acel tip predefinit, iar ceilalţi vor fi
iniţializaţi.
Exemplu:
/ / N u m e re r a ţ i o n a l e : Q
#include <string.h>; #include <iostream.h>; #include <conio.h>;
long Cmmdc(long, long);
class Q { long m, n; // m / n
public: Q (long, long); // constructor implicit
Q& operator ~(); // operator de simplificare
friend Q operator *(Q, Q); // functie prietenă
void Tip(const char* Mes=""); // tiparire (mesaj)
};
inline Q::Q(long p=0, long q=1 ) { m=p; n=q; }
Q& Q::operator ~()
{ long d=Cmmdc(m,n); m/=d; n/=d; return *this; }
Q operator *(Q r, Q s) {return ~Q(r.m*s.m, r.n*s.n); } // friend
inline void Q::Tip (const char* Mes)
{ if (n) cout << Mes << m << "/" << n << endl;
else cerr << " Numitor nul " ;};
long Cmmdc(long a, long b)
{ if (b) return Cmmdc(b,a%b);
else return a; };
void main ()
{ clrscr();
Q x(3,2); x.Tip(" x : ");
Q y(2,9); y.Tip(" y : ");
Q z(2); z.Tip(" z : "); z=x*y; z.Tip(" x*y = ");
Q w(2,1); w.Tip(" w : "); z=x*w; z.Tip(" x*w = ");
z=x*2; z.Tip(" x*2 = "); z=2*x; z.Tip(" 2*x = "); getch();
} // R e z u l t a t e :
x : 3/2
y : 2/9
z : 2/1
x*y = 1/3
w : 2/1
x*w = 3/1
x*2 = 3/1
2*x = 3/1

26.11.18 87
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
O altă variantă în care se evită utilizarea unei funcţii prietene este de a defini o funcţie
membru (Produs) care se va apela de către funcţia de supraîncărcare a operatorului de
înmulţire.
Exemplu:
/ / N u m e re r a ţ i o n a l e : Q
#include <string.h>; #include <iostream.h>; #include <conio.h>;
long Cmmdc(long, long);
class Q { long m; long n; // m / n
public: Q (long, long); // constr. implicit
Q& operator ~(); // operator de simplificare
Q Produs (Q); // Produs
void Tip(const char* Mes=""); // tiparire (mesaj)
};
inline Q::Q(long p=0, long q=1 ) { m=p; n=q; }
Q& Q::operator ~()
{ long d=Cmmdc(m,n); m/=d; n/=d; return *this; }
inline Q Q::Produs (Q r) { return ~Q(m*r.m, n*r.n); }
Q operator *(Q p, Q q) { return p.Produs(q); } // operator de inmultire
inline void Q::Tip (const char* Mes)
{ if (n) cout << Mes << m << "/" << n << endl; else cerr << " Numitor nul " ;};
long Cmmdc(long a, long b) { if (b) return Cmmdc(b,a%b); else return a; };
void main ()
{ clrscr();
Q x(3,2); x.Tip(" x : ");
Q y(2,9); y.Tip(" y : ");
Q z(4,2); z.Tip(" z : ");
Q w;
w=x*y; w.Tip(" x*y= ");
w=x*z; w.Tip(" x*z= ");
w=x*2; w.Tip(" x*2= ");
w=2*x; w.Tip(" 2*x= "); getch();
} // R e z u l t a t e :
x : 3/2
y : 2/9
z : 4/2
x*y= 1/3
x*z= 3/1
x*2= 3/1
2*x= 3/1

23.1.2. Conversia dintr-un tip abstract într-un alt tip abstract


O altă problemă pe care o vom aborda în cele ce urmează este de a realiza o
conversie dintr-un tip abstract în altul. Pentru aceasta vom defini un constructor pentru
realizarea conversiei dorite.
În programul următor am definit tipul complex în cele două forme:
a) algebrică - clasa C,
b) trigonometrică (polară) - clasa T.
Conversia realizată face trecerea din forma b) în forma a).
Pentru a putea verifica rezultatele, se utilizează şi tipul complex predefinit.

26.11.18 88
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
/ / N u m e re c o m p l e x e : T C
#include <iostream.h> #include <conio.h> #include <math.h>

#include <complex.h>
// class C;
class T { float Ro, Fi; // forma polara
public: T (float Modul=0, float Arg=0);
// T (C w); // Conversie C->T
float Re ();
float Im ();
void Tip (const char* Mesaj);
};
class C { float Re, Im; // forma algebrica
public: C (float a=0, float b=0);
C (T z); // Conversie prin constructor C<-T
float Modul ();
float Arg ();
void Tip (const char* Mesaj);
};
C::C ( float a, float b ) { Re=a; Im=b; }
C::C (T z) { Re=z.Re(); Im=z.Im(); } // Conversie prin constructor C<-T
float C::Modul( ) { return sqrt(Re*Re+Im*Im); }
float C::Arg ( ) { return atan2 (Im,Re); }
float C::Arg ( ) { return atan2 (Im,Re); }
void C::Tip ( const char* Mesaj)
{ cout << Mesaj << Re << "+" << Im << "i" << endl; }

T::T ( float Modul, float Arg) { Ro=Modul; Fi=Arg; }


// T::T (C w) { Ro=w.Modul(); Fi=w.Arg(); } // Conversie C->T
float T::Re ( ) { return Ro*cos(Fi); }
float T::Im ( ) { return Ro*sin(Fi); }
void T::Tip(const char* Mesaj)
{ cout << Mesaj << Ro << "," << Fi << ";" << endl; }
void main ()
{ clrscr();
T y(2,3); y.Tip(" (r,u) = ");
C x;
x=y; x.Tip(" (a,b) = ");
complex z(y.Re(),y.Im());
cout << " z = " << z << endl;
cout << " (x,y) = " << real(z) << "+" << imag(z) << "i" << endl;
cout << " (x,y) = " << sqrt(norm(z)) << "," << arg(z) << ";" << endl;
getch();
} // R e z u l t a t e :
(r,u)=2,3;
(a,b)= -1.979985+0.28224i
z =(-1.979985,0.28224)
(x,y)= -1.979985+0.28224i
(r,u)=2,3;

26.11.18 89
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
23.2. Conversii explicite

23.2.1. Conversia dintr-un tip abstract într-un tip predefinit


Conversia dintr-un tip abstract de dată într-un tip predefinit se poate realiza prin
supraîncărcarea operatorului de conversie explicită corespunzător, printr-o funcţie
membru definită astfel:
class Clasă { ...
public: ...
operator Tip_Predefinit ( );
...
};
Clasă :: operator Tip_Predefinit ( )
{ ...
return Expresie_de_Tip_Predefinit;
}

În exemplul următor se va realiza o conversie dintr-un număr raţional într-un număr


real:
/ / C o n v e r s i e Ta d - Q  d o u b l e
#include <string.h>; #include <iostream.h>; #include <conio.h>;
class Q { long m; long n; // m / n
public: Q (long, long); // constr. implicit
operator double(); // Q  double
Q operator *(Q); // inmultire
void Tip (const char* Mes); // tiparire
};
inline Q::Q(long p, long q) { m=p; n=q; }
inline Q::operator double () { return double(m) / n; }
inline Q Q::operator * (Q r) { return Q(m*r.m, n*r.n); }
inline void Q::Tip(const char* Mes) {cout << Mes << m << "/" << n << endl;}
void main ()
{ clrscr();
Q x(2,5); Q y(3,7);
Q z=x*y; z.Tip(" z = ");
double a, b;
a=x*4.5; cout << " a = " << a << endl;
b=4.5*x; cout << " b = " << b << endl; getch();

} // R e z u l t a t e :
z = 6/35
a = 1.8
b = 1.8

26.11.18 90
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
23.2.2. Conversia dintr-un tip abstract într-un alt tip abstract (prin operatori)
Acest tip de conversie se poate realiza şi prin oparatori (dar nu simultan şi prin
constructori). În programul următor este realizată conversia (prin operatorul de
conversie) din trigonometrică (clasa T) în forma algebrică (clasa C):
/ / N u m e re c o m p l e x e : T C
#include <iostream.h> #include <conio.h> #include <math.h>

#include <complex.h>
class C { float Re, Im; // forma algebrică
public: C (float a=0, float b=0);
float Modul ();
float Arg ();
void Tip (const char* Mesaj);
};
C::C ( float a, float b ) { Re=a; Im=b; }
float C::Modul( ) { return sqrt(Re*Re+Im*Im); }
float C::Arg ( ) { return atan2 (Im,Re); }
void C::Tip ( const char* Mesaj)
{ cout << Mesaj << Re << "+" << Im << "i" << endl; }

class T { floatRo, Fi; // forma polară


public: T (float Modul=0, float Arg=0);
operator C (); // Operatorul de conversie
float Re ();
float Im ();
void Tip (const char* Mesaj);
};
T::T ( float Modul, float Arg) { Ro=Modul; Fi=Arg; }
T::operator C() { return C(Re(),Im()); } // Op. Conv.
float T::Re ( ) { return Ro*cos(Fi); }
float T::Im ( ) { return Ro*sin(Fi); }
void T::Tip (const char* Mesaj)
{ cout << Mesaj << Ro << "," << Fi << ";" << endl; }
void main ()
{ clrscr();
T y(2,3); y.Tip("(r,u)=");
C x;
x=y; x.Tip("(a,b)=");
complex z(y.Re(),y.Im());
cout << " z =" << z << endl;
cout << "(x,y)=" << real(z) << "+" << imag(z) << "i" << endl;
cout << "(r,u)=" << sqrt(norm(z)) << "," << arg(z) << ";" << endl; getch();
} // R e z u l t a t e :
(r,u)=2,3;
(a,b)= -1.979985+0.28224i
z =(-1.979985,0.28224)
(x,y)= -1.979985+0.28224i
(r,u)=2,3;

26.11.18 91
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
24. Clase Şablon (Template)

Clasele Template (parametrizate sau generice) permit descrierea unor categorii de


clase, care diferă prin tipul unor atribute, acesta fiind descris generic (nu este precizat la
descrierea clasei ci doar la instanţierea obiectelor). O astfel de clasă abstractă va fi
particularizată într-o clasă concretă înlocuind tipul general cu un anumit tip ales.

24.1. Funcţii Şablon (Template)


Funcţiile Template (generice) conţin şi parametri formali generici care vor fi
înlocuiţi cu parametri de un anumit tip concret.

Exemplu:
// Funcţii T e m p l a t e (1) \\
#include <iostream.h>
#include <conio.h>
template <class T>
T Max (T x, T y) { return (x>y)? x : y; }
void main ()
{ clrscr();
int a,b;
cout << " Dati a,b : "; cin >> a >> b;
cout << " Maximul = " << Max(a,b) << endl;
float x,y;
cout << " Dati x,y : "; cin >> x >> y;
cout << " Maximul = " << Max(x,y) << endl;
getche();
} //N&d-Eusorsăgreşeşti!

Se observă că putem folosi ca parametri actuali parametri de diverse tipuri, pentru


care însă este definit operatorul > . Dacă acest operator nu este definit pentru un tip de
dată cu care dorim să lucrăm, sau nu corespunde cerinţelor noastre, acesta va trebui
redefinit sau chiar funcţia va fi rescrisă conform cerinţelor.
Exemplu:
// Funcţii T e m p l a t e (2) \\
#include <iostream.h> #include <string.h>
#include <conio.h>

template <class T>


T Max (T x, T y) { return (x>y)? x : y; }
char* Max(char* x, char* y) { return (strcmp(x,y)>0) ? x : y; }
void main ()
{ char* a=new char[10]; clrscr();
char* b=new char[10];
cout << " Dati a,b : "; cin >> a >> b;
cout << " Maximul = " << Max(a,b) << endl; getche();
}

26.11.18 92
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
24.2. Clase Template
O clasă Template este un model (şablon) din care se vor genera diverse clase
concrete prin particularizarea atributelor cu tip ambiguu (generic). O astfel de categorie de
clase care diferă prin tipurile atributelor sunt specificate printr-o clasă template pentru ca
apoi să fie generate diverse clase specifice corespunzătoare anumitor tipuri necesare
aplicaţiei.

Exemplu:
// Clase T e m p l a t e \\
#include <iostream.h>
#include <conio.h>
template <class T>
class Vect { T* X;
int Dim;
public: Vect (int n) { X = new T [Dim=n]; }
~Vect ( ) { delete [ ] X; }
void CitV ( );
T MaxV ( );
};
template <class T>
void Vect<T>::CitV ()
{
for (int i=0; i<Dim; i++) cin >> X[i];
}
template <class T>
T Vect<T>::MaxV ()
{ T max=X[0];
for (int i=1; i<Dim; i++)
if (X[i]>max) max=X[i];
return max;
}
void main ()
{ clrscr();
int m;
cout << " Dati nr.el. X : "; cin >> m;
Vect<int> X(m);
cout << " Dati elem. X : "; X.CitV();
cout << " Maximul este " << X.MaxV() << endl;
int n;
cout << " Dati nr.el. Y : "; cin >> n;
Vect<float> Y(n);
cout << " Dati elem. Y : "; Y.CitV();
cout << " Maximul este " << Y.MaxV() << endl; getche();
}

Se observă că în exemplul anterior s-au utilizat nu numai clase template ci şi funcţii


membru template.
Argumentele pot fi tipuri de date (class Nume_Tip) sau constante (Tip
Nume_Parametru), de exemplu:

template <class T, int Dim>

26.11.18 93
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
24.3. Implementarea elementelor Template
În cele ce urmează ne vom referi la poziţia codului (care se expandează conform
cerinţelor utilizatorului) corespunzător obiectelor template. Codul template (corpul
funcţiilor membru) trebuie să fie vizibil acolo unde sunt utilizate elemente template.
Există două metode (posibilităţi) de implementare:
a) template smart – tot codul unei clase template este scris în fişierul header (definiţii de
clase, funcţii precum şi implementarea funcţiilor), acest mod putând fi precizat fie prin
opţiunea de compilare –Jg, fie prin meniul Options , Compiler , C ++ options ,
opţiunea Template Generation : Smart , programul urmând să includă acest fişier cu
toate descrierile.
b) template manual – doar declaraţiile elementelor template sunt scrise în fişierul header
iar implemetarea făcându-se separat, în alt fişier. Acest mod trebuie precizat prin
directiva #pragma option, utilizând opţiunea de compilare –Jgd (urmează o definire
publică a instanţierilor unor elemente template) şi opţiunea –Jgx (urmează o declaraţie
externă a instanţierilor template). Acest mod este ilustrat în următorul exemplu simplu:
// Program Template ... Manual \\
#include <conio.h> #include <iostream.h>
# include "C_Templ4.h"
# pragma option -Jgx
void main ()
{ clrscr();
Vint10 X; X.CitV("X"); cout << " Maximul este " << X.MaxV( ) << endl;
Vflo13 Y; Y.CitV("Y"); cout << " Maximul este " << Y.MaxV( ) << endl; getche();
}

// Cpp Template ... Manual \\


#include <conio.h> #include <iostream.h>
#include "C_Templ4.h"
template <class T, int Dim>
void Vect<T,Dim>::CitV (char *Mes)
{ cout << " Dati nr. elem.: "; cin >> n;
cout << " Dati elem." << Mes << " : ";
for (int i=0; i<n; i++) cin >> X[i];
}
template <class T, int Dim>
T Vect<T,Dim>::MaxV ()
{ T max=X[0];
for (int i=1; i<n; i++) if (X[i]>max) max=X[i]; return max;
}

// Header Template ... Manual \\


template <class T, int Dim>
class Vect { T X[Dim];
int n;
public: void CitV (char*);
T MaxV ( ); };
# pragma option –Jgd
typedef Vect<int, 10> Vint10;
typedef Vect<float,10> Vflo13;

26.11.18 94
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
25. Relaţii între clase

La elaborarea modelului obiectual al unei aplicaţii se disting următoarele două


etape:
a) identificarea claselor – corespunzătoare conceptelor aplicaţiei (substantivele),
b) stabilirea relaţiilor dintre clase – corespunzătoare specificaţiilor aplicaţiei (verbele).

În cele ce urmează ne vom referi la următoarele tipuri de relaţii între clase:


1) Asociaţie – relaţie de cooperare între clase – corespunzătoare unui verb oarecare din
specificaţie, diferită de relaţia parte-întreg (de exemplu relaţia Student – Facultate).
Relaţia corespunzătoare dintre obiecte aparţinând unor clase asociate se numeşte
legătură. O asociaţie poate fi simplă sau multiplă (dacă un obiect asociant este pus în
legătură, de exemplu prin pointeri, cu mai multe obiecte asociate, de acelaşi tip).
Această relaţie se reprezintă grafic (după metodologia OMT) în plan orizontal astfel:

simplă multiplă k
C1 C2 C1 C2

2) Agregare – relaţie de asociaţie prin care obiectul agregat este inclus în obiectul
agregant (verbul caracteristic este a avea), şi evident că poate fi simplă sau multiplă:

simplă multiplă k
C1 C2 C1 C2

3) Specializare (generalizare, moştenire) – relaţie prin care sunt păstrate (moştenite)


caracteristicile unei clase (de bază) şi sunt adăugate diferenţele specifice, formând o
nouă clasă (derivată). Moştenirea permite reutilizarea de cod definit în clasa de bază
(superclasă) şi în noua clasă (sublasă). Deci, o subclasă este o specializare a unei
superclase (verbul caracteristic fiind a fi), iar o superclasă este o generalizare a unei
subclase. Această relaţie este tranzitivă, iar structura formată de mulţimea claselor
aflate în această relaţie (construită pe verticală) se numeşte ierarhie de clase. Atât
specializarea cât şi moştenirea poate fi simplă sau multiplă, reprezentarea făcându-se în
plan vertical astfel:

C1 C1 C1 C2

C2 C2 C3 C3

Specializare Specializare Moştenire


simplă multiplă multiplă
Se pot obţine în felul acesta şi ierarhii spaţiale de clase, având relaţii atât pe
orizontală cât şi pe verticală.

26.11.18 95
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
25.1. Relaţia de Asociaţie

Prin această relaţie dintre clase se


modelează o legătură între obiectele instanţiate

instanţiere
C1 asociaţie C2
(care depind unul de celălalt). Traversarea unei C1 C2
rol1 rol2
asociaţii se face printr-un rol (nume dat
extremitatăţii unei asociaţii). Implementarea unei

instanţiere
asociaţii se poate realiza astfel:
a) printr-un pointer – clasa asociantă conţine
un atribut de tip pointer spre clasa asociată,
b) printr-o clasă – cu atribute şi comportare legătură
proprie, fiecare legătură fiind o instanţă a O1 O2
acestei clase.
Asociaţiile pot fi unidirecţionale sau bidirecţionale, iar relaţiile de asociaţie pot fi
binare, ternare sau n-are. Pe de altă parte, asociaţiile pot fi simple sau multiplicative
(acestea din urmă putând fi eventual şi cu restricţii de ordonare sau de calificare).
Asociaţiile multiplicative sunt caracterizate prin numărul de instanţe ale claselor
care se află în asociaţie, iar pentru a reprezenta direcţia de asociaţie se pot utiliza săgeţi.
O asociaţie multiplicativă poate să fie
asociaţia {ordonata}
neordonată (instanţele formează o mulţime), sau C1 C2
poate să fie ordonată (instanţele formează o listă
ordonată).
O relaţie multiplicativă cu restricţie de
calificare pune în relaţie două clase printr-un
asociaţia
calificant (atribut care reduce multiplicitatea C1 calificant C2
asociaţiei printr-un criteriu pe care trebuie să-l
îndeplinească obiectele asociate pentru a intra în
relaţie).
La implementarea relaţiilor de asociaţie putem aplica cele două metode amintite
anterior:
a) prin pointeri spre clasa asociată încuibăriţi în clasa asociantă în funcţie de tipul relaţiei
de asociere astfel:
– pentru relaţia de asociaţie simplă se adaugă clasei asociante încă un atribut de tip
pointer spre clasa asociată, împreună cu relaxarea încapsulării pentru traversarea
asociaţiei alegând o metodă convenabilă dintre următoarele variante:
 modificarea protecţiei datelor membru implicate în public,
 utilizarea de metode sau clase friend,
 extinderea interfeţei prin metode de acces la componente.

– pentru relaţia de asociaţie multiplă se adaugă clasei asociante mai multe atribute de tip
pointer în funcţie de tipul asociaţiei şi ordinul de multiplicitate astfel:
 dacă este relativ mic, se vor adăuga pointeri distincţi,
 iar în caz contrar se poate utiliza un şir de pointeri;
 dacă relaţia este supusă unor restricţii de ordonare, se pot utiliza liste ordonate.

26.11.18 96
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
b) prin clase distincte care realizează
abstractizarea asociaţiilor dacă legăturile au
m n
proprietăţi şi operaţii proprii (nemaifiind C1 C2
necesară adăugarea de atribute claselor care se
asociază), această metodă utilizându-se în Cas.
special în cazul asociaţiilor bidirecţionale de tip
m-n), sau o legătură poate conecta obiecte de
clase diferite.

Exemplu:
// Clase asociate \\
#include <conio.h>
#include <iostream.h>
#include "VectCaut.h"
void main (void)
{ int n; clrscr();
cout << " Dati n : "; cin >> n;
VectSort X(n); // X.Sort ();
VectCaut x(&X); X.Print();
int a,p;
do { cout << " Dati a : "; cin >> a;
if (p=x.CautSec(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a);
cout << " Dati m : "; cin >> n;
VectSort* Y=new VectSort(n); Y->Sort();
VectCaut* y=new VectCaut(Y); Y->Print();
do { cout << " Dati b : "; cin >> a;
if (p=y->CautBin(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a); getche();
}

// Clasă asociantă \\ << VectCaut.h >>


#include "VectSort.h"
class VectCaut { VectSort *v;
public: VectCaut (VectSort*);
int CautSec (int a);
int CautBin (int a);
};

// Clasă asociată \\ << VectSort.h >>

class VectSort { int *v, n;


public: VectSort (int = 10);
void Sort ( );
void Print( );
int* Adr ( );
int Dim ( );
~ VectSort ( );
};

26.11.18 97
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Clasă asociantă \\ << VectCaut.Cpp >>
# include "VectCaut.h"
VectCaut::VectCaut (VectSort *p)
{
v = p;
}
int VectCaut::CautSec(int a)
{ int i=1, n=v->Dim(), *x=v->Adr();
while ((i<=n) && (x[i]-a)) i++;
return i%(n+1);
}
int VectCaut::CautBin(int a)
{ int St=1, Dr=v->Dim(), *x=v->Adr();
while (St<=Dr) { int m=(St+Dr)/2;
if (x[m]-a) if (x[m]<a) St=m+1; else Dr=m-1;
else return m; }
return 0;
}

// Clasă asociată \\ << VectSort.Cpp >>


# include <iostream.h>
# include "VectSort.h"
VectSort::VectSort (int k)
{
n = k; v = new int[k+1];
for (int i=1; i<=n; i++) cin >> v[i];
}
void VectSort::Sort( )
{ int k=1; enum {Nu,Da} Sortat;
do { Sortat=Da;
for (int i=1; i<=n-k; i++)
if (v[i]>v[i+1]) { int Temp=v[i]; v[i]=v[i+1];
v[i+1]=Temp; Sortat=Nu;
} k++; }
while (!Sortat);
}
void VectSort::Print ( )
{
for (int i=1; i<=n; i++) cout << v[i] << ','; cout << endl;
}
int* VectSort::Adr ( )
{
return v;
}

int VectSort::Dim ( )
{
return n;
}
VectSort::~VectSort ( )
{
delete []v;
}

26.11.18 98
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
25.2. Relaţia de Agregare

Relaţia de agregare este cea mai puternică


relaţie de asociaţie, în care o clasă este o

instanţiere
componentă a altei clase, deci relaţia este binară, C1 Conţine C2
C1 C2
unidirecţională, iar relaţiile multiplicative sunt de
tip 1-n. Prin această relaţie dintre clase, un obiect

instanţiere
al clasei agregate este parte constituentă, atribut,
al clasei agregante, deci verbul caracteristic este a
avea (conţine). Obiectele constituente pot fi
independente sau doar componente ale obiectului
conţine
care le include. O1 O2

Această relaţie (notată cu simbolul  având semnificaţia conţine) are următoarele


două proprietăţi de bază:
a) tanzitivitate : Dacă Cx  Cy şi Cy  Cz, atunci Cx  Cz ,
b) antisimetrie : Dacă Cx  Cy atunci Cy  / Cx .

Relaţia de agregare poate fi:


a) fixă – numărul şi tipul componentelor sunt fixe,
b) variabilă – permite un număr variabil de obiecte de acelaşi tip,
c) recursivă – acceptă acelaşi tip ca tip agregat şi agregant.

Exemplu:
// Relaţia de agregare \\
#include <conio.h>
#include <iostream.h>
#include "Vect_Agr.h"
void main (void)
{ int n; clrscr();
cout << " Dati n : "; cin >> n;
VectCaut X(n); X.Print();
int a,p;
do { cout << " Dati a : "; cin >> a;
if (p=X.CautSec(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a);
cout << " Dati m : "; cin >> n;
VectCaut* Y=new VectCaut(n); Y->Sort(); Y->Print();
do { cout << " Dati b : "; cin >> a;
if (p=Y->CautBin(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a); getche();
}

26.11.18 99
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Clasă Agregantă \\ << Vect_Agr.h >>
#include "VectSort.h"
class VectCaut { VectSort V;
public: VectCaut (int=10);
void Sort ();
void Print();
int CautSec (int);
int CautBin (int);
};

// Clasă Agregantă \\ << Vect_Agr.Cpp >>


# include "Vect_Agr.h"
VectCaut::VectCaut (int n) : V(n)
{
}
void VectCaut::Sort ()
{
V.Sort();
}
void VectCaut::Print ()
{
V.Print();
}
int VectCaut::CautSec(int a)
{ int i=1, n=V.Dim(), *x=V.Adr();
while ((i<=n) && (x[i]-a)) i++;
return i%(n+1);
}
int VectCaut::CautBin(int a)
{ int St=1, Dr=V.Dim(), *x=V.Adr();
while (St<=Dr) { int m=(St+Dr)/2;
if (x[m]-a) if (x[m]<a) St=m+1; else Dr=m-1;
else return m; }
return 0;
}

// Clasă Agregată \\ << VectSort.h >>


class VectSort { int *v, n; // A fost descrisă la clase asociate. \\
public: VectSort (int = 10);
void Sort ( );
void Print( );
int* Adr ( );
int Dim ( );
~ VectSort ( );
};

// Clasă Agregată \\ << VectSort.Cpp >>


# include <iostream.h>
# include "VectSort.h"
… // A fost deja descrisă la clase asociate. \\

26.11.18 100
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În următorul exemplu se va folosi o clasă Iterator pentru listă simplu înlănţuită care
utilizează clasa Elem pentru un nod al listei şi clasa Lista:

// Iterator Listă \\
#include <conio.h>
#include <iostream.h>

# define Tel int

class Elem { Tel Inf;


Elem* Leg;
public: Elem (Tel inf, Elem* leg=0) { Inf=inf; Leg=leg; }
friend class Lista;
friend class Iterator;
};

class Lista { Elem* Cap;


public: Lista ( ) { Cap=0; }
void Ad (Tel);
friend class Iterator;
};

void Lista::Ad (Tel elem)


{ if (Cap) { Elem* p=Cap; while (p->Leg) p=p->Leg; p->Leg=new Elem(elem,0);}
else Cap=new Elem(elem,0);
}

class Iterator { Elem* p;


public:
Iterator(Lista& L) { p = L.Cap; }
Tel operator () ( ) { return p->Inf; } // elementul curent
void operator ++ ( ) { p = p->Leg; } // avanseaza in lista
int operator ! ( ) { return p!=0; } // exista element
};

void main (void)


{ clrscr();
Lista L; L.Ad (11); L.Ad (22); L.Ad (33);
Iterator l(L);
while (!l)
{
cout << l() <<" "; l++;
}
getche();
}

26.11.18 101
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
25.3. Clase Încuibate(imbricate)

Există posibilitatea definirii unei clase (încuibate) în interiorul altei clase (ca şi
atribut al cesteia). Această posibilitate există de fapt şi la structuri (struct) şi uniuni (union).
Declararea obiectelor din clasa încuibată se poate realiza utilizând operatorul de
scop (::) aşa cum se poate vedea în exemplul următor:
// C l as e Im bri ca t e \\
class Cerc { // Cerc(x,y,r)
float r; // Raza
class Punct { // Punct(x,y) Centrul
float x,y; /*
... */
}; /*
... */
};

void main ()
{
Cerc C;
Cerc::Punct P;
// ...
}

Utilizarea obiectelor din clasa încuibată se poate realiza utilizând operatorul de


apartenenţă (.) după cum se vede în următorul exemplul:

// C l as e In cu i b at e \\
#include <conio.h>
#include <iostream.h>
class Cerc { // Cerc(x,y,r)
float r;
class Punct { // Punct(x,y)
float x,y;
public: Punct (float x0=0, float y0=0) { x=x0; y=y0; }
void Print () { cout <<' '<< x <<' '<< y <<' '; }
};
Punct Centru;
public: Cerc (Punct P, float raza) { Centru=P; r=raza; }
void Print() { Centru.Print(); cout << r; }
};

void main ()
{ clrscr();
Cerc::Punct O(1,2); O.Print(); cout << endl;
Cerc C(O,3); C.Print(); cout << endl;
getch();
}

26.11.18 102
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Evident că din clasa încuibată (Punct) nu avem acces la elementele clasei din care
face parte (Cerc). Dacă se doreşte acest lucru, atunci se poate proceda ca şi în următorul
exemplu:

// C l as e In cu i b at e \\
#include <conio.h>
#include <iostream.h>
class Cerc { // Cerc(x,y,r)
float r;
public: Cerc (float raza) { r=raza; }
class Punct;
friend Punct;
class Punct { // Punct(x,y)
float x,y;
public: Punct (float x0, float y0) { x=x0; y=y0; }
void Print (Cerc c){cout <<' '<<x<<' '<<y<<'
'<<c.r;}
}; };

// void Cerc::Punct::Print (Cerc c) { cout <<' '<<x<<' '<<y<<' '<<c.r; }

void main ()
{ clrscr();
Cerc c(3);
Cerc::Punct O(1,2); O.Print(c);
getch();
}

Se poate observa în exemplul dat că referirea atributului r al clasei Cerc nu este


permisă din interiorul clasei încuibate (vezi funcţia Print descrisă în ambele variante), motiv
pentru care clasa Punct a fost declarată prietenă.
În următorul exemplu sunt imbricate clasele R  R2  R3 :
// C l as e In cu i b at e \\
#include <conio.h>
#include <iostream.h>
class R {
double x;
public: R (double x) { this->x=x; }
class R2; friend R2;
class R2 {
double y;
public: R2 (double y) { this->y=y; }
class R3; friend R3;
class R3 {
double z;
public: R3 (double z) { this->z=z; }
void Print (R,R2);
};
void Print (R);
}; };
void R::R2::Print (R a) {cout <<' '<<a.x;}
void R::R2::R3::Print (R a, R2 b) {b.Print(a); cout <<' '<<b.y<<' '<<z;}
void main ()
{ clrscr();
R OX (1);
R::R2 XOY(2);
R::R2::R3 XYZ(3); XYZ.Print(OX,XOY);
getch();
}

26.11.18 103
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
25.4. Relaţia de derivare

Prin această relaţie putem modela similitudinile dintre clase două sau mai multe
clase. Pornind de la o clasă de bază (generală) se pot deriva noi clase (prin diferenţele
specifice). Obiectele clasei derivate moştenesc atributele şi metodele clasei de bază la care
se vor adăuga noile elemente caracteristice (vor fi umflate), ceea ce permite reutilizarea
resurselor deja pregătite în clasele de bază (pentru obiectele similare). Verbul caracteristic
al acestei relaţii de specializare este a fi ( … este un fel de … <a kind of>).
Moştenirea permite păstrarea elementelor (date şi
funcţii ale) unei clase de bază (superclasă), cu definirea de
noi elemente construind o nouă clasă derivată (subclasă),

este un …
formând în felul acesta ierarhii de clase. Moştenirea poate fi Ob
şi multiplă dacă o clasă moşteneşte mai multe clase.
Deoarece această relaţie este tranzitivă se utilizează şi

este o …
Cb
termenii de strămoş şi descendent.
generalizare

Od

C1 C1 C1 C2
specializare

Cd
C2 C2 C3 C3

Specializare Specializare Moştenire


simplă multiplă multiplă
25.4.1. Clase derivate
Relaţia de derivare se poate descrie prin construcţii speciale fără a mai fi nevoie de o
relaxare a încapsulării, aşa cum a fost necesară la relaţiile prezentate anterior. Dacă într-o
aplicaţie se poate utiliza relaţia de derivare, este de preferat în locul asociaţiei sau agregării
pentru că avem instrumente specializate în limbajul de programare.
O clasă derivată se declară astfel:
class Clasă_Derivată : Listă_clase_de_bază
{
Date şi Funcţii membru noi
};

26.11.18 104
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Lista claselor de bază poate să conţină şi modificatorii de protecţie (Mod_Pr)
public, protected sau private, deci o derivare poate să fie publică, protejată sau privată,
accesul rezultat fiind redat în următoarele tabele.
d\b#+
Accesul în clasa de bazăMod_PrAccesul în clasa
derivatăprivate*Privateprivateprotected sau
publicProtectedprotectedPublicneschimbat (protected sau public) +#+###

De exemplu, dacă cele două


clase sunt descrise astfel: a b c
Cl_Bază
class Cl_Bază public:
{
private: …a… x by cz
Cl_Derivată
protected: …b…
public: …c…
};
a b c
Cl_Bază
class Cl_Derivată : Mod_Pr Cl_Bază
protected:
{
private: …a… x bcy z
Cl_Derivată
protected: …b…
public: …c…
};
a b c
Cl_Bază
atunci protecţia membrilor din
clasa derivată este redată în schema private:
alăturată. Cl_Derivată
bcx y z
Ordinea de executare a constructorilor la instanţierea obiectelor dintr-o clasă
derivată:
prima dată se execută constructorul clasei de bază, apoi constructorul clasei derivate (se
construişte cadrul, apoi se adaugă diferenţele specifice).
Ordinea de executare a destructorilor la distrugerea obiectelor dintr-o clasă
derivată:
prima dată se execută destructorul clasei derivate, apoi destructorul clasei de bază.
Constructorul clasei derivate transmite parametrii necesari constructorului clasei de
bază prin apelul direct al acestuia astfel:
Clasă_Derivată ( … ) : Clasă_de_bază ( … ) { … }; // inline
sau
Clasă_Derivată :: Clasă_Derivată ( … ) : Clasă_de_bază ( … ) { … }; //inline

26.11.18 105
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Deoarece relaţia de derivare este poate cea mai importantă relaţie dintre clase, sunt
oferite facilităţi de implementare, care permit următoarele facilităţi:
 economia de cod – reutilizarea codului scris o singură dată după care se moşteneşte,

 extensibilitate – re-specializare prin derivarea de noi ramuri dintr-o ierarhie,

 polimorfism – într-o ierarhie de clase se poate implementa o comportare polimorfică,

 încapsulare–relaxare – relaţia de derivare oferă posibilitatea închiderii resurselor

simultan cu deschiderea spre modificare şi extensie.

Relaţiile de derivare (de fapt şi celelalte relaţii dintre clase) sunt stabilite la
compilare, deci nu se mai pot modifica pe parcursul execuţiei. Mai trebuie cunoscut faptul
că prin derivare nu se pot moşteni constructorii, destructorii, elementele prietene (funcţii,
clase sau metode friend) şi nici operatorii redefiniţi.

Exemplu:
// Relatia de derivare \\
#include <conio.h>
#include <string.h>
#include <iostream.h>
class N {
protected: char* c;
public: N (char* s) { c=new char[strlen(s)+1]; strcpy(c,s); }
~N ( ) { delete [ ] c; }
char* Modul ( ) { return c; }
};

void Print (N n) { cout << n.Modul() << endl; }

class Z : public N
{
private: char Semn;
public: Z (char* s) : N(s+1) { Semn=s[0]; }
~Z ( ) { }
char Semnul( ) { return Semn; }
};

void Print (Z n) { cout << n.Semnul() << n.Modul() << endl; }

void main (void)


{ clrscr();
N n("1234"); Print (n);
Z k("-123"); Print (k);
N* i = new N("567"); Print (*i);
Z* j = new Z("-89"); Print (*j); getche();
}

26.11.18 106
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Conversia unui obiect dintr-o clasă derivată într-un obiect aparţinând clasei de bază
este permisă, invers însă nu (sursa trebuie să acopere destinaţia):
Contra_Exemplu:

// Conversii la derivare ? \\

void main (void)
{ clrscr();
N n("1234"); Print (n);
Z k(n); Print (k); Error CONVCDCB.CPP 28: Could not find a match for 'Z::Z(N)'
N* i = new N(k); Print (*i);
Z* j = new Z(i); Print (*j); Error CONVCDCB.CPP 30: Could not find a match for 'Z::Z(N *)'
} getche();

Pentru o funcţie care are ca parametru formal un obiect al clasei de bază este permis
apelul având ca parametru un obiect al clasei derivate, invers nu (o funcţie care are ca
parametru formal un obiect al clasei derivate, nu poate fi apelată având ca parametru actual
un obiect al clasei de bază).
Exemplu:
// Conversie la derivare \\
#include <conio.h>
#include <string.h>
#include <iostream.h>
class N {
protected: char* c;
public: N ( ) { c=new char[2]; c[0]='0'; c[1]=0; }
N (char* s) { c=new char[strlen(s)+1]; strcpy(c,s); }
N (N& n) { c=new char[strlen(n.c)+1]; strcpy(c,n.c); }
~N ( ) { delete [ ] c; }
char* Modul ( ) { return c; }
};
void Print (N n) { cout << n.Modul() << endl; }
class Z : public N
{
private: char Semn;
public: Z( ) : N( ) { Semn='+' ; }
Z (char* s) : N(s+1) { Semn=s[0]; }
~Z ( ) { }
char Semnul( ) { return Semn; }
};
void Print (Z n) { cout << n.Semnul() << n.Modul() << endl; }
void WriteAbs (N n) { Print( n); }
void WriteAbs_(N*n) { Print(*n); }
void main (void)
{ clrscr();
Z k("+123"); Print (k);
N n(k); Print (n);
WriteAbs(n);
WriteAbs(k);
Z* p=new Z("-456"); Print (*p);
N* q; q = p; Print (*q);
WriteAbs(*p); WriteAbs_(p);
WriteAbs(*q); WriteAbs_(q); getche();
}

În exemplul următor se porneşte de la clasa de bază VectBaza şi se construieşte clasa


derivată Vect_Der :

26.11.18 107
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Relaţia de derivare \\
#include <conio.h>
#include <iostream.h>
#include "Vect_Der.h"
void main (void)
{ int n; clrscr();
cout << " Dati n : "; cin >> n;
Vect_Der X(n); X.Print();
int a,p;
do { cout << " Dati a : "; cin >> a;
if (p=X.CautSec(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a);
cout << " Dati m : "; cin >> n;
Vect_Der* Y=new Vect_Der(n); Y->Sort(); Y->Print();
do { cout << " Dati b : "; cin >> a;
if (p=Y->CautBin(a)) cout << " Pe poz." << p << endl;
else if(a) cout << " Inexistent! " << endl; }
while (a); getche();
}

// Clasă de bază \\ << VectBaza.h >>


class VectBaza {
protected: int *v, n;
public: VectBaza (int = 10);
void Sort ( );
void Print( );
~ VectBaza ( );
};

// Clasă de bază \\ << VectBaza.Cpp >>


# include <iostream.h>
# include "VectBaza.h"
VectBaza::VectBaza (int k)
{
n = k; v = new int[k+1];
for (int i=1; i<=n; i++) cin >> v[i];
}
void VectBaza::Sort( )
{ int k=1; enum {Nu,Da} Sortat;
do { Sortat=Da;
for (int i=1; i<=n-k; i++)
if (v[i]>v[i+1]) { int Temp=v[i]; v[i]=v[i+1];
v[i+1]=Temp; Sortat=Nu;
} k++; }
while (!Sortat);
}
void VectBaza::Print ( )
{
for (int i=1; i<=n; i++) cout << v[i] << ','; cout << endl;
}
VectBaza::~VectBaza ( )
{
delete []v;
}

26.11.18 108
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Clasă Derivată \\ << Vect_Der.h >>
#include "VectBaza.h"
class Vect_Der : public VectBaza {
public: Vect_Der (int=10);
int CautSec (int);
int CautBin (int);
};

// Clasă Derivată \\ << Vect_Der.Cpp >>


# include "Vect_Der.h"
Vect_Der::Vect_Der (int n) : VectBaza(n) { }
int Vect_Der::CautSec(int a)
{ int i=1; while ((i<=n) && (v[i]-a)) i++; return i%(n+1); }
int Vect_Der::CautBin(int a)
{ int St=1, Dr=n;
while (St<=Dr) { int m=(St+Dr)/2;
if (v[m]-a) if (v[m]<a) St=m+1; else Dr=m-1;
else return m; }
return 0;
}

În exemplul care urmează, datele x,y (din clasa de bază Punct) au fost declarate
protected deoarece clasa derivată (Cerc) le referă. La clasa derivată am utilizat
modificatorul public pentru a putea utiliza şi pentru Cerc operaţia Contine (PC).

// Program Fct_NeVirtuala; \\
#include <stdio.h>; #include <conio.h>; #include <iostream.h>; #include <math.h>;
float Sqr (float x) { return x*x; }
class Punct {
protected:
float x,y;
public:
Punct (float x0=0, float y0=0);
float Dist (Punct P);
int Contine(Punct P);
};
Punct::Punct (float x0, float y0) { x=x0; y=y0; }
float Punct::Dist (Punct P) {return sqrt(Sqr(x-P.x)+Sqr(y-P.y)); }
int Punct::Contine(Punct P) {return Dist(P)==0; }
class Cerc : public Punct
{ float r;
public:
Cerc (float x0=0, float y0=0, float raza=0)
{x=x0; y=y0; r=raza;}
float Dist (Punct P)
{Punct C(x,y); return C.Dist(P)-r; }
};
void main (void)
{ Punct P(3,4); Cerc C(0,0,5);
if (C.Contine(P)) cout << " Cercul C contine punctul P." << endl;
else cout << " Cercul C nu contine punctul P." << endl; getch();
} // R e z u l t a t e :
Cercul C nu contine punctul P.

Se observă în exemplul de mai sus că rezultatul nu este cel dorit. Acest neajuns îl
vom rezolva mai târziu declarând Distanţa ca funcţie virtuală (pentru legare dinamică).

26.11.18 109
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Faţă de moştenirea simplă, în care dintr-
Cb Cb1 Cb2
o singură clasă de bază se derivează una sau
mai multe clase derivate (specializate),
moştenirea multiplă presupune existenţa mai Cd1 Cd2 Cd
multor clase de bază din care un sau mai multe
clase moştenesc diverse caracteristici. Moştenire simplă Moştenire multiplă

Declararea unei clase derivate din mai multe clase de bază se face astfel:
class Clasă_de_bază_1 { … };
class Clasă_de_bază_2 { … };
class Clasă__derivată : Mod_Pr Clasă_de_bază_1, Mod_Pr Clasă_de_bază_2
{ … };

unde Mod_Pr  { public, protected, private }.

Datorită moştenirii multiple o clasă de bază poate fi


Animal
prezentă în mai multe exemplare într-o clasă derivată, aşa
cum se poate vedea în exemplul alăturat, unde datele
membru ale clasei Animal vor fi moştenite în două Mamifer Domestic
exemplare de către clasa Câine (unul prin clasa Domestic,
altul prin clasa Mamifer) şi pot fi referite prin operatorul
Câine
de rezoluţie ( :: ) aplicat clasei prin care se face moştenirea
(Nume).

Această moştenire repetitivă a unei clase de bază


este corectă şi se poate utiliza astfel: Cl_Bază Cl_Bază

Cl_Der1 Cl_Der2

Clasă_Derivată

class Cl_Bază { protected: … Atribut … };


class Cl_Der1 : public Cl_Bază { … };
class Cl_Der2 : public Cl_Bază { … };
class Clasă_Derivată : public Cl_Der1, Cl_Der2
{ … Cl_Der1::Atribut … Cl_Der2::Atribut … };

26.11.18 110
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Dacă dorim realizarea unei singure copii a atributelor moştenite, vom folosi
moştenirea multiplă virtuală:
Cl_Bază

Cl_Der1 Cl_Der2

Clasă_Derivată

class Cl_Bază { protected: Atribut … };


class Cl_Der1 : virtual public Cl_Bază { … };
class Cl_Der2 : virtual public Cl_Bază { … };
class Clasă_Derivată : public Cl_Der1, Cl_Der2
{ … Atribut … };

26.11.18 111
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Aşa cum se poate vedea în exemplul următor, vom avea un nume de mamifer şi un
nume domestic.

// P ro g r a m C l a s e N e Vi r t u a l e ; \\
#include <iostream.h>
#include <conio.h>
#include <string.h>
class Animal { protected: char* Nume;
public: Animal (char *nume) { strcpy(Nume,nume); }
};
class Mamifer : public Animal {
protected: int Greu;
public: Mamifer (char* nume,int gr) : Animal(nume) { Greu=gr;}
};
class Domestic: public Animal {
protected: int Pret;
public: Domestic(char* nume,int pr) : Animal(nume) { Pret=pr;}
};
class Caine : public Mamifer, public Domestic {
protected: int Lant;
public: Caine(char* numeM,char* numeD, int gr, int pr, int l) :
Mamifer(numeM,gr), Domestic(numeD,pr) { Lant=l;}
void Tip() { cout << " Nume Mamifer : " << Mamifer::Nume << endl
<< " Nume Domestic: " << Domestic::Nume << endl
<< " Greutate : " << Greu << endl
<< " Pret : " << Pret << endl
<< " Lant : " << Lant << endl ;}

};
void main (void)
{ clrscr();
Caine c ("Cane","Nero",13,1300,8); c.Tip();
getch();
} // Rezultate:
Nume Mamifer : Cane
Nume Domestic: Nero
Greutate : 13
Pret : 1300
Lant : 8

26.11.18 112
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Dacă dorim ca datele membru să fie prezente într-un singur exemplar în clasele
derivate, atunci vom utiliza clase virtuale. O clasă de bază devine virtuală prin moştenire
dacă se declară aceasta prin cuvântul virtual plasat înaintea clasei (devenind astfel clasă
virtuală faţă de clasa derivată).

Programul anterior modificat astfel încât numele să fie memorat într-un singur
exemplar este următorul:

// P ro g r a m C l a s e Vi r t u a l e ; \\
#include <iostream.h>
#include <conio.h>
#include <string.h>
class Animal { protected: char* Nume;
public: Animal (char* nume) { strcpy(Nume,nume); }
};
class Mamifer : virtual public Animal { // Animal este clasă virtuală pentru Mamifer
protected: int Greu;
public: Mamifer (char* nume,int gr) : Animal(nume) { Greu=gr;}
};
class Domestic: virtual public Animal { // Animal este clasă virtuală pentru Domestic
protected: int Pret;
public: Domestic(char* nume,int pr) : Animal(nume) { Pret=pr;}
};
class Caine : public Mamifer, public Domestic {
protected: int Lant;
public: Caine(char* nume, int gr, int pr, int l) :
Animal(nume), Mamifer(nume,gr), Domestic(nume,pr) {Lant=l;}
void Tip() { cout << " Nume Animal : " << Nume << endl
<< " Greutate : " << Greu << endl
<< " Pret : " << Pret << endl
<< " Lant : " << Lant << endl ;}
};
void main (void)
{ clrscr();
Caine c ("Lup",13,1300,8); c.Tip();
getch();

} // Rezultate:
Nume Animal : Lup
Greutate : 13
Pret : 1300
Lant : 8

26.11.18 113
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Pentru o ierarhie ca cea din figura alăturată,
în care avem clase virtuale () şi nevirtuale (), se A
execută mai întâi constructorii claselor de bază
virtuale apoi cei ai claselor nevirtuale, iar
constructorul clasei de bază se va executa pentru o B C D E F
singură dată toate exemplarele virtuale şi câte o dată
pentru fiecare exemplar nevirtual.
G

Exemplul:
// P ro g r a m I e r a r h i e C l a s e Vi r t u a l e / N e v i r t u a l e ; \\

#include <iostream.h>
#include <conio.h>
class A { public: A (char* a) { cout << " A : " << a << endl; }
class B: virtual public A {
public: B (char* b) : A(b) { cout << " B : " << b << endl; }
class C: virtual public A {
public: C (char* c) : A(c) { cout << " C : " << c << endl; }
class D: public A {
public: D (char* d) : A(d) { cout << " D : " << d << endl; }
class E { public: E (char* e) { cout << " E : " << e << endl; }
class F { public: F (char* f) { cout << " F : " << f << endl; }
class G: public B, public C, public D, public E, virtual public F {
public: G (char* g) : A(g), B(g), C(g), D(g), E(g), F(g)
{ cout << " G : " << g << endl; }
void main (void)
{ clrscr();
G Ob("Ob."); getch();

} // Rezultate:
A : Ob.
F : Ob.
B : Ob.
C : Ob.
A : Ob.
D : Ob.
E : Ob.
G : Ob.

26.11.18 114
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
26. Polimorfism

Supraîncărcarea (overloading), prin redefinirea unor funcţii sau metode, permite


alegerea la compilare-link_editare a funcţiei sau a metodei dorite prin semnătura acesteia,
fără a mai putea alege la execuţie.

Polimorfismul permite ca la execuţie să se decidă ce metodă să fie apelată, oferind


o facilitate a metodelor din clase aflate în relaţie de derivare. Prin polimorfism se execută
acţiuni diferite prin mesaje cu semnături identice asupra obiectelor de tip diferit (obiecte din
clase diferite răspund diferit la acelaşi mesaj).

Două obiecte sunt compatibile dacă aparţin aceleaşi clase (evident) dar şi două
variabile
a) de tip pointer la clasa de bază, respectiv pointer la clasa derivată,
b) de tip referinţă (pointer constant) la clasa de bază, respectiv referinţă la clasa derivată .

Metodele unei clase pot fi:


 Clasice – metode legate static, la compilare-link_editare fiind fixată adresa de apel a
metodei, fără posibilitatea de a o schimba la rularea aplicaţiei,
 Polimorifice – metode legate dinamic, care permit întârzierea deciziei referitoare la adresa
de apel a metodei, până la execuţie.

Legarea unei metode (binding), înţelegând prin aceasta cenexiunea logică dintre o
entitate şi o proprietate a acesteia (corespondenţa dintre un mesaj trimis unui obiect, adică
ordinul de apel, şi metoda care se execută ca răspuns la acesta) poate fi:
 Timpurie (statică – early-binding) – compilatorul şi editorul de legături vor fixa adresa
metodei care se execută, fără ca aceasta să mai
poată fi modificată pe parcursul execuţiei;
 Târzie (dinamică – late-binding) – compilatorul va construi un tablou de adrese ale
metodelor posibile de apel, iar determinarea
adresei metodei dorite se va efectua doar la
execuţie. În funcţie valoarea pointerului spre
clasa de bază, care poate conţine şi adresa unui
obiect al clasei derivate, se va alege metoda
corespunzătoare.

26.11.18 115
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
26.1. Funcţii membru Vi rt u al e
Implicit, o metodă este legată static (early, la compilare), iar dacă se doreşte o
legare dinamică (late, la execuţie) se va declara virtuală prin scrierea cuvântului virtual
înaintea metodei. O metodă virtuală a unei clase de bază, poate fi moştenită într-o clasă
derivată sau poate fi redefinită (înlocuită - overriding). O metodă se declară vituală în
clasa de bază (nu se poate declara virtuală doar într-o clasă derivată.
Se poate observa în exemplul următor că dacă dorim ca rezultatul să fie
“Baza/Derivata” şi la apelul funcţiei g, trebuie să declarăm funcţia f virtuală, altfel
rezultatul ar fi “Baza/Baza”.
// Met od ă vi r t u al ă \\
# include <conio.h>
# include <iostream.h>
class Cb { public:
virtual void f() { cout << " Baza " << endl; }
};
class Cd : public Cb
{ public: void f() { cout << " Derivata " << endl; }
};
void g(Cb* p) { p->f(); }
void main ()
{ clrscr();
Cb* Pb = new Cb; Cd* Pd = new Cd;
Pb->f(); Pd->f(); // Legare Statica
g(Pb); g(Pd); // Legare Dinamica
delete Pb; delete Pd;
getche();
}

În exemplul următor vom utiliza variabile de tip referinţă la clasa de bază, respectiv
la clasa derivată.
// Met od ă vi r t u al ă \\
# include <conio.h>
# include <iostream.h>
class Cb { public:
virtual void f() { cout << " Baza " << endl; }
};
class Cd : public Cb
{ public: void f() { cout << " Derivata " << endl; }
};
void g(Cb& r) { r.f(); }
void main ()
{ clrscr();
Cb Ob; Cd Od;
Ob.f(); Od.f(); // Legare Statica
g(Ob); g(Od); // Legare Dinamica
getche();
}

26.11.18 116
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În următorul exemplu se poate deduce necesitatea legării dinamice, pentru a putea
calcula corect distanţa de la un punct la un cerc şi respectiv la un segment (la o dreaptă).
Din păcate pentru că metoda Contine există în dublu exemplar (Stanga şi Dreapta) apelul
nu se poate efectua cum ar fi de dorit!
// Met od ă vi r t u al ă \\
#include <conio.h>;
#include <iostream.h>;
#include <math.h>;
float Sqr (float x) { return x*x; }
class Punct { protected: float x,y;
public: Punct (float x0, float y0) { x=x0; y=y0; }
Punct (Punct &P) { x=P.x; y=P.y; }
virtual float Dist (Punct P) {return sqrt(Sqr(x-P.x)+Sqr(y-P.y));
int Contine(Punct P) {return Dist(P)==0; };
};
class Cerc : public Punct { float r;
public: Cerc (float x0, float y0, float R):Punct(x0,y0){r=R;}
float Dist (Punct P) {Punct C(x,y); return C.Dist(P)-r; }
};

class Stanga : public Punct


{ public:Stanga (float x0, float y0) : Punct(x0,y0) { }
Stanga (Punct& P) : Punct(P) { }
};
class Dreapta: public Punct
{ public:Dreapta(float x0, float y0) : Punct(x0,y0) { }
Dreapta(Punct& P) : Punct(P) { }
};

class Segm : public Stanga, Dreapta {


public: Segm(Punct St, Punct Dr) : Stanga(St), Dreapta(Dr) { }
float Dist (Punct C) { Punct A(Stanga::x, Stanga::y);
Punct B(Dreapta::x,Dreapta::y);
float a=B.Dist(C);
float b=A.Dist(C);
float c=A.Dist(B);
float p=(a+b+c)/2;
float S=sqrt(p*(p-a)*(p-b)*(p-c));
return 2*S/c; }
};

void main (void)


{ clrscr();
Punct P(3,4);
Cerc C(0,0,5);
if (C.Contine(P)) cout << " Cercul C contine punctul P." ;
else cout << " Cercul C nu contine punctul P." ;
Punct A(0,0), B(6,8);
Segm AB(A,B);
if (AB.Stanga::Contine(P)) cout << " Segm. AB contine punctul P." ;
else cout << " Segm. AB nu contine punctul P." ;
getche();
}

26.11.18 117
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Aproape orice metodă poate fi virtuală, chiar şi metodele inline, metodele friend
(dar nu şi funcţiile friend) operatorii (dacă nu se redefinesc prin funcţii friend) şi
destructorii, în schimb constructorii şi metodele statice nu pot fi virtuale.
În exemplul prezentat în continuare, al doilea produs ( 2/3 * 4/5 = 8/15) nu va fi
afişat dacă operatorul de înmulţire a două numere raţionale nu este declarat virtual,
(deoarece operatorul *= va apela operatorul de înmulţire pentru Q în loc de F cum ar
trebui, a şi b fiind din clasa F). Se observă că la înmulţirea a două obiecte din clasa Q nu
sunt tipărite fracţiile care se înmulţesc, pe când la înmulţirea a două obiecte din clasa F
fracţiile care se înmulţesc sunt tipărite.

// Program Operator Virtual; \\


#include <conio.h>; #include <iostream.h>;
class Q { protected: int p,q;
public: Q (int m=0, int n=1) { p=m;q=n; }
virtual Q operator * (Q& r) { return Q(p*r.p, q*r.q); }
Q& operator *= (Q& r) { return *this=*this * r; }
void Tip (char* Ms) { cout << Ms << p << "/" << q; }
};
class F : public Q {
public: F (int m=0, int n=1) : Q (m,n) { }
Q operator * (Q& r)
{ Q f = Q(*this) * r; this->Tip(""); r.Tip(" * ");
f.Tip(" = "); cout << endl; return f; }
};

void main (void)


{ clrscr();
Q p(2,3), q(4,5), r;
p.Tip(" p = "); cout << endl; q.Tip(" q = "); cout << endl;
r=p*=q;
p.Tip(" p = "); cout << endl; r.Tip(" r = "); cout << endl;
F a(2,3), b(4,5); Q d;
a.Tip(" a = "); cout << endl; b.Tip(" b = "); cout << endl;
d=a*b; d.Tip(" d = "); cout << endl;
d=a*=b; d.Tip(" d = "); cout << endl;
getch();
} // R e z u l t a t e :
p = 2/3
q = 4/5
p = 8/15
r = 8/15
a = 2/3
b = 4/5
2/3 * 4/5 = 8/15
d = 8/15
2/3 * 4/5 = 8/15
d = 8/15

26.11.18 118
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
26.2. Clase abstracte - funcţii membru virtuale p u r e

În clasa de bază se poate declara o comportare generică având un nume şi o


semnătură unică (urmând ca fiecare specializare să ofere propria metodă specifică) prin:
a) metode nule care se declară astfel:

virtual Tip_met Nume_met (Listă_Par_Formali) { }


b) metode pure declarate în forma:

virtual Tip_met Nume_met (Listă_Par_Formali) = 0;


Ambele variante permit înlocuirea acestei metode cu o metodă proprie clasei
specializate derivată din clasa de bază, permiţând astfel solicitarea unui comportament
general, dar propriu fiecărei specializări.
Metodele pure nu pot fi apelate, rolul lor fiind doar de a declara tipul, numele şi
parametrii unei metode abstracte care urmează să fie redefinită concret în fiecare clasă
specializată.

O clasă este abstractă dacă ea conţine cel puţin o funcţie membru virtuală pură. O
funcţie membru virtuală este pură dacă ea este declarată (virtual antet = 0) dar nu este
definită în clasa din care face parte ci într-o clasă derivată. Deoarece clasele abstracte
conţin funcţii membru nedefinite (virtuale pure), nu se pot crea obiecte aparţinând acestora
(nu pot fi instanţiate, dar se pot defini variabile de tip pointer sau referinţă la o clasă
abstractă), iar dacă funcţiile virtuale nu sunt definite nici în clasele derivate, atunci şi aceste
clase devin abstracte (o clasă derivată dintr-o clasă abstractă rămâne abstractă dacă nu s-au
redefinit toate metodele pure moştenite, iar în caz contrar devine clasă concretă).

O clasă abstractă realizează implementarea unei noţiuni care nu poate fi concretizată


(şi atunci nu poate fi decât enunţată), dar surprinde o caracteristică comună a claselor
specializate din aceasta (care vor conţine implementările efective). Deci, o clasă abstractă
va generaliza (abstractiza) comportamentul subclaselor specializate.

Într-o ierarhie, clasa de bază poate avea nişte


proprietăţi care nu se pot defini decât în clasele Animal

derivate (anumite caracteristici depind de clasa


derivată). În exemplul alăturat, cu toate că se
cunoaşte greutatea unui animal, nu se poate spune că Porumbel Urs Cal

este slab sau gras decât pentru o clasă derivată).

26.11.18 119
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor vom da trei caracterizări pentru un anumit animal în funcţie de
greutatea lui şi cea medie (slab/gras), vârsta lui şi cea medie (tânăr/bătrân), şi viteza lui (de
deplasare) şi cea medie (lent/rapid), acestea pentru un Porumbel, Urs sau Cal.

/ / Cl as e A bs tr ac te - M et od e Pure \ \
#include <iostream.h>
#include <conio.h>
class Animal { protected: double Greut, Varsta, Viteza;
public: Animal (double Kg, double Ani, double Km_H)
{Greut= Kg; Varsta=Ani, Viteza=Km_H;}
virtual double Greut__Medie () = 0;
virtual double Varsta_Medie () = 0;
virtual double Viteza_Medie () = 0;
int Slab () { return Greut < Greut__Medie(); }
int Tanar() { return Varsta< Varsta_Medie()/2; }
int Lent () { return Viteza< Viteza_Medie(); }
void Tip () { cout << ( Slab ()? "slab, " : "gras, " )
<< ( Tanar()? "tanar, " : "batran," )
<< ( Lent ()? "lent \n" : "rapid\n" );}
};
class Porumbel:public Animal {
public: Porumbel (double Kg, double Ani, double Km_H) :
Animal(Kg, Ani, Km_H) { }
double Greut__Medie () { return 0.5; }
double Varsta_Medie () { return 6.0; }
double Viteza_Medie () { return 90.0; }
};
class Urs: public Animal {
public: Urs (double Kg, double Ani, double Km_H) :
Animal(Kg, Ani, Km_H) { }
double Greut__Medie () { return 450; }
double Varsta_Medie () { return 43; }
double Viteza_Medie () { return 40; }
};
class Cal: public Animal {
public: Cal (double Kg, double Ani, double Km_H) :
Animal(Kg, Ani, Km_H) { }
double Greut__Medie () { return 1000; }
double Varsta_Medie () { return 36; }
double Viteza_Medie () { return 60; }
};
void main (void)
{ clrscr();
Porumbel p (0.6, 1, 80); p.Tip();
Urs u (500,40, 46); u.Tip();
Cal c (900, 8, 70); c.Tip(); getch();

} // Rezultate:
gras, tanar, lent
gras, batran, rapid
slab, tanar, rapid

26.11.18 120
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor vom apela o funcţie Draw pentru a Figură
desena o figură oarecare (Punct, Pătrat sau Cerc) şi o funcţie Arie
care va aplica formula caracteristică fiecărei figuri geometrice: Punct Pătrat Cerc

/ / Cl as ă A bs tr ac tă - M et od e Pure \ \
# include <Conio.h>
# include <Process.h>
# include <Iostream.h>
# include <Graphics.h>
class Figura { protected: int x,y;
public: Figura (int u=0, int v=0) { x=u; y=v; }
virtual void Draw () = 0; // Pura sau Nula
{ }
virtual int Arie () = 0;
int Pret () { return Arie()*100+1; }
};
class Punct : public Figura {
int Cul;
public: Punct (int u, int v, int
c=WHITE):Figura(u,v)
{ Cul=c;
}
void Draw() { putpixel(x,y,Cul); }
int Arie() { return 0; }
};
class Patrat : public Figura {
int Lat;
public: Patrat (int u, int v, int L=1) :
Figura(u,v)
{ Lat=L;
}
void Draw() { moveto(x,y);
linerel(0,+Lat); linerel(+Lat,0);
linerel(0,-Lat); linerel(-
Lat,0); }
int Arie() { return Lat*Lat; }
};
class Cerc : public Figura {
int Raza;
public: Cerc (int u, int v, int R=1) : Figura(u,v)
{ Raza=R;}
void Draw() { circle(x,y,Raza); }
int Arie() { return 3*Raza*Raza; }
};
void InitGraf(void) { int Gd = DETECT, Gm; initgraph(&Gd, &Gm, "C:\\BorlandC\\Bgi"); }
void main (void)
{ clrscr();
Figura* Fig[22];
int i,n; cout << " Dati n : "; cin >> n;
for (i=0; i<n; i++) { int t,x,y,z;
cout << " Dati fig." << i+1 << "(t,x,y,z): "; cin >> t >> x >> y >>
z;
switch (t) { case 1: Fig[i]=new Punct (x,y,z); break;
case 2: Fig[i]=new Patrat(x,y,z); break;
case 3: Fig[i]=new Cerc (x,y,z); break;
default: exit(1);
};
cout << " Pret = " << Fig[i]->Pret() << endl;

26.11.18 121
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
};
getche(); InitGraf();
for (i=0; i<n; i++) { setcolor(15-i); Fig[i]->Draw();}
getche(); closegraph();
}

26.11.18 122
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
27. I e r a r h i i p e n t r u I n t r ă r i / I e ş i r i

Pentru că nu există instrucţiuni de intrare/ieşire, s-au definit funcţii (în C), respectiv
două ierarhii de clase (în C++). Aceste două ierarhii (reprezentate în figurile de mai jos şi
declarate în fişierul iostream.h) realizează operaţiile de intrare/ieşire prin stream-uri (flux de
date sursădestinaţie).
strembuf

filebuf strstreambuf

Clasa streambuf se foloseşte pentru gestionarea zonelor tampon şi operaţii de


intrare/ieşire simple.

Clasa ios este clasa de bază vituală pentru


clasa istream (care face conversia după un format
ios
specificat, din caracterele unui obiect de tip
streambuf), clasa ostream (care face conversia după
istream ostream
un format specificat, în caractere ale unui obiect de
tip streambuf) şi clasa iostream (care face conversii iostream

în ambele sensuri). Legătura dintre cele două istream_withassign ostream_withassig


ierarhii se realizează printr-o dată membru a clasei
iostream_withassig
ios (pointer la streambuf).
Clasele derivate din clasa istream sau ostream se numesc clase stream iar obiectele
claselor derivate din clasa ios se numesc streamuri. În fişierul iostream.h sunt definite
streamurile cin ( istream_withassign, pentru stdin), cout ( ostream_withassign, pentru
stdout), clog şi cerr ( ostream_withassign, pentru stderr, cu respectiv fără zone tampon).

27.1. Operatorul de inserare <<


Operaţiile de scriere se pot efectua cu operatorul de inserare << . Operandul stâng
trebuie să fie un obiect al clasei ostream (sau al unei clase derivate). Pentru scrierea pe
dispozitivul standard se va folosi obiectul cout. Operandul drept este o expresie pentru al
cărei tip a fost supraîncărcat operatorul << . Pentru tipurile standard a fost supraîncărcat
printr-o funcţie membru de forma:

ostream& operator << ( Tip_Standard );

26.11.18 123
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Pentru tipurile abstracte programatorul poate supraîncărca acest operator, aşa cum
se poate vedea în cele ce urmează.
Pentru a putea tipări un obiect
cout << Obiect ;
vom supraîncărcărca (într-o primă variantă) operatorul de inserare (<<) printr-o funcţie
prieten astfel:
class Clasă { ...
friend ostream& operator << ( ostream&, Clasă );
...
};
Exemplu:
// Progr am O per at or < < Fr ien d; \\
#include <iostream.h> #include <conio.h>

class Q { protected: int p,q;


public: Q (int m=0, int n=1) { p=m;q=n; }
friend ostream& operator << ( ostream& s, Q r )
{ s << r.p << "/" << r.q; return s; }
};
void main (void)
{ Q r(12,13); clrscr();
cout << " r = " << r << endl; getch();
} // Rezultate:
r = 12/13

Se observă că acest operator se poate aplica înlănţuit pentru că funcţia prieten


returnează o referinţă la stream-ul curent.
În cele ce urmează vom da o altă rezolvare fără a utiliza o funcţie prieten (care
micşorează gradul de protecţie a datelor). Pentru o Clasă vom scrie o funcţie membru de
Tipărire, care va fi apelată de către funcţia de supraîncărcare a operatorului << astfel:

class Clasă { ...


public: ostream& Tipărire ( ostream& s );
...
};
ostream& Tipărire ( ostream& s )
{ s << ... ;
return s;
}
ostream& operator << ( ostream&, Clasă c )
{
return c.Tipărire(s);
}

26.11.18 124
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Pentru exemplul anterior (Q) programul va fi următorul:
// Progr am O per a tor << \\
#include <iostream.h>
#include <conio.h>
class Q { protected: int p,q;
public: Q (int m=0, int n=1) { p=m;q=n; }
ostream& Tip (ostream& s)
{ s << p << "/" << q; return s; }
};
ostream& operator << ( ostream& s, Q r ) { return r.Tip(s); }
void main (void)
{ Q r(12,13); clrscr();
cout << " r = " << r << endl; getch();
} // Rezultate:
r = 12/13

27.2. Operatorul de extragere >>

Operaţiile de citire se pot efectua cu operatorul de extragere >> . Operandul stâng


trebuie să fie un obiect al clasei istream (sau al unei clase derivate). Pentru citirea de la
dispozitivul standard se va folosi obiectul cin. Operandul drept este o expresie pentru al
cărei tip (standard sau abstract) a fost supraîncărcat operatorul >> . Pentru tipurile
standard a fost supraîncărcat printr-o funcţie membru de forma:

istream& operator >> ( Tip_Standard & );

Pentru tipurile abstracte programatorul poate supraîncărca acest operator, aşa cum
se poate vedea în cele ce urmează. Pentru a putea citi un obiect

cin >> Obiect ;

vom supraîncărcărca (într-o primă variantă) operatorul de extragere (>>) printr-o funcţie
prieten astfel:

class Clasă { ...


friend istream& operator >> ( istream&, Clasă& );
...
};

26.11.18 125
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Exemplu:
// Progr am O per at or > > Fr ien d; \\
#include <iostream.h>
#include <conio.h>
class Q { protected: int p,q;
public: Q (int m=0, int n=1) { p=m; q=n; }
friend ostream& operator << ( ostream& s, Q r )
{ s << r.p << " / " << r.q; return s; }
friend istream& operator >> ( istream& s, Q& r )
{ s >> r.p >> r.q; return s; }
};
void main (void)
{ Q r; clrscr();
cin >> r;
cout << " r = " << r << endl; getch();
}

Se observă că acest operator se poate aplica înlănţuit pentru că funcţia prieten


returnează o referinţă la stream-ul curent.
În cele ce urmează vom da o altă rezolvare fără a utiliza o funcţie prieten (funcţie
care micşorează gradul de protecţie a datelor). Pentru o Clasă vom scrie o funcţie membru
de Citire, (care va fi apelată de către funcţia de supraîncărcare a operatorului >> ) astfel:
class Clasă { ...
public: istream& Citire ( istream& s );
...
};
istream& Citire ( istream& s );
{ s >> ... ;
return s;
}
istream& operator >> ( istream&, Clasă& c );
{
return c. Citire (s);
}

Pentru exemplul anterior (Q) programul va fi următorul:


// Progr am O per a tor >> \\
#include <iostream.h>
#include <conio.h>
class Q { protected: int p,q;
public: Q (int m=0, int n=1) { p=m; q=n; }
ostream& Tip (ostream& s) { s << p << "/" << q; return s; }
istream& Cit (istream& s) { s >> p >> q; return s; }
};
ostream& operator << ( ostream& s, Q r ) { return r.Tip(s); }
istream& operator >> ( istream& s, Q& r ) { return r.Cit(s); }
void main (void)
{ Q r; clrscr();
cin >> r ;
cout << " r = " << r << endl; getch();

26.11.18 126
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
27.3. Intrări/Ieşiri cu format

Tipărirea (afişarea) datelor după un anumit format (şablon) precizat (asemănător


funcţiilor scanf şi printf) se poate realiza şi cu ajutorul ierarhiilor de clase definite în C++,
fie prin apelul funcţiilor membru setf, width, fill, precision , fie cu ajutorul unor
metode speciale numite manipulatori.
27.3.1. Funcţiile membru setf, width, fill,
precision
Clasa ios conţine o dată membru x_flags care conţine formatul operaţiilor de intrare-
ieşire. În aceeaşi clasă mai este definit un tip enumerare prin care se poate referi formatul
corespunzător conversiei ataşate operaţiilor de transfer:
class ios { public: …
enum {
skipws = 0x0001, // salt peste (ignoră la citire) caracterele albe
left = 0x0002, // cadrare la stânga
right = 0x0004, // cadrare la dreapta
internal = 0x0008, // spaţiile după semn sau bază
dec = 0x0010, // conversie în zecimal
oct = 0x0020, // conversie în octal
hex = 0x0040, // conversie în heza
showbase = 0x0080, // afişarea bazei
showpoint = 0x0100, // afişare punct zecimal
uppercase = 0x0200, // cifre hexa cu litere mari
showpos = 0x0400, // afişare cu semn
scientific = 0x0800, // reale cu exponent
fixed = 0x1000, // reale fără exponent
unitbuf = 0x2000, // vidare zone tampon supă scriere
stdio = 0x4000 // vidare stdout şi stderr
};

};

Atributul x_flags are o valoare implicită pentru fiecare tip standard, care se poate
modifica utilizând funcţia membru setf descrisă în continuare.
Metoda setf are următoarele două forme:
1) long setf (long format);
2) long setf (long bit, long grup);

Funcţia modifică atributul x_flags precizând întraga valoare (varianta a)) sau
precizând un grup de biţi şi bitul dorit din cadrul grupului (varianta b)). Grupele (şi valorile
corespunzătoare) sunt adjustfield (left, right, internal), basefield (dec, oct, hex) şi
floatfield (scientific, fixed) În ambele variante funcţia returnează valoarea anterioară a
atributului x_flags. Referirea grupului şi bitului dorit se face prin numele clasei urmat de
operatorul de rezoluţie şi bitul dorit (ios::b). Valoarea atributului x_flags se poate obţine şi
prin apelul metodei flags (cout.flags() ).

26.11.18 127
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Atributul x_width conţine lungimea minimă a câmpului de afişare a unei date
(respectiv lungimea maximă a câmpului din care se face citirea), având valoarea implicită
nulă (afişare pe lungimea minimă necesară), care se poate modifica utilizând funcţia membru
width descrisă în continuare în ambele forme:
a) int width ( );
b) int width (int lungime);

Funcţia returnează valoarea atributului x_flags (varianta a)) sau modifică atributul
x_width precizând noua valoare (lungime care poate fi o expresie) şi returnează valoarea
anterioară a atributului x_width (varianta b)). După fiecare transfer valoarea atributului
x_flags devine nulă.

Atributul x_fill conţine caracterul de umplere necesar completării câmpului de afişare


a datei în situaţia în care lungimea acestuia este mai mare decât lungimea necesară, având
valoarea implicită spaţiu (‘ ‘), care se poate modifica utilizând funcţia membru fill :
a) char fill ( );
b) char fill (char car);

Funcţia returnează valoarea atributului x_ fill (varianta a)) sau modifică atributul x_
fill precizând noul caracter de umplere (car) şi returnează valoarea anterioară (varianta b)).

Atributul x_precision conţine precizia de afişare (numărul de zecimale) a unei date de


tip real, având valoarea implicită 0, care se poate modifica utilizând funcţia membru
precision :
a) int precision ( );
b) int precision (int n);

Funcţia returnează valoarea atributului x_ precision (varianta a)) sau modifică


atributul x_ precision precizând noua precizie (p) şi returnează valoarea anterioară (varianta
b)).

În exemplul următor se poate vedea apelul funcţiilor prezentate anterior precum şi


rezultatele obţinute:

// Op erat oru l d e i n serare << cu form a t \\


#include <conio.h>
#include <iostream.h>
class N { int c;
public: N (int x=0 ) { c=x; }
istream& Cit (istream& s) { s >> c; return s; }
ostream& Tip (ostream& s) { s << c; return s; }
operator double ( ) { return this-> c; } // N -> R
};
istream& operator >> (istream& s, N& C) { return C.Cit(s); }
ostream& operator << (ostream& s, N C) { return C.Tip(s); }

26.11.18 128
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
void main (void)
{ clrscr();
N n;
cout << " Dati un numar natural : "; cin >> n;
cout << " Numarul natural n este: " << n << endl;
cout.setf(ios::hex,ios::basefield);
cout << " Numarul natural n este: " << n << endl;
cout.setf(ios::showbase);
cout << " Numarul natural n este: " << n << endl;
cout << " Numarul natural n este: ";
cout.setf(ios::dec,ios::basefield);
cout.width(6); cout.fill('.');
cout << n << endl;
double x(n); cout << " Numarul n/3.14159 este: ";
cout.setf(ios::fixed,ios::floatfield);
cout.width(9); cout.fill('_'); cout.precision(2);
cout << x/3.14159 << endl;
getche();
}
Rezultate:
Dati un numar natural : 100
Numarul natural n este: 100
Numarul natural n este: 64
Numarul natural n este: 0x64
Numarul natural n este: ...100
Numarul n/3.14159 este: ____31.83

27.3.2. Manipulatori
Atributele x_flags, x_width, x_fill şi x_precision pot fi modificate şi cu ajutorul
manipulatorilor, aceştia având avantajul că pot fi apelaţi înlănţuit (deoarece returnează
referinţă la stream). Primii şapte manipulatori prezentaţi în continuare sunt declaraţi în
fişierul iostream.h, iar ultimii şase în fişierul iomanip.h :
1. ws setarea bitului de salt (skipws)
2. dec conversie în zecimal
3. oct conversie în octal
4. hex conversie în hexa
5. flush vidarea zonei tampon a ob. stream
6. ends inserare car. Nul ‘\0’
7. endl trece la rând nou şi vidarea zonei tampon
1. setbase (int b) defineşte baza în care se face conversia
2. setiosflags (int f) setarea unor biţi precizaţi
3. resetiosflags (long f) ştergerea unor biţi precizaţi
4. setw (int l) defineşte lungimea câmpului
5. setfill (int c) defineşte caracterul de umplere
6. setprecision (int p) defineşte numărul de zecimale

Exemplul următor utilizează manipulatorii pentru a realiza tipărirea rezultatelor


dorite:

26.11.18 129
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
// Op erat oru l d e i n serare << cu manipul atori \\
#include <conio.h>
#include <iostream.h>
#include <iomanip.h> Rezultate :
n : 100
class N { int c; n = 100
public: N (int x=0 ) { c=x; }
istream& Cit (istream& s) { s >> c; return s; } n = 64 : 2001
ostream& Tip (ostream& s) { s << c; return s; } n = 0x64
operator double ( ) { return this-> c; } n = ...100
}; n/3= ____33.33
istream& operator >> (istream& s, N& C) { return C.Cit(s); }
ostream& operator << (ostream& s, N C) { return C.Tip(s); }

void main (void)


{ clrscr();
N n;
cout << " n : "; cin >> n;
cout << " n = " << n << endl;
cout << " n = " << hex << n <<" : "<< cout.flags() << endl;
cout << " n = " << setiosflags(cout.showbase) << n << endl;
cout << " n = " << dec <<setw(6)<<setfill('.')<< n << endl;
cout << "n/3= " << setw(9)<<setfill('_')<<setprecision(2)<<n/3;
getche();
}

În exemplul următor se utilizează manipulatorii pentru a realiza citirea datelor


utilizând un format variabil (width(i+1)):

// Op erat oru l d e e xt r age re >> cu manipulat ori \\


#include <conio.h>
#include <iostream.h> Rezultate :
#include <iomanip.h>
1 : 1234567890
class N { char c[6]; _______________ n = 1
public: N ( ) { c[0]=0; } 2 : _______________ n = 23
istream& Cit (istream& s) { s >> c; return s; } 3 : _______________ n = 456
ostream& Tip (ostream& s) { s << c; return s; } 4 : _______________ n = 7890
}; 5 : 1234567890
istream& operator >> (istream& s, N& C) {return C.Cit(s);} _______________ n = 12345
ostream& operator << (ostream& s, N C) {return C.Tip(s);}
void main (void)
{ clrscr();
N n;
for (int i=1; i<=5; i++) { cout << i << " : ";
cin >> setw(i+1) >> n ; // cin.width(i+1);
cout << " _______________ n = " << n << endl;
}
getche();
}

26.11.18 130
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
27.4. Tratarea erorilor la operaţiile de intrare/ieşire

Dacă o operaţie de intrare/ieşire nu s-a încheiat cu succes (nu s-a desfăşurat corect,
situaţie în care vom spune că streamul ajunge într-o stare de eroare), programul poate lua o
decizie (controlând în acest fel desfăşurarea transferurilor de date în scopul corectitudinii
desfăşurării lor). Tipul erorii (un codul de retur) poate fi aflat verificând biţii datei membru
state (de tip int) prin tipul enumerare io_state definit în clasa ios astfel:
class ios { public: …
enum {
goodbit = 0x00, // operaţie corectă
eofbit = 0x01, // sfârşit de fişier
failbit = 0x02, // eroare intrare/ieşire
badbit = 0x04, // operaţie invalidă
hardfail = 0x80, // eroare fatală
};

};

Valorile (biţilor) atributului state se pot determina utilizând următoarele funcţii:


1) int good (); // biţii de eroare (eofbit, failbit, badbit, hardfail) nu sunt setaţi,
2) int eof (); // este setat bitul eofbit,
3) int fail (); // este setat bitul failbit sau badbit sau hardfail,
4) int bad (); // este setat bitul badbit sau hardfail,
5) int rdstate (); // returnează toate valorile biţilor de stare (valoarea datei state).

Valorile biţilor datei state pot fi modificate cu funcţia:


void clear (int = 0);
La un apel fără paramteru actual se vor anula biţii eofbit, failbit şi badbit iar pentru a
preciza un anumit bit se poate folosi ca parametri actual o expresie de forma:
cin.clear (ios::nume_bit); // nume_bit restul anulaţi
Exemplu:
cin.clear (ios::bad_bit | cin.rdstate() ); // bad_bit restul neschimbaţi

Citirea (inclusiv a caracterelor albe) se poate realiza cu funcţia membru getline


definită astfel:
istream& getline ([un]signed char* z, int n, char c = ’\n’);
care citeşte cel mult n-1 caractere sau întâlneşte caracterul c.
În exemplul următor se citesc mai multe cuvinte separate prin spaţii:

class N { char c[80]; … Rezultate :
istream& Cit (istream& s) {s.getline(c,80); return s;} : Citeste spatiile.
… }; … = Citeste spatiile.
void main (void) : ^Z
{ N n;
do {cout <<':'; cin >>n; if (cin.good()) cout <<'='<<n<<endl;} while (!cin.eof());
}

26.11.18 131
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor se repetă citirea până când numărul tastat este corect:
// C on t rol u l erori l or l a op . I/E \\
#include <conio.h>
#include <iostream.h>
class N { int c; Rezultate :
public: N ( ) { c=0; } n : a
istream& Cit (istream& s) { s >> c; return s; } State : 2
ostream& Tip (ostream& s) { s << c; return s; } n : ^Z
}; State : 3
istream& operator >> (istream& s, N& C) { return C.Cit(s); } n : 123
ostream& operator << (ostream& s, N C) { return C.Tip(s); } State : 0
void main (void) n = 123
{
clrscr();
N n; int Gresit;
do {
cout << " n : "; cin >> n ;
cout << " State : " << hex << cin.rdstate() << endl;
if (cin.good()) Gresit=0; else {
Gresit=1;
cin.clear(); // anulare biti
char t[255]; // zona tampon
cin.getline(t,255); // vidare z.t.
} }
while (Gresit);
cout << " n = " << dec << n << endl;
getche();
}

Verificarea stării de eroare a unui stream se mai poate face prin operatorul ! sau prin
conversia într-un pointer fără tip (void*) :
a) operatorul ! este supraîncărcat cu metoda clasei ios:
int operator ! ( ); // returnează o valoare egală cu a funcţiei fail();
De exemplu, în programul Propoziţie.Cpp prezentat anterior instrucţiunea
if (cin.good()) cout << '=' << n << endl;
se poate înlocui cu
if (!!cin) cout << '=' << n << endl;
sau mai simplu cu
if (cin) cout << '=' << n << endl;
b) conversia spre tipul void* permite verificarea stării de eroare a stream-ului, şi poate fi
utilizată în construcţii de forma
if ( s >> dată) … ;
rezultatul (o referinţă la obiectul stream  clasei istream) fiind NULL (0) dacă funcţia fail( )
 0.

Citirea caracterelor sau a datelor se poate realiza şi cu funcţia membru get definită
astfel:
a) int get ( ); // extrage un caracter din stream-ul curent,
b) istream& get ([un]signed char* z, int n, char c = ’\n’); // nu extrage caracterul c.

26.11.18 132
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
În exemplul următor se poate vedea atât utilizarea conversiei spre tipul void*,
precum şi a funcţiei membru get ( în varianta b)):
// C on t rol u l erori l or l a op . I/E \\
#include <iostream.h>
#include <string.h>

class N { int c;
char*Mes;
char*Mer;
char*Met;
public: N (int c=0, char* mes=" : ",
char* mer=" Err.\n",
char* met=" = ");
istream& Cit (istream& s);
ostream& Tip (ostream& s) {s<<Met<<c; return s;}
};

N::N (int c, char* mes, char* mer, char* met)


{ this->c=c;
Mes=new char[strlen(mes)+1]; strcpy(Mes,mes);
Mer=new char[strlen(mer)+1]; strcpy(Mer,mer);
Met=new char[strlen(met)+1]; strcpy(Met,met);
}

istream& N::Cit(istream& s)
{
cout << Mes;
while (!(s>>c)) { char t[255];
s.clear(); s.get(t,255);
if (s.get()==EOF) return s;
cout << Mer << Mes;
}
return s;
}

istream& operator >> (istream& s, N& C) { return C.Cit(s); }


ostream& operator << (ostream& s, N C) { return C.Tip(s); } Rezultate :
: 123
void main (void) = 123
{ : a
N n; Err.
: 456
do { = 456
cin >> n; : xy
if (cin) cout << n << endl; Err.
} : ^Z
while (!cin.eof());
}

26.11.18 133
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Cuprins
pag.
1. Redactarea programelor C.........................................................................1
1.1. Generalităţi...........................................................................................1
1.2. Structura unui program.........................................................................1
1.3. Funcţii..................................................................................................2
1.4. Elementele limbajului...........................................................................3

2. Variabile...................................................................................................4
2.1. Variabile globale...................................................................................4
2.2. Variabile locale.....................................................................................4
2.3. Variabile de tip registru........................................................................5
2.4. Iniţializarea variabilelor.......................................................................6

3. Expresii.....................................................................................................7
3.1. Operatori..............................................................................................7

4. Operaţii de intrare/ieşire.......................................................................11
4.1. Funcţia Printf....................................................................................11
4.2. Funcţia Scanf.....................................................................................12
4.3. Funcţia PutChar................................................................................13
4.4. Funcţia GetChar................................................................................13
4.5. Funcţia GetChe.................................................................................13
4.6. Funcţia GetCh....................................................................................13

5. Instrucţiuni.............................................................................................14
5.1. Instrucţiunea Vidă..............................................................................14
5.2. Instrucţiunea Expresie.......................................................................14
5.3. Instrucţiunea Compusă......................................................................14
5.4. Instrucţiunea If..................................................................................15
5.5. Instrucţiunea Switch..........................................................................15
5.6. Instrucţiunea While............................................................................16
5.7. Instrucţiunea Do_While.....................................................................16
5.8. Instrucţiunea For...............................................................................17
5.9. Instrucţiunea Break.............................................................................17
5.10. Instrucţiunea Continue.......................................................................17

26.11.18 134
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
5.11. Instrucţiunea GoTo.............................................................................17
5.12. Apelul unei funcţii..............................................................................18

6. Pointeri...................................................................................................20
6.1. Declararea unui Pointer......................................................................20
6.2. Operaţii cu Pointeri............................................................................21
6.3. Alocare dinamică a memoriei.............................................................22
6.4. Pointeri la funcţii.............................................................................23
6.5. Utilizarea parametrilor din linia de comandă.....................................24
6.6. Declararea c o n s t antelor..................................................................24
6.7. S t i v a .................................................................................................25

7. Recursiviate............................................................................................25
8. Tipuri de date.........................................................................................26
8.1. Definirea unui tip de dată (typedef)..................................................26
8.2. Tipul enumerare (enum).....................................................................26
8.3. Definirea unei structuri (struct).........................................................27
8.4. Redefinirea unei date (union).............................................................28
8.5. Câmpuri de biti..................................................................................28

9. Structuri de date dinamice....................................................................29


9.1. Listă simplu înlănţuită ordonată.........................................................29
9.2. Abori binari........................................................................................30

10. Utilizarea fişierelor........................................................................32


10.1. Nivelul inferior...................................................................................32
10.2. Nivelul superior..................................................................................35

11. Funcţii standard.............................................................................40


11.1. Macrouri de clasificare.......................................................................40
11.2. Macrouri de transformare a simbolurilor............................................40
11.3. Conversii............................................................................................40
11.4. Funcţii de prelucrare a şirurilor de caractere......................................41
11.5. Funcţii de calcul.................................................................................41
11.6. Funcţii pentru controlul proceselor....................................................42
11.7. Funcţii pentru timp.............................................................................42
11.8. Funcţii diverse....................................................................................42

26.11.18 135
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
12. Ecranul în mod text.......................................................................43
13. Ecranul în mod grafic....................................................................44
14. Facilităţi C++.................................................................................47
14.1. Extensii ale limbajului C....................................................................47
14.2. Operatori............................................................................................48
14.3. Structură, uniune şi enumerare...........................................................51

15. Funcţii C++....................................................................................53


15.1. Funcţii Inline......................................................................................53
15.2. Funcţii de tip referinţă........................................................................54
15.3. Supraîncărcarea funcţiilor..................................................................56
15.4. Iniţializarea parametrilor formali........................................................57
15.5. Funcţii membru pentru Structuri........................................................58

16. T i p A b s t r a c t d e D a t ă ..........................................................59
17. Programare orientată obiect (OOP)............................................63
17.1. Definirea Claselor..............................................................................64
17.2. Constructori şi Destructori..............................................................68

18. Specificarea claselor – Limbajul UML(Unified Modeling Language).71


1 9 . F u n c ţ i i ş i C l a s e P r i e t e n e ( F r i e n d ) ................................72
2 0 . M e m b r i s t a t i c i ( S t a t i c ) // $ : ................................................76
20.1. Atribute (Date membru) Statice // $ : .................................................76
20.2. Metode (Funcţii membru) Statice // $ : ..............................................78

21. Pointeri la Metode..........................................................................79


22. Supraîncărcarea operatorilor.......................................................81
22.1. Operatorul de asignare (atribuire) şi iniţializare (=)..........................82
22.2. Operatorii de atribuire +=, =, *=, /=...........................................84
22.3. Operatorii de incrementare (++) şi decrementare ()......................85

23. Conversii utilizator........................................................................86


23.1. Conversii implicite.............................................................................86
23.2. Conversii explicite..............................................................................89

26.11.18 136
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
24. Clase Şablon (Template).................................................................91
24.1. Funcţii Şablon (Template)..................................................................91
24.2. Clase Template...................................................................................92
24.3. Implementarea elementelor Template.................................................93

25. Relaţii între clase...........................................................................94


25.1. Relaţia de Asociaţie............................................................................95
25.2. Relaţia de Agregare............................................................................98
25.3. Clase Încuibate(imbricate)................................................................101
25.4. Relaţia de derivare............................................................................103

2 6 . P o l i m o r f i s m .............................................................................113
26.1. Funcţii membru Vi r t u a l e ...............................................................114
26.2. Clase abstracte - funcţii membru virtuale p u re ..............................117

2 7 . I e r a r h i i p e n t r u I n t r ă r i / I e ş i r i .........................................120
27.1. Operatorul de inserare <<..............................................................120
27.2. Operatorul de extragere >>...........................................................122
27.3. Intrări/Ieşiri cu format......................................................................124
27.4. Tratarea erorilor la operaţiile de intrare/ieşire..................................128

Cuprins.....................................................................................................131
Bibliografie...............................................................................................135

26.11.18 137
+
C+ SC ALL – INC SRL - MANAGER - SPĂTARU VIRGIL
O
PO
Bibliografie

1. Dan Roman, Ingineria programării obiectuale, Editura Albastră, Cluj_Napoca, 1996;


2. Dorin & Ioan Mircea Popovici, Iustin Tanase, Tehnologia orientată pe obiecte.
Aplicaţii, Editura Teora, Bucureşti, 1996;
3. Ellis Horowitz, Sartaj Sahni, Dinesh Metha, Fundamentals of data structures in C+
+, Computer Science Press, New York, 1995;
4. Liviu Negrescu, Limbajele C şi C++ pentru începători, Editura Albastră, Cluj_Napoca,
1997;
5. Thomas A. Standish, Data Structures, Algorithms & Software Principles in C,
Addison-Weslay, California, 1995;
6. Vasile Cioban, Zsolt Darvay, Metode evoluate de programare, UBB-Mate_Info,
1999;

26.11.18 138

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