Sunteți pe pagina 1din 137

C

P
O
O
+
+

Prejmerean Vasile


C
l
u
j
-
N
a
p
o
c
a

2004
C
+
+
P
O
O

09.01.12 1
1. Redactarea programelor C
1.1. Generaliti
Mediul Borland C a fost extins la Visual C i C++ Builder, adaptate programrii
orientate obiect i interfeei grafice Windows 95. Limbajul C a fost extins la C++ permind
aplicarea conceptelor programrii prin abstractizarea datelor i programrii orientate spre
obiecte.
Fiierele surs pot avea extensia C, CP, sau CPP.
1.2. Structura unui program
Un program C este conine o funcie principal (main) i eventual alte funcii
secundare, apelate de ctre funcia principal, situate la acelai nivel (far imbricare).
Structura unui program este urmtoarea:
Directive de procesare,
Declaraii de date globale,
Declaraii de funcii, sau doar [ Antete de funcii (prototipuri) ]
Funcia principal; q
[ Descrierea funciilor (implementri) ]
Se observ c descrierea funciilor se poate face fie n ntregime naintea funciei
main fie doar prototipul nainte, iar corpul dup aceasta.
Comentariile se scriu ntre caracterele /* i */ ( ... /* comentariu */ ... ), sau la
nivelul unui rnd dup caracterele // ( ... // comentariu ).
nainte de compilare, un program este precompilat, de ctre un preprocesor, care
permite includerea unor fiier surs, definirea i apelul unror macrouri, precum i o
compilare condiionat.
Includerea unui fiier surs (*.h sau *.c) se realizeaz prin directiva include astfel:
# include specificator_fiier // pentru fiiere utilizator
sau
# include <specificator_fiier> // pentru fiiere standard
Exemplu:
#include <stdio.h>; // Standard Input Output Header
#include <iostream.h>; // Console Input, Console Output
C
+
+
P
O
O

09.01.12 2
Constantele simbolice se definesc cu ajutorul directivei define astfel:
#define Nume_constant ir_caractere
Exemplu:
#define Pi 3.141592 // nlocuiete Pi cu 3.141592
O constant simbolic poate fi redefinit sau anulat (#undef Nume_constant).
1.3. Funcii
O funcie este format dintr-un antet i un bloc (corp). Ea poate fi apelat dac a
fost definit n ntregime sau doar antetul su.
Antetul unei funcii are urmtorul format:
Tip Nume (List_parametri_formali)
unde:
Tip este tipul valorilor funciei (codomeniul);
Nume este un identificator (liter urmat eventual de alte litere sau cifre);
List_parametri_formali conine parametrii formali separai prin ,.
Exemplu: int Min (int a, int b)
{ if (a<b) return a; else return b; }
Observaie. Prototipul unei funcii este antetul acesteia urmat de ; .
Corpul unei funcii are urmtoarea structur:
{
Declaraii
Instruciuni
}
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;
}
C
+
+
P
O
O

09.01.12 3
1.4. Elementele limbajului
Alfabetul limbajului C este format din litere mari i mici, cifre i caractere speciale
(\n=CrLf, \t=Tab).
Identificatorii sunt formai 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 urmtoarele:
int (Z [-2
15
,2
15
-1]),
short (Z [-2
15
,2
15
-1]),
long (Z [-2
31
,2
31
-1]),
unsigned (N [0,2
16
-1]),
float (Q
*
[-3.410
-38
, 3.410
38
]),
double (Q
*
[-1.710
-308
, 1.710
308
]),
char (cod ASCII).
Constantele numerice pot fi zecimale (123, 123L
ong
, 111l
ong
), octale (077), hexa
(0xabba, 0Xfac), sau flotante (2.71828, 6.023e23, 6.023E23).
Constantele de tip caracter pot fi afiabile ('A', '0', '"') sau funcionale
('\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 [d
1
] [d
2
] ... [d
i
] ... [d
n
]; // indicele k
i
: 0e k
i
<d
i

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 conine adresa tabloului
a[1][0]=3; a[1][1]=4;
C
+
+
P
O
O

09.01.12 4
2. Variabile
Variabilele pot fi statice sau dinamice, locale sau globale.
2.1. Variabile globale
Declararea unei variabile globale se face la nceputul unui fiier surs (n afara
tuturor funciilor) i poate fi referit pn la sfritul programului (n orice funcie).
Utilizarea lor n alte fiiere surs se poate face doar dac acestea sunt declarate ca variabile
externe:
extern declaraie_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 funcia n care a
fost definit, putnd 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, declaraia ei trebuie s fie precedat
de cuvntul cheie static:
static declaraie_variabil
Funciile au implicit atributul extern, deci pot fi apelate din alte fiiere surs, dar
dac dorim ca acest apel s nu fie permis, atunci se vor declara statice prin scrierea
cuvntului cheie static naintea antetului acesteia ( static antet_funcie ) ?!.
C
+
+
P
O
O

09.01.12 5
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 mri viteza de execuie. n registrii se pot memora parametri
funciilor sau variabile automatice de tip int, char sau pointer. Pentru ca o variabil s fie
memorat ntr-un registru, declaraia ei trebuie s fie precedat de cuvntul cheie register:
register declaraie_variabil
Exemplu:
float f ( register int i );
{ register int n; register char c; ... }
C
+
+
P
O
O

09.01.12 6
2.4. Iniializarea variabilelor
Variabilele simple se iniializeaz printr-o declaraie de forma:
Tip Identificator_de_variabil = Expresie

Exemple:

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


Tablourile se iniializeaz printr-o declaraie de forma:
Tip Ident_tablou [n] = {Expresie
1
, Expresie
2
,..., Expresie
m
}
unde men, 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 iniializeaz 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 !"};



C
+
+
P
O
O

09.01.12 7
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 stnga la dreapta, cu excepia
operatorilor unari i de atribuire, care se asociaz de la dreapta la stnga.
Operanzii pot fi: constante, constante simbolice, variabile simple sau structurate
(tablouri, structuri, sau elemente ale acestora), funcii sau apeluri de funcii.
3.1. Operatori
Operatorii, n ordinea descresctoare a prioritii sunt urmtorii:


( ) [ ]
(unar) + (unar) * (unar) & (unar) ! ~ ++
(tip) sizeof

* / %
+
<< >>
< <= >= >
= = !=
&
^
|
&&
| |
?: (ternar)
= *= /= %= += = <<= >>= &= ^= |=
,

Operatorii aritmetici sunt urmtorii:
+ , , * , / , % (mod), pentru adunare, scdere, nmulire, ct (mprire), rest.
Exemple:
int i, j ;
int cat = i / j; // 13 / 5 = 2
int rest = i % j; // 13%5 = 3
C
+
+
P
O
O

09.01.12 8
Operatorii relaionali sunt urmtorii:
< , <= , > , >= , == , != , pentru < , e , > , u , = , { , rezultatul (valoarea
expresiei relaionale) fiind 1 pentru adevrat, 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 adevrat
prin orice valoare diferit de 0.
Operaii pe bii se pot realiza utiliznd urmtorii operatori:
~ (complementul fa de FFFF, schimb fiecare bit), << (deplasare la stnga),
>> (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);
}
C
+
+
P
O
O

09.01.12 9
Operaia de atribuire se realizeaz astfel:
Var = Expresie; // expresie de atribuire cu tipul Var
Exist posibilitatea realizrii de atribuiri multiple prin expresii de forma:
Var
n
= ... = Var
2
= Var
1
= Expresie;
Mai exist o facilitate utiliznd o operaie de atribuire de forma:
Var = Expresie; // unde {+, , *, /,%, &, ^, | , <<, >>}
avnd semnificaia:
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*2
k

Operatorii de incrementare / decrementare sunt ++ respectiv prin care se
mrete, respectiv se micoreaz, valoarea operandului cu unu.
Acetia pot fi utilizai:
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=b1;
Operatorul de conversie explicit (expresie cast) realizeaz conversia unui
operand ntr-un tip precizat astfel:
(Ti p) 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
C
+
+
P
O
O

09.01.12 10
Conversiile implicite (realizate automat) se fac astfel:
a) charpint,
b) floatpdouble,
c) (double,*)p(double,double)=double,
d) (long,*)p(long,long)=long,
e) (unsigned,*)p(unsigned,unsigned)=unsigned.
Operatorul pentru dimensiune (sizeof) determin lungimea n octei a unei
variabile simple sau structurate, precum i a unui tip de dat:
si zeof (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 condiionali ? : sunt utilizai n construcii de forma:
Expresie
1
? Expresie
2
: Expresie
3
;
Valoarea expresiei rezultat este Expresie
2
dac Expresie
1
este nenul, altfel este Expresie
3
.
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
avnd valoarea ultimei expresii:
Expresie
1
, Expresie
2
, ... , Expresie
n
;
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");
C
+
+
P
O
O

09.01.12 11
4. Operaii de intrare/ieire
n limbajul C nu exist instruciuni de intrare/ieire, aceste operaii ralizndu-se prin
funcii aflate n bibliotecile standard. Implicit, unui program i se ataeaz fiierele stdin
(intrare standard), stdout (ieire standard), stderr (ieire standard pentru erori), stprn (ieire
pentru imprimant), stdoux (intrare/ieire serial).
4.1. Funcia Printf
Aceast funcie realizeaz afiarea dup un ablon, avnd urmtorul format:
int printf (Control [, List_Expresii]);
unde Control este ablonul (formatul) scris sub forma unui ir de caractere care conine
mesaje i specificatori de format corespunztori valorile expresiilor din list. Un
specificator de format se descrie astfel:
% [] [m[.n] ] [l] [ f ]
unde:
[] - determin alinierea la stnga, implicit fiind la dreapta,
[m] - precizeaz lungimea cmpului,
[.n] - precizeaz lungimea prii zecimale, respectiv numrul de caractere,
[ l ] - conversia se va efectua din format intern long,
[ f ] - determin tipul conversiei precizat prin unul din urmtoarele caractere:
d - int p zecimal extern,
o - int p octal extern,
x - int p hexa extern (0...9,a...f),
X - int p Hexa extern (0...9,A...F),
u - unsigned p zecimal extern (fr semn),
c - binar intern p caracter (char),
s - string (ir de coduri ASCII terminat cu \0=NUL) p ir de caractere,
f - float sau double p zecimal extern [m[.n] ], implicit n=6,
e - float sau double p zecimal extern forma exponenial (b*10
e
),
E - float sau double p zecimal extern forma exponenial (b*10
E
),
g - se alege dintre variantele f sau e reprezentarea minim,
G - se alege dintre variantele f sau E reprezentarea minim.
Funcia printf returneaz numrul de octei afiai dac operaia a decurs corect, iar
n caz contrar -1 (EOF):
if (EOF = = printf (Control , List_Expresii)) ... eroare ... ;
C
+
+
P
O
O

09.01.12 12
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. Funcia Scanf
Aceast funcie realizeaz citirea datelor dup un ablon, avnd urmtorul format:
int scanf (Control , List_Adrese_de_Variabile );
unde Control este ablonul (formatul) scris sub forma unui ir de caractere care conine
eventual texte (obligatorii la intrare) i specificatori de format corespunztori tipurilor
variabilelor din list. Specificatorii de format sunt asemntori celor prezentai la funcia
printf, realiznd ns conversiile inverse: % [*] [m] [l] [ f ] , unde:
[*] - un caracter opional,
[m] - precizeaz lungimea maxim a cmpului,
[ l ] - conversia se va efectua din format intern long,
[ f ] - determin tipul conversiei precizat prin unul din urmtoarele caractere:
d - int n zecimal extern,
o - int n octal extern,
x - int n hexa extern (0...9,a...f),
X - int n Hexa extern (0...9,A...F),
u - unsigned n zecimal extern (fr semn),
c - binar intern n caracter (char),
s - string n ir de caractere terminat la spaiu sau dimensiunea m,
f - float n flotant extern.
Adresele variabilelor de intrare sunt date prin operatorul de adrese & plasat naintea
identificatorului fiecrei 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
Funcia scanf returneaz numrul de cmpuri citite corect. Sfritul de fiier
(Ctrl/Z) poate fi verificat prin valoarea returnat EOF:
if (EOF = = scanf (Control , List_Expresii)) ... Sfrit ... ;
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); }
C
+
+
P
O
O

09.01.12 13
4.3. Funcia PutChar
Aceast funcie realizeaz tiprirea unui caracter al crui cod ASCII este precizat
printr-o expresie:
putchar (Expresie);
4.4. Funcia GetChar
Aceasta, returneaz codul ASCII al caracterului citit (pentru Ctrl/Z p EOF=-1):
getchar ( );
Exemplu:
char c;
do putchar (((c=getchar())>'Z')? c^' ' : c); // Litere mici p LITERE MARI
while (c!='.'); // se termin cu .
q
Litere mici in Litere MARI ! p getchar
LITERE MICI IN LITERE MARI ! putchar n
Se termina la . (Punct) p getchar
SE TERMINA LA . putchar n
4.5. Funcia GetChe
Funcia returneaz codul caracterului citit direct i l afieaz (n ecou):
int getche ( );
Exemplu:
do putchar (((c=getche())>'Z')? c^' ' : c); while (c!='.'); // se termin cu .
q
LLiIt TeErReE mMiIcCiI iInN LLiIt TeErReE MMAARRII. .
4.6. Funcia GetCh
Aceast funcie returneaz codul caracterului citit (direct) fr ca acesta s mai fie
afiat:
int getch ( );
Exemplu:
do putchar (((c=getch())>'Z')? c^' ' : c); while (c!='.'); // se termin cu .
q
LITERE MICI IN LITERE MARI. // S-a tastat: Litere mici in Litere MARI.
C
+
+
P
O
O

09.01.12 14
5. Instruciuni
n limbajul C instruciunile se termin cu ; mai puin cele care se termin cu }.
5.1. Instruciunea Vid
Aceast instruciune se utilizeaz n situaia n care este nescerar prezena unei
instruciuni i care nu trebuie s execute nimic:
;
5.2. Instruciunea Expresie
Instruciunea are formatul general:
Expresie ;
Exemple:
y = (x+1)*(x-1); // Atribuire: v=Expresie;
f(x,y); // Apel de funcie: f(p
1
, p
2,
...
,
p
n
);
c++; --c; // Incrementri/Decrementri (Pre/Post fixate)
5.3. Instruciunea Compus
Aceasta este format dintr-o succesiune de declaraii (proprii) i instruciuni, incluse
ntre acolade:
{
Declaraii
Instruciuni
}
Exemplu:
{
int i; // Variabil local instruciunii;

f (i); // i se poate utiliza doar n aceast instruciune compus;
}
-
; // Dup } nu se pune ;


C
+
+
P
O
O

09.01.12 15
5.4. Instruciunea If
Structura alternativ cu una sau dou ramuri poate fi scris astfel:
if (expresie) instructiune
1
;
[ else instructiune
2
; ]
Exemplu:
{ P(x,y) p 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; // C
4
else_; (instruciunea vid)
else { x=-x; // C
2
sau C
3
(x)
if (y<0) y=-y; // C
3
(y)
}
printf(" x=%5.2f, y=%5.2f \n", x,y) ;
} // trebuie pus pentru C
1
instruciunea vid: else_;

5.5. Instruciunea Switch
Pentru structura alternativ cu mai multe ramuri Case (Select) se utilizeaz
instruciunea Switch:
switch (expresie)
{ case c
1
: secven instructiuni
1
[ break; ]
case c
2
: secven instructiuni
2
[ break; ]
...
case c
n
: secven instructiuni
n
[ break; ]
[ default : secven instructiuni
n+1
]
}
Instruciunea break realizeaz saltul la sfritul instruciunii switch, iar n absena ei
se vor executa i urmtoarele secvene de instruciuni.
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
C
+
+
P
O
O

09.01.12 16
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. Instruciunea While
Structura repetitiv pretestat poate fi scris astfel:
while (expresie) instructiune;
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. Instruciunea Do_While
Structura repetitiv posttestat poate fi scris astfel:
do instructiune while (expresie);
Exemplu:
do { r=a%b; a=b; b=r; } while (c); // c!=0
cmmdc=a;
C
+
+
P
O
O

09.01.12 17
5.8. Instruciunea For
Structura repetitiv Pentru (
!
) poate fi descris astfel:
for (expresie
1
; expresie
2
; expresie
3
) instructiune ;
Instruciunea are acelai efect ca i:
expresie
1
; while (expresie
2
) { instructiune; expresie
3
; }
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. Instruciunea Break
Aceast instruciune se folosete pentru a termina o structur repetitiv:
break;
Exemplu:
for ( ; ; ) { ...
if (expr) break;
... }
5.10. Instruciunea Continue
Aceast instruciune realizeaz saltul la sfritul unei structuri repetitive (pentru
while sau do_while la reevaluarea expresiei, iar pentru for la expresie
3
), avnd formatul:
continue;
Exemplu:
for (... ;... ; expr
3
) { ...
if (expr) continue;
... }
5.11. Instruciunea GoTo
Aceast instruciune realizeaz saltul necondiionat i fr revenire la instruciunea
ce poart eticheta specificat, avnd formatul:
goto etichet ;
Exemplu:
while (expr1) { ...
C
+
+
P
O
O

09.01.12 18
if (expr2) goto et;
... }
...
et: ... // instruciune
5.12. Apelul unei funcii
Instruciunea de apel a unei funcii este un caz particular al instruciunii expresie:
Nume_funcie (List_parametri_actuali);
O funcie poate fi apelat i n cadrul unei expresii dintr-o instruciune:
... Nume_funcie (List_parametri_ actuali) ... ;
O funcie poate fi utilizat doar dac a fost definit sau cel puin a fost declarat
prototipul ei ntr-una din urmtoarele moduri:
a) Tip_ funcie Nume_ funcie (Lista_parametrilor_formali);
b) Tip_ funcie Nume_ funcie (Lista_tipurilor_parametrilor_formali);
c) Tip_ funcie Nume_ funcie (Void); // nu sunt parametri formali
d) Tip_ funcie Nume_ funcie ( ); // nu se fac verificrile de tip
Apelul implicit pentru variabile simple (de baz) este prin valoare, iar pentru
tablouri prin referin. Apelul prin referin se obine prin intermediul variabilelor de tip
pointer i a operatorului de adres &.
Revenirea dintr-o funcie se poate realiza fie prin instruciunea return, fie automat
dup ultima instruciune a funciei (situaie 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:
/ / Ult ima cifr nenul a lui n! \ \
#include <iostream.h>;
#include <conio.h>;
int Sf (int& f, int k)
C
+
+
P
O
O

09.01.12 19
{ 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. AB, AB \ \
#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();
}
C
+
+
P
O
O

09.01.12 20
6. Pointeri
O variabil p de tip pointer conine adresa unei variabile a crei valoare se obine
utiliznd operatorul * (*p = valoarea variabilei de la adresa coninut n p).
Adresa unei variabile v se poate obine 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 obine prin urmtoarea construcie:
Tip *
Declararea unui pointer (care conine 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. Operaii cu Pointeri
Aceste operaii sunt operaii cu adresele coninute n variabilele de tip pointer.
C
+
+
P
O
O

09.01.12 21
6.2.1. Incrementare / Decrementare
Aceste operaii mresc/miocoreaz valoarea de adres spre urmtorul 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 / Scdere a unui numr ntreg
Aceste operaii mresc/miocoreaz 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 aceluiai tablou pot fi comparai utiliznd operatorii
relaionali. Valoarea NULL marcheaz faptul c un pointer nu refer nici un element.
... p
1
< p
2
... ; ... p
1
=

= p
2
... ; ... p
1
!= p
2
... ; ... 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
Diferena a doi pointeri ai aceluiai tablou d ca rezultat diferena 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 cta 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,lunaZile,An);
C
+
+
P
O
O

09.01.12 22
Exemplu:
/ / Opera ii cu point eri \ \
#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 urmtoarele dou
funcii definite n fiierele 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 funcii
C
+
+
P
O
O

09.01.12 23
Numele unei funcii fiind un pointer la acea funcie, ea poate fi parametru actual, i
evident trebuie descris ca parametru formal:
... tip (*f ) ( ), ...
Exemplu:
/ / Poi nt eri l a f unc i i (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();
}
Urmtorul exemplu construiete un tabel cu valorile a patru funcii dintr-un interval
dat [a,b] pentru o diviziune precizat (n):

/ / Poi nt eri l a f unc i i (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();
}
C
+
+
P
O
O

09.01.12 24
6.5. Utilizarea parametrilor din linia de comand
Apelul unui program poate fi nsoit de o list de parametri:
> Nume_Program List_Parametri
care se poate accesa scriind antetul funciei principale astfel:
main ( int ArgC, char *ArgV [ ] )
unde:
ArgC este o variabil ntreag care conine numrul de parametri plus unu (!),
ArgV este un tablou care conine 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 const 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. St i va
C
+
+
P
O
O

09.01.12 25
Prin stiv nelegem o list cu disciplina Last In First Out pentru care vom defini
urmtoarele trei funcii:
Push - adaug un element n stiv,
Pop - extrage un element din stiv,
Clear - iniializarea stivei (stiv vid),
Vida - verific dac stiva este vid:
// Fact.Cpp \\
#include <stdio.h>
#include <conio.h>
#include "Stiva.h"
void main(void)
{
int n; unsigned long f;
printf(" Dati n : "); scanf("%d",&n);
Clear(); while (n) Push(n--);
f=1; while (!Vida()) f*=Pop();
printf(" n! = %15lu \n",f);
getch();
}

// Stiva.h \\
#define DimMax 13
static int Stiva[DimMax]; static Next=0;
void Push(int x)
{
if (Next<DimMax) Stiva[Next++]=x;
else printf(" Depasire stiva \n");
}
int Pop()
{ if (Next>0) return Stiva[--Next];
else { printf(" Stiva vida \n"); return 0; }
}
void Clear() { Next=0; }
int Vida() { return (Next= =0); }


7. Recursiviate
Exist posibilitatea de a defini o funcie prin ea nsi (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();
}
C
+
+
P
O
O

09.01.12 26
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] { Id
0
[=Expr
0
], Id
1
[=Expr
1
],..., Id
n
[=Expr
n
] } [List_Var];
Implicit Expr
0
=0, iar Expr
i
=Expr
i-1
+1, iar dac se declar o list de variabile
avnd 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();
}


C
+
+
P
O
O

09.01.12 27
8.3. Definirea unei structuri (struct)
Definirea unei structuri (nregistrri) se face astfel:
struct [Denumire] { List_Declaraii_Cmpuri } [List_Var];
Dac se declar o list de variabile avnd 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); }

C
+
+
P
O
O

09.01.12 28
8.4. Redefinirea unei date (union)
Redefinirea unei zone de memorie se poate face n cadrul unei uniuni astfel:
union [Denumire] { List_Declaraii } [List_Var];
Toate componentele aflate n List_Declaraii ocum aceeai zon de memorie (se
suprapun), lungimea uniunii fiind dat de maximul lungimilor declaraiilor .
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. Cmpuri de biti
Exist posibilitatea definirii unei structuri ale crei cmpuri s fie formate dintr-o
secven de bii consecutivi (ai unui cuvnt). Aceste cmpuri au tipul unsigned avnd
fiecare o lungime precizat (n numr de bii):
struct [Denumire] { Cmp
0
; Cmp
1
; ... ; Cmp
n
; } [List_Var];
unde cmpurile Cmp
i
sunt de forma:
unsigned

[ Nume_Cmp
i
] : Lungime
i

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);
}

C
+
+
P
O
O

09.01.12 29
9. Structuri de date dinamice
Pentru a implementa structura liniar (lista simplu nlnuit) i structura de tip
arbore binar vom apela la structuri definite recursiv.
9.1. List simplu nlnuit ordonat
Considerm o list nevid fiind format din primul element i sublista aflat la adresa
de legtur memorat n fiecare element pe lng informaia propriuzs.
n exemplul urmtor vom crea o list care va conine monoamele unui polinom n
ordinea descresctoare a gradelor. Un element din list va conine pe lng informaia
propriuzis (coeficientul i gradul monomului) i adresa urmtorului monom (adresa
sublistei). De exemplu, pentru polinomul P(x)=120x
12
+77x
7
+130x
3
+22x
2
lista va conine
patru elemente avnd informaiile (20,12); (77,7); (130,3); (22,2), indiferent de ordinea
introducerii monoamelor. Deoarece coeficienii 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 decresctor 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

C
+
+
P
O
O

09.01.12 30
Exemplu:
// List simpl ordonat cresctor \\
#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
Considerm c un arbore binar nevid este format din rdcin, subarbore stng 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();
}

C
+
+
P
O
O

09.01.12 31
n exemplul urmtor se citeste un arbore genealogic ascendent (dnd pentru fiecare
persoan nume prinilor), apoi se va reprezenta grafic arborele construit ntr-o fereastr
ecran precizat (u
1
,v
1
,u
2
,v
2
). Distana dintre dou nivele se calculeaz innd cont de
adncimea 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();
}

C
+
+
P
O
O

09.01.12 32
10. Utilizarea fiierelor
Prelucrarea fiierelor se poate efectua la dou nivele:
Nivelul inferior - face apel direct la sistemul de operare;
Nivelul superior - utilizeaz proceduri speciale pentru operaii de intrare/ieire.
10.1. Nivelul inferior
Prelucrrile la acest nivel permit urmtoarele cinci operaii:
10.1.1. Deschiderea unui fiier (Open/Creat)
int open ( const char * cal e, int acces ) ;
unde:
cal e - este specificatorul de fiier,
acces - poate fi o combinaie (utiliznd operatorul |) a urmtoarelor valori:
O_RDONLY (fiier deschis numai pentru citire), O_WRONLY sau O_CREAT (numai
pentru scriere - creare), O_RDWR (citire/scriere), O_APPEND (deschis pentru
adugare la sfrit), O_BINARY (pentru prelucrare binar), O_TEXT (pentru fiier de
tip text).
Dac deschiderea fiierului s-a realizat corect, atunci funcia returneaz o valoare
ntreag reprezentnd descriptorul de fiier (LUN, care va fi utilizat n continuare la celelelte
operaii efectuate asupra acestui fiier), iar n caz de nereuit se va returna valoarea -1.
Pentru a putea utiliza funcia Open trebuie incluse fiierele header io.h i fcntl.h.
Exemplu:
...
int Lun;
Lun = open (Fisier.Dat,ORDONLY);
...
Pentru crearea unui fiier se va apela funcia Creat:
int creat ( const char * cal e, int mod ) ;
unde:
mod - poate lua una dintre valorile: S_IREAD (fiierul se poate citi), S_IWRITE
(scriere n fiier), S_IEXEC (execuia programului din fiierul specificat).
Pentru a putea utiliza funcia Creat trebuie incluse fiierele io.h i stat.h.
Fiierele text sunt implicite.
C
+
+
P
O
O

09.01.12 33
10.1.2. Citirea dintr-un fiier (Read)
int read ( int Lun, void *buffer, unsigned lung ) ;
unde:
Lun - este descriptorul definit la deschidere (0=STDIN, 1=STDOUT, 2=STDERR,
3=STDPRN, 4=STDAUX),
buffer - este zona de memorie n care se citete,
l ung - este lungimea (n octei) a nregistrrii citite.
Funcia returneaz numrul de octei citii (cel mult l ung), 0 la sfrit, sau -1 n caz
de eroare. Automat, dup o citire (a articolului curent) se trece la urmtorul articol, implicit
prima poziionare fiind la nceput de fiier (acces secvenial).
Pentru a utiliza funciile Read, Write, LSeek sau Close trebuie inclus fiierul io.h.
10.1.3. Scrierea ntr-un fiier (Write)
int write ( int Lun, void *buffer, unsigned lung ) ;
Funcia returneaz numrul de octei scrii n fiier, reprezentnd lungimea
articolului = l ung, sau -1 n caz de eroare.
10.1.4. Poziionarea ntr-un fiier (LSeek)
Aceast funcie permite accesul aleator printr-un apel de forma:
long lseek ( int Lun, long *deplasament , int origine ) ;
unde:
deplasament - reprezint numrul de octei peste care se deplaseaz capul de
citire/scriere,
origine - reprezint punctul din care se msoar deplasament -ul (0=nceputul
fiierului, 1=poziia curent, 2=sfritul fiierului).
Funcia returneaz poziia curent fa de nceputul fiierului, sau -1 la eroare.
10.1.5. nchiderea unui fiier (Close)
int close ( int Lun) ;
Funcia returneaz 0 la o nchidere corect, sau -1 la eroare.
10.1.6. Stergerea unui fiier (UnLink)
int unlink (const char * cal e) ;
Funcia returneaz 0 la o tergere corect, sau -1 la eroare.
C
+
+
P
O
O

09.01.12 34
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();
}
C
+
+
P
O
O

09.01.12 35
10.2. Nivelul superior
La acest nivel sunt posibile urmtoarele operaii:
10.2.1. Deschiderea unui fiier (FOpen)
FILE * fopen ( const char * cal e, const char * mod ) ;
unde:
mod - poate fi r pentru deschidere n citire, w pentru scriere, a pentru
adugare, r+ pentru modificare (citire/scriere), rb pentru citire binar, wb
pentru scriere binar, sau r+b pentru citire/scriere binar.
Dac la deschiderea fiierului s-a ales modul w sau a, fiierul va fi creat (recreat).
Funcia returneaz un pointer spre tipul FILE definit n fiierul stdio.h, iar n caz de
nereuit se va returna valoarea NULL (stdin, stdout, stderr, stdaux i stdprn sunt pointeri
spre tipul FILE permind transferuri fr a fi necesar deschiderea sau nchiderea lor).
Exemplu:
...
FILE * Pf;
Pf = fopen (Fisier.Dat,w);
...

10.2.2. Prelucrarea pe caractere a unui fiier (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.
Funcia returneaz valoarea lui c sau -1 la eroare.
int getc (FILE * Pf ) ;
Funcia returneaz codul caracterului citit, sau valoarea EOF la sfritul fiierului,
sau -1 la eroare.
Exemplu:
#include <stdio.h>
void main (void)
{ int c;
while ((c=getc(stdin))!=EOF) putc(c,stdout);
}
C
+
+
P
O
O

09.01.12 36
10.2.3. nchiderea unui fiier (FClose)
int fclose ( FILE * Pf ) ;
Funcia returneaz 0 la nchiderea corect a fiierului 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 aceeai semnificaie ca i pentru funcia scanf.
Funcia returneaz numrul de cmpuri citite sau EOF.
int fprintf ( FILE * Pf , control, list_expresii) ;
Funcia returneaz numrul de caractere scrise n fiier sau -1 la eroare.
Ex.1:
// Creare fiier 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 fiier 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();
}



// Listare fiier text \\
C
+
+
P
O
O

09.01.12 37
#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. Intrri/Ieiri de iruri de caractere (FGetS, FPutS)
char * fgets ( char *s, int n, FILE * Pf ) ;
unde:
s - zona receptoare (tablou de tip char de dimensiune e n, terminat cu NUL=\0),
n-1 - numr maxim de caractere (n-1),
Funcia returneaz adresa irului s, sau la EOF returneaz NULL.
int fputs ( char *s, FILE * Pf ) ;
Funcia returneaz codul ultimului caracter scris sau -1 la eroare.
Urmtorul program nlocuiete cuvintele din fiierul F_Niv_S.Cpp aflate n partea
stng a dicionarului Dicio.Txt cu cele corespunztoare din partea dreapt, rezultatul fiind
depus n fiierul F_Niv_S.Pas, aa cum se poate vedea n schema de mai jos.
Fin_Niv_S.Cpp Dictio.Txt
Fin_Niv_S.Pas
Traduce

C
+
+
P
O
O

09.01.12 38

// Traduce Fiier 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. Poziionarea ntr-un fiier (FSeek, FTell)
int fseek (FILE * Pf, long deplasamnet , int origine ) ;
C
+
+
P
O
O

09.01.12 39
unde deplasamnet i origine au aceeai semnificaie ca i la funcia lseek.
Funcia fseek returneaz 0 la poziionare corect sau o valoare {0 la eroare.
long ftell ( FILE * Pf );
Funcia ftell returneaz poziia curent (fa de nceputul fiierului, n octei).
10.2.7. Prelucrarea fiierelor 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 numrul de articole care se transfer (citesc),
unsigned fwrite (const void *Pzt , unsigned dim, unsigned nrart , FILE * Pf) ;
Ambele funcii returneaz numrul 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);
}
C
+
+
P
O
O

09.01.12 40
11. Funcii standard
11.1. Macrouri de clasificare
Macrourile din aceast categorie (aflate n fiierul ctype.h) verific dac un caracter
este de un anumit tip:

int isascii (int car ); car [0,127] ?
int isalpha (int car ); car este codul unui caracter alfanumeric ?
int isalnum (int car ); car este codul unei litere ?
int isupper (int car ); car este codul unei litere mari ?
int islower (int car ); car este codul unei litere mici ?
int isdigit (int car ); car este codul unei cifre zecimale ?
int isxdigit (int car ); car este codul unei cifre hexa ?
int isgraph (int car ); car este codul unui caracter afiabil ?
int isprint (int car ); car este codul unui caracter imprimabil ?
int isspace (int car ); car este spaiu, tab, Cr, Lf, Vt sau Np ?
11.2. Macrouri de transformare a simbolurilor
Macrourile din aceast clas (aflate n fiierul ctype.h) transform un caracter astfel:

int toascii (int car ); car p [0,127] (returneaz ultimii 7 bii)
int toupper (int car ); car p liter mare (transform din l n L)
int tolower (int car ); car p liter mic (transform din L n l)
11.3. Conversii
Funciile care urmeaz (aflate n fiierul stdlib.h) realizeaz conversii far format.

Format i nt ern n Format (zeci mal ) ext ern
int atoi (const char *pt r ); binar (i nt ) n zeci mal ext ern
long atol (const char *pt r ); binar (l ong) n zeci mal ext ern
double atof (const char *pt r ); virgul flotant (dubl precizie) n zeci mal ext ern
Format ext ern n Format i nt ern
char *itoa (int v, char *s, int b); s n v
b
(valoarea v de tip int, scris n baza b)
char *ltoa (long v, char *s, int b); s n v
b
(valoarea v de tip long scris n baza b)
C
+
+
P
O
O

09.01.12 41
11.4. Funcii de prelucrare a irurilor de caractere
Funciile din aceast categorie se afl n fiierul string.h.
11.4.1. Copiere (Str[n]Cpy)
char * str[n]cpy (char *dest ina ie, const char *sursa [, unsigned n]) ;
unde sursa este copiat n dest ina ie, eventual doar primii n octei (cel mult n).
11.4.2. Concatenare (Str[n]Cat)
char * str[n]cat (char *dest ina ie, const char *sursa [, unsigned n]) ;
unde sursa este copiat la sfritul dest ina iei, eventual doar primii n octei 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 ir
2
(eventual doar primii n octei, i eventual ignornd diferena
dintre literele mari i cele mici), iar rezultatul comparrii este un numr negativ dac
ir
1
<ir
2
, este un numr pozitiv dac ir
1
>ir
2
sau zero dac ir
1
=ir
2
.
11.4.4. Lungimea unui ir (StrLen)
unsigned strlen (char *ir) ;
returneaz lungimea irului (de caractere, fr caracterul NUL care l termin).
11.5. Funcii de calcul
Aceste funcii se afl n fiierul math.h (abs i labs i n stdlib.h *):

Prototip
Semnificaie 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); x
y

double sqrt (double x); . x double cabs (struct complex z); |z|
double exp (double x); e
x
double poly (double x, int n, double a[ ] ); P(x)

11.6. Funcii pentru controlul proceselor
Urmtoarele funcii se afl n fiierele stdlib.h i process.h .

C
+
+
P
O
O

09.01.12 42
Prot ot i p Semni fi ca i e
void abort (void); termin un program la eroare
void exit (int cod_retur); termin un program returnnd un cod de retur
int system (const char *comand); execut o comand i returneaz cod_retur (0=Ok).
11.7. Funcii pentru timp
Aceste funcii se refer la dat i or, i sunt definite n fiierul dos.h mpreun cu
urmtoarele dou tipuri:

struct date {
int da_year;
int da_day;
int da_mon;
}
struct time {
unsigned char ti_min;
unsigned char ti_hour;
unsigned char ti_hund;
unsigned char ti_sec;
}

Semni fi ca i e Prot ot i p
Citete Data curent : void getdate (struct date *Data);
Modific Data curent : void setdate (const struct date *Data);
Citete 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. Funcii diverse
Aceste funcii sunt definite n fiierul conio.h:

Prototip Semnificaie
p
3. void sleep (unsigned sec);
Wait (sec)
1. void clrscr (double x);
Clear Screen T
4. void sound (unsigned Hz);
Sound (Fr)
2. void delay (unsigned ms);
Wait (ms) p
5. void nosound (void );
NoSound
C
+
+
P
O
O

09.01.12 43
12. Ecranul n mod text
Exist posibilitatea de a defini urmtoarele 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) ;
Poziionarea cursorului:
void gotoxy ( int x, int y) ; // col, lin
Poziia cursorului:
int wherex ( void ) ; // col

int wherey ( void) ; // lin
Un caracter poate fi afiat pe ecran clipitor (BLINK=1), pe o culoare de fond (0-7)
i ntr-o anumit culoare de scriere (0-15), culorile posibile fiind urmtoarele:
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 funcia:
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:
C
+
+
P
O
O

09.01.12 44
void far initgraph ( int far *graphdriver, int far *graphmode, char far *path) ;
Ieirea 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 funcii:
Semni fi ca i e Func i i
Numr 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 (x
1
,y
1
, x
2
,y
2
);
Deseneaz dreptunghi rectangle (x
1
,y
1
, x
2
,y
2
);
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 suprafee \\
#include "graf.h"
#i ncl ude <st dl i b. h> #i ncl ude <st di o. h> #i ncl ude <coni o. h> #i ncl ude <mat 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;
};

C
+
+
P
O
O

09.01.12 45
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>
C
+
+
P
O
O

09.01.12 46
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); }


C
+
+
P
O
O

09.01.12 47
14. Faciliti C++
Limbajul C++ ofer n plus fa de limbajul C unele faciliti noi. Un avantaj
important l constituie noiunea de clas (prin care se definete 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 declaraiile erau scrise nainte de instruciuni, n C++ ele pot fi
scrise oriunde.
Dispozitivelor standard de intrare-ieire li s-au ataat streamurile standard cin
(pentru stdin) i respectiv cout (pentru stdout), care permit efectuarea operaiilor de intrare-
ieire aplicnd operatorul >> streamului cin, respectiv << streamului cout. Ierarhiile
necesare sunt n fiierul 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; // Coninutul adresei
getch(); // la care se afl un ntreg
}
C
+
+
P
O
O

09.01.12 48
14.2. Operatori
14.2.1. Operatorul de rezoluie (::)
Acest operator (::) se utilizeaz cnd dorim s referim o variabil global redefinit
ntr-o funcie, 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-
declaraie de forma tip & (asemntor cu o construcie de forma tip
*
, pentru pointer).
Cu ajutorul acestui operator putem redenumi o variabil, putem realiza un apel prin referin
sau putem s declarm o variabil de referin astfel:
tip & parametru_formal // par. ref. (adres)

tip & nume_var_ref ; // var. de tip referin
C
+
+
P
O
O

09.01.12 49
Exemple:
#include <conio.h>; / / Redefi ni rea unei vari abi l e
#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>; / / Redefi ni rea unei func i i
#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 pri n Referi n
#include <iostream.h>;
void suma (int x,int y,int *z) / / x, y p z
{ *z = ++x * ++y; }
void Suma (int x,int y,int &z) / / x, y p 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 urmtoarele trei variante:
new tip

new tip ( Valoare_de_intiializare_a_variabilei_dinamice )

new tip [ Numrul_de_variabile_dinamice_alocate ]
Dealocarea se realizeaz astfel:
delete Variabil_de_referin ;
sau
delete [ Numrul_de_var_dinamice_alocate ] Variabil_de_referin ;
Exemplu:
#include <stdio.h>; #include <conio.h>; #include <iostream.h>;
void main (void)
C
+
+
P
O
O

09.01.12 50
{
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 urmtor se va utiliza o matrice A cu numr variabil de coloane i o
matrice B utiliznd 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();
} // Re z u l t at 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

C
+
+
P
O
O

09.01.12 51
14.3. Structur, uniune i enumerare
Referirea acestor tipuri se poate face n C++ fr a mai fi nevoie de cuvntul
corespunztor struct, union, respectiv enum. De asemenea, parametrii i valoarea unei
funcii pot fi structuri, pointeri la structuri sau referine 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 iniializa.
n C++, variabilelor de tip enumerare nu se mai pot atribui dect 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();
}

C
+
+
P
O
O

09.01.12 52

// 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();
}
C
+
+
P
O
O

09.01.12 53
15. Funcii C++
15.1. Funcii 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, fr a face
verificri de tipuri, ceea ce poate conduce la erori.
Aceste erori pot fi eliminate dac utilizm funciile inline, caz n care se vor face
conversiile de tip necesare. Aceste funcii se declar prin scrierea cuvntului inline la
nceputul antetului, aa cum se pate vedea n exemplele urmtoare:
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
C
+
+
P
O
O

09.01.12 54
15.2. Funcii de tip referin
Antetul unei funcii cu valoare de tip referin este:
tip & nume
f
( 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 urmtorul exemplu se dorete 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(); }

C
+
+
P
O
O

09.01.12 55
/ / Ex. Ref er i n \ \
#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();
} // Rez ul t at 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)
C
+
+
P
O
O

09.01.12 56
15.3. Suprancrcarea funciilor
Aceast proprietate d posibilitatea utilizrii unor funcii avnd acelai 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();
}

C
+
+
P
O
O

09.01.12 57
15.4. Iniializarea parametrilor formali
Parametrii formali pot avea o valoare implicit, dac acetia lipsesc din lista
parametrilor actuali, valoare dat de o expresie. n lista parametrilor formali, cei cu valoare
implicit (iniializai) 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 R
2
(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 implicii
pentru a declara punctul O(0,0), un punct A pe axa Ox, un punct P n plan (R
2
), un cerc C
(n plan), extremitile unui segment din spaiu (Q,RR
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;
}
C
+
+
P
O
O

09.01.12 58
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. Funcii membru pentru Structuri
Acestea se declar n cadrul structurii ca fincii inline sau prototipuri (urmnd
n acest caz descrierea lor cu ajutorul operatorului de rezoluie (::).
// 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 \\
C
+
+
P
O
O

09.01.12 59
#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. Ti p Abs t ract de Dat
Programarea modular permite protejarea datelor prin memorie static, (accesul la
date se poate efectua doar din locul declarrii pn la sfritul modulului, nu i n afara lui).
Un tip abstract de dat (Domeniu, Operaii) conine 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, aa cum se poate vedea n schema de
mai jos:
Program.Exe Tad.h
Program.Cpp
Tad.Cpp
Program.Obj
Program.Obj
Compilare
Compilare
Link-editare

n proiect (meniul Project) vor fi incluse fiierele Program.Cpp i Tad.Cpp.
C
+
+
P
O
O

09.01.12 60
n exemplul urmtor, pentru Tad Mulime, fiierele 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 mulimii
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];
};
C
+
+
P
O
O

09.01.12 61
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);
}
C
+
+
P
O
O

09.01.12 62
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 mulimii


Un tip abstract de dat realizeaz o unificare (printr-o grupare de tip struct) ntre
date (date membru) i operaiile (funcii membru) lor caracteristice. Funciile membru sunt
considerate de tip inline iar definirea lor n afara structurii se face prin operatorul de
rezoluie (::). n acest mod ns nu se realizeaz o protecie a datelor (accesul la date se
poate face i prin alte funcii, nu numai prin cele membru), aceast protecie putnd fi
realizat (aa 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();
}

C
+
+
P
O
O

09.01.12 63
17. Programare orientat obiect (OOP)
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 motenire.
Un limbaj este orientat obiect dac:
a) Utilizeaz obiecte,
b) Oblig obiectele s aparin unei clase,
c) Permite motenirea.
Limbajul C++ ofer noiunea de clas, prin care se pot forma ierarhii, deci putem
vorbi de o programare orientat obiect (OOP).
OOP nseamn realizarea unor programe alctuite dintr-o mulime de obiecte care
interacioneaz pentru a rezolva problema propus, i permite reutilizarea elementelor
descrise (a interfeei i a codului).
Un obiect are o stare i un comportament (operaii descrise n interfaa obiectului)
aceste dou componente fiind definite prin datele membru (variabile de instan) i
respectiv prin funciile membru (metode).
OOP utilizeaz ormtoarele concepte:
v c l a s a - implementarea unui TAD,
v o b i e c t u l - instana unei clase,
v me t o d a - mesajul prin care se asigur interfaa (operaiile).
OOP are urmtoarele caracteristici (proprieti) de baz:
v ncapsularea

- gruparea datelor i a operaiilor definite pentru acestea, precum i protecia
acestor date (ele neputnd fi accesate dect prin funciile membru).
v motenirea

- pstrarea elementelor (date i funcii ale) unei clase (de baz), cu definirea
de noi elemente construind o nou clas (derivat), formnd n felul acesta
ierarhii de clase. Motenirea poate fi i multipl dac o clas motenete
mai multe clase.
v polimorfism

- redefinirea (suprancrcarea) operaiilor (funciilor). ntr-o ierarhie pot fi
mai multe funcii cu acelai nume, deci va fi efectuat operaia
corespunztoare obiectului care o apeleaz. Determinarea operaiei se
poate face la compilare (legare static) sau la execuie (legare dinamic,
prin funcii vituale).

C
+
+
P
O
O

09.01.12 64
17.1. Definirea Claselor
O clas se declar ca i o structur, nlocuind cuvntul struct cu class. Protecia
datelor se definete scriind modificatorul dorit (private, protected sau public) urmat de :.
Descrierea unei clase conine att datele membru (variabilele de instan) ct i
funciile membru (metodele), preciznd pentru acestea gradul de protecie, astfel:
cl ass Nume_clas {
{ [ Modificator_de_protecie: ] List_membrii }
};
unde:
v Modificator_de_protecie { private, protected, public} , private fiind implicit,
v private nu permite accesul din afara clasei,
v protected permite accesul din clasele derivate, #
v public permite accesul din afara clasei; +
v List_membrii { List_declaraii_date_membru, List_ declaraii _funcii_membru }
Datele de tip private () pot fi accesate doar de funciile membru sau funcii prietene
(friend). O funcie membru a unei clase poate fi funcie prieten a altei clase, iar dac toate
sunt prietene, atunci se poate declara clas prieten (friend). // Vezi C8
Fiecare obiect al unei clase deine un set de date membru (variabile de instan).
Funciile membru publice pot fi utilizate din orice funcie din program, pe cnd cele
private doar din funciile membru ale clasei.
Definirea funciilor membru (metodelor) se poate realiza:
a) imediat (complet, antet plus corp) n definiia clasei (ca funcie inline) dac funcia nu
conine multe instruciuni i nu conine structuri repetitive (apelul nu se face prin salt cu
revenire), astfel:
cl ass Nume_clas {
Tip_funcie Nume_metod ( ... ) { . . . }; // antet+corp

};
b) ulterior (dac a fost declarat n definiia clasei doar prototipul funciei), utiliznd
operatorul de rezoluie (de scop) astfel:
Tip_funcie Nume_clas :: Nume_metod ( ... ) // :: operatorul de rezoluie
{ . . . }; // corpul funciei
C
+
+
P
O
O

09.01.12 65
Exemplu:
// C l a s a P u n c t \\
// ----------------------------- \\
# 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
aparine unei singure clase (aceasta putnd avea mai multe obiecte).
Obiectele unei clase se declar astfel:
Clas List_Obiecte;
Exemplu:
// Obiecte P u n c t \\
// ----------------------------- \\
# 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();
}
C
+
+
P
O
O

09.01.12 66
Alocarea (i iniializarea) obiectelor se face cu o funcie membru specific numit
constructor (cu numele Clas) iar dealocarea cu o funcie 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();
}

C
+
+
P
O
O

09.01.12 67
Componentele claselor (datele i funciile membru) se refer prin operatorul - sau
ca i n cazul unei structuri. Funciile membru refer direct componentele clasei (fr aceti
operatori, utiliznd 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();
}
C
+
+
P
O
O

09.01.12 68
17.2. Constructori i Destructori
Un obiect este creat de un constructor al clasei i este ters (distrus) de ctre
destructor.
Constructorii permit iniializarea obiectelor cu (mai multe) funcii membru omonime
(avnd acelai nume cu clasa i care difer prin lista parametrilor formali), fr a returna o
valoare. Constructorul este apelat automat la crearea unui obiect. O clas trebuie s
conin cel puin doi constructori:
v un constructor implicit (fr parametri, care iniializeaz obiectele cu o valoare
implicit),
v un constructor de copiere (care iniializeaz cu valoarea unui obiect existent, de acelai
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();
}

C
+
+
P
O
O

09.01.12 69
Antetul unui constructor al unei clase ce conine ca date membru obiecte alte altor
clase este de forma:
Clas (List_par_formali) : Obiect
1
(List_par_formali
1
),...,Obiect
n
(List_par_formali
n
)
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 sfritul
programului, iar a celor locale la sfritul funciei. 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 afiate:
Alocare ...
C(1,2,3)
Dealocare...

C
+
+
P
O
O

09.01.12 70
n exemplul urmtor se poate urmrii momentul n care acioneaz constructorul i
destrucorul:

/ / Obiecte alocate dinamic (operatorul del et 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 afiate:
Constr.Ob. ...123
*Start*
Constr.Ob. ...456
Constr.Ob. ...789
... f(x) ...
... Distr.Ob. 789
*Stop*
... Distr.Ob. 456
... Distr.Ob. 123

C
+
+
P
O
O

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

UML specific entitile (clasele) dintr-un program i relaiile dintre ele astfel:
v Specificarea entitilor :
numele clasei,
date membru - protecie nume_dat : tip
funcii membru - protecie nume_funcie (tip par.formali) : tip_funcie
( protecie poate fi (private), # (protected) sau + (public) ).







v Specificarea relaiilor dintre clase :
relaia de asociere :

// prietenie
relaia de derivare :


// motenire














Punct
- x : float
- y : float
+ Punct ( )
+ Punct (Punct&)
+~Punct ( )

numele clasei
date membru
funcii membru

Exemplu:
Punct
- x : float
- y : float
+ Punct ( )
+ Punct (Punct&)
+~Punct ( )

Segment
- A : Punct
- B : Punct
+ Segment ( )
+ Segment (Segment&)
+~Segment ( )

Persoan
- Nume : String
+ Persoan ( )
+ Persoan (Persoan &)
+~Persoan ( )

Student
- Facultate: String
- Varst : int
+ Student ( )
+ Student (Student &)
+~Student ( )

C
+
+
P
O
O

09.01.12 72
19. Func i i i Cl as e Pr i et ene ( Fr i end)
O funcie este prieten cu o clas dac are acces la datele membru private ale acelei
clase. O funcie prieten poate fi o funcie global sau chiar o funcie membru a altei clase.
O clas este prieten cu o alt clas dac ea are acces la datele membru ale
acesteia.
O funcie, respectiv o clas prieten se declar utiliznd cuvntul fri end astfel:
a) fri end Tip_funcie Nume_funcie ( List_parametri_formali ); // Funcie friend global
b) fri end Tip_funcie Nume_clas::Nume_funcie(List_par._formali); // Funcie friend membru
c) fri end Nume_clas; // Clas friend
Urmtorul exemplu, nu este corect, deoarece elementul C.y nu este accesibil:

// Funcie 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 soluie pentru a rezolva aceast problem, ar putea fi declararea funciei membru
TaieOx ca funcie prieten a clasei Punct. Aceast modificare nu este suficient deoarece
clasa Cerc nu a fost nc (deja!) definit, deci aceasta trebuie mai nti 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,
funcia TaieOx nu poate fi definit imediat, ci doar ulterior, dup declararea complet a
clasei Punct.
/ / Func i e f ri end 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 ";
}
C
+
+
P
O
O

09.01.12 73
Exemple:
// Funct i e gl obal a fri end \\
# 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;
}

C
+
+
P
O
O

09.01.12 74


// Funct i e membru fri end \\
# 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;
}

C
+
+
P
O
O

09.01.12 75
// Cl asa fri end \\
# 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(); }
}
C
+
+
P
O
O

09.01.12 76

20. Membr i s t at i ci ( St at i c ) // $:
Fiecare obiect dintr-o clas deine toate datele membru (atributele) acesteia. Exist
ns posibilitatea ca toate instanele unei clase s dein anumite atribute comune tuturor
obiectelor clasei respective. Aceti membri (date, funcii) stati ci au acelai regim de
protecie ca i ceilali membrii.
20.1. Atribute (Date membru) Statice // $:
Datele membru statice, care urmeaz s fie utilizate de ctre toate obiectele clasei,
se definesc prin specificatorul st at i c astfel:
cl ass Nume_clas {
st at i c List_Declaraii_date_membru ; // $ :

};
Datele membru statice, se declar (se iniializeaz) 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 urmtorul exemplu, se numr cte Puncte sunt utlizate la un moment dat n
program, utiliznd ca dat comun pentru toate punctele (ntreaga clas) Nr_Ob:


/ / Membru St at i c
# 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 iniializeaz

C
+
+
P
O
O

09.01.12 77
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 urmtor, sunt utilizai membri statici a,b,c,d pentru a memora domeniul
minim care conine toate punctele curbei (definite parametric) care se deseneaz:


/ / Membri St at i ci
# 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();
}

C
+
+
P
O
O

09.01.12 78
20.2. Metode (Funcii membru) Statice // $:
Metodele (Funciile membru) statice, acioneaz doar asupra atributelor statice
(ale claselor), deci nu pot aciona asupra atributelor obiectului curent (deoarece nu li se
transmite poinetrul this). De asemenea ele pot apela doar metodele statice. Pot ns aciona
asupra atributelor unui anumit obiect prin operatorii - sau >. Metodele statice, se definesc
prin specificatorul st at i c astfel:
cl ass Nume_clas {
st at i c Tip_funcie Nume_funcie ( List_par_formali ) // $ :

};
Referirea (utilizarea) metodelor statice se face astfel:
a) Nume_clas ::Funcie_membru (List_par_actuali) // Referire natural la clas
b) Obi ect - Func i e_membru (List_par_actuali) // Referire la un obiect
c) Pointer_Obiect > Funcie_membru (List_par_actuali) // Referire prin pointer
n urmtorul exemplu, se determin fereastra real (definit prin cele dou puncte
diagonal opuse St_Sus, Dr_Jos) utiliznd funciile statice MinX, MaxX, MinY, MaxY pentru a
determina domeniul minimal care include punctele din grafic.

/ / Fu nc i i S t a t i c e
# 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.
C
+
+
P
O
O

09.01.12 79
v Definirea unui pointer la o metod se poate face astfel:
Tip_funcie (Nume_clas :: *Nume_Pointer ) ( List_par_formali ) // sau cu typedef
v Iniializarea unui pointer la o metod se poate realiza astfel:
Nume_Pointer = & Nume_clas :: Nume_Metod; // se pot realiza i la definire
v Referirea unui pointer la o metod (apelarea metodei) :
(Nume_Obiect . *Nume_Pointer ) ( List_par_actuali )

De exemplu, pentru programul anterior, modificrile necesare pentru a putea apela
cele dou metode Muta i Trag ale clase Punct pot fi urmtoarele:


/ / P o i nt e r i l a me t o d e

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}; // Iniializare

// 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
}

C
+
+
P
O
O

09.01.12 80
Un alt exemplu, care utilizeaz pointeri la metode (Triun, Drept i Romb) este
urmtorul:


/ / P o i nt e r i l a * Me t o d e
# 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

C
+
+
P
O
O

09.01.12 81
22. Suprancrcarea operatorilor
Anumite operaii se pot exprima mult mai bine prin operatori. Nu se pot defini
operatori noi, dar se pot suprancrca cei existeni ( +, <, ++, +=, >, [ ], ( ), new, delete,
, mai puin operatorii -
*
, :: , ?: ), fr a modifica ns aritatea, prioritatea sau
asociativitatea.
Suprancrcarea se poate face cu:
a) funcii membru - numrul parametrilor fiind egal cu aritatea operatorului minus unu,
deoarece un operand este chiar obiectul curent pentru care se apeleaz metoda (acesta
putnd fi referit prin pointerul this),
b) funcii prietene - numrul parametrilor fiind egal cu aritatea operatorului.
Redefinirea unui operator se realizeaz printr-o funcie (prieten sau membru) al
crei nume este compus din cuvntul operator urmat de operatorul propriuzis (+, <, ) .
Exemplu:
// Operat ori de concat enare + & \\
# 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) // funcie 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) // funcie 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();
}
C
+
+
P
O
O

09.01.12 82
22.1. Operatorul de asignare (atribuire) i iniializare (=)
Operatorul de atribuire (=) se poate utiliza i pentru obiecte, acesta fiind
suprancrcat implicit i realizeaz copierea datelor membru. Dac ns datele membru
sunt referine (pointeri) la nite variabile dinamice, atunci prin copiere se vor obine dou
obiecte care refer acceai zon de memorie, iar la dealocare se va elibera aceeai zon de
dou ori, iar alta niciodat, ceea ce ne oblig, n aceast situaie, la redefinirea
(suprancrcarea) acestui operator. Prin aceasta, coninutul variabilelor dinamice sunt
identice, dar la adrese diferite, astfel nct dac un obiect i modific valorile, cellalt obiect
rmne neschimbat.
Pentru o declaraie de tipul Cl as Obi ect ; se va apela constructorul implicit, sau
cel cu toi parametrii implicii, iar pentru o declaraie de forma Cl as Obi ect =Ob; se va
apela constructorul de copiere (i nu operatorul de atribuire) ca i la o declaraie de forma
Cl as Obi ect (Ob);. Constructorul de copiere se mai poate apela dac parametrul unei
funcii este un obiect sau dac funcia returneaz un obiect.
Exemplu:

// Cl asa Numar Nat ural (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
};

C
+
+
P
O
O

09.01.12 83
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();
}
C
+
+
P
O
O

09.01.12 84
22.2. Operatorii de atribuire +=, =,
*
=, /=
Aceti operatori (+=, =,
*
=, /=) nu sunt suprancrcai automat, deci dac dorim
s-i utilizm va trebui s i redefinim (aa cum se poate vedea n exemplul urmtor
suprancrcarea operatorilor +=, =).
Exemplu:
// Cl asa Numar Nat ural (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();
} LvtvostEspotHotooptgtoov
C
+
+
P
O
O

09.01.12 85
22.3. Operatorii de incrementare (++) i decrementare ()
Continund cu exemplul anterior, dorim s suparancrcm operatorii de
incrementare si decrementare, mai nti cei prefixai (++x, x), unde nu sunt probleme
deosebite, apoi ce postfixai (x++, x). Pentru a suprancrca i operatorii de
incrementare postfixai vom aduga cte o funcie membru avnd un parametru de tip int
(care nu se va folosi, i care automat la un apel va lua valoarea zero).
Exemplu:
// Cl asa Numar Nat ural ( 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();
}
C
+
+
P
O
O

09.01.12 86
23. Conversii utilizator
Conversiile sunt executate automat dac:
a) operanzii nu sunt de acelai tip (char, enum p int p 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 funcie 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 conin un parametru avnd acel tip predefinit, iar ceilali vor fi
iniializai.
Exemplu:

/ / Numer e ra i onal 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();
} // Rez ul t at 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
C
+
+
P
O
O

09.01.12 87
O alt variant n care se evit utilizarea unei funcii prietene este de a defini o funcie
membru (Produs) care se va apela de ctre funcia de suprancrcare a operatorului de
nmulire.
Exemplu:
/ / Numer e ra i onal 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();
} // Rez ul t at 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 urmtor 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.
C
+
+
P
O
O

09.01.12 88
Exemplu:
/ / Numer e compl exe: TpC
#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();
} // Rez ul t at 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;

C
+
+
P
O
O

09.01.12 89
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
suprancrcarea operatorului de conversie explicit corespunztor, printr-o funcie
membru definit astfel:
class Clas { ...
public: ...
operator Tip_Predefinit ( );
...
};
Clas :: operator Tip_Predefinit ( )
{ ...
return Expresie_de_Tip_Predefinit;
}

n exemplul urmtor se va realiza o conversie dintr-un numr raional ntr-un numr
real:
/ / Conver si e Tad- Q p doubl 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 p 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();
} // Rez ul t at e:
z = 6/35
a = 1.8
b = 1.8
C
+
+
P
O
O

09.01.12 90
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 urmtor este realizat conversia (prin operatorul de
conversie) din trigonometric (clasa T) n forma algebric (clasa C):

/ / Numer e compl exe: TpC
#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 { float Ro, 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();
} // Rez ul t at 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;

C
+
+
P
O
O

09.01.12 91
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 instanierea obiectelor). O astfel de clas abstract va fi
particularizat ntr-o clas concret nlocuind tipul general cu un anumit tip ales.
24.1. Funcii ablon (Template)
Funciile Template (generice) conin i parametri formali generici care vor fi
nlocuii cu parametri de un anumit tip concret.
Exemplu:
// Func i i 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-Eusorsgreeti!
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 lucrm, sau nu corespunde cerinelor noastre, acesta va trebui
redefinit sau chiar funcia va fi rescris conform cerinelor.
Exemplu:
// Func i i 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();
}
C
+
+
P
O
O

09.01.12 92
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 corespunztoare anumitor tipuri necesare
aplicaiei.
Exemplu:
// Cl ase 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 funcii
membru template.
Argumentele pot fi tipuri de date (class Nume_Tip) sau constante (Tip
Nume_Parametru), de exemplu:
template <class T, int Dim>
C
+
+
P
O
O

09.01.12 93
24.3. Implementarea elementelor Template
n cele ce urmeaz ne vom referi la poziia codului (care se expandeaz conform
cerinelor utilizatorului) corespunztor obiectelor template. Codul template (corpul
funciilor membru) trebuie s fie vizibil acolo unde sunt utilizate elemente template.
Exist dou metode (posibiliti) de implementare:
a) template smart tot codul unei clase template este scris n fiierul header (definiii de
clase, funcii precum i implementarea funciilor), acest mod putnd fi precizat fie prin
opiunea de compilare Jg, fie prin meniul Options , Compiler , C ++ options ,
opiunea Template Generation : Smart , programul urmnd s includ acest fiier cu
toate descrierile.
b) template manual doar declaraiile elementelor template sunt scrise n fiierul header
iar implemetarea fcndu-se separat, n alt fiier. Acest mod trebuie precizat prin
directiva #pragma option, utiliznd opiunea de compilare Jgd (urmeaz o definire
public a instanierilor unor elemente template) i opiunea Jgx (urmeaz o declaraie
extern a instanierilor template). Acest mod este ilustrat n urmtorul 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;
C
+
+
P
O
O

09.01.12 94
25. Relaii ntre clase
La elaborarea modelului obiectual al unei aplicaii se disting urmtoarele dou
etape:
a) identificarea claselor corespunztoare conceptelor aplicaiei (substantivele),
b) stabilirea relaiilor dintre clase corespunztoare specificaiilor aplicaiei (verbele).
n cele ce urmeaz ne vom referi la urmtoarele tipuri de relaii ntre clase:
1) Asociaie relaie de cooperare ntre clase corespunztoare unui verb oarecare din
specificaie, diferit de relaia parte-ntreg (de exemplu relaia Student Facultate).
Relaia corespunztoare dintre obiecte aparinnd unor clase asociate se numete
legtur. O asociaie poate fi simpl sau multipl (dac un obiect asociant este pus n
legtur, de exemplu prin pointeri, cu mai multe obiecte asociate, de acelai tip).
Aceast relaie se reprezint grafic (dup metodologia OMT) n plan orizontal astfel:


2) Agregare relaie de asociaie prin care obiectul agregat este inclus n obiectul
agregant (verbul caracteristic este a avea), i evident c poate fi simpl sau multipl:

3) Specializare (generalizare, motenire) relaie prin care sunt pstrate (motenite)
caracteristicile unei clase (de baz) i sunt adugate diferenele specifice, formnd o
nou clas (derivat). Motenirea 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 relaie este tranzitiv, iar structura format de mulimea claselor
aflate n aceast relaie (construit pe vertical) se numete ierarhie de clase. Att
specializarea ct i motenirea poate fi simpl sau multipl, reprezentarea fcndu-se n
plan vertical astfel:




Se pot obine n felul acesta i ierarhii spaiale de clase, avnd relaii att pe
orizontal ct i pe vertical.

Specializare
simpl
C1
C2
Specializare
multipl
C1
C2 C3
Motenire
multipl
C1 C2
C3
simpl
C1 C2
multipl
C1 C2
k
simpl
C1 C2
multipl
C1 C2
k
C
+
+
P
O
O

09.01.12 95
25.1. Relaia de Asociaie
Prin aceast relaie dintre clase se
modeleaz o legtur ntre obiectele instaniate
(care depind unul de cellalt). Traversarea unei
asociaii se face printr-un rol (nume dat
extremitatii unei asociaii). Implementarea unei
asociaii se poate realiza astfel:
a) printr-un pointer clasa asociant conine un
atribut de tip pointer spre clasa asociat,
b) printr-o clas cu atribute i comportare
proprie, fiecare legtur fiind o instan a
acestei clase.
Asociaiile pot fi unidirecionale sau bidirecionale, iar relaiile de asociaie pot fi
binare, ternare sau n-are. Pe de alt parte, asociaiile pot fi simple sau multiplicative
(acestea din urm putnd fi eventual i cu restricii de ordonare sau de calificare).
Asociaiile multiplicative sunt caracterizate prin numrul de instane ale claselor
care se afl n asociaie, iar pentru a reprezenta direcia de asociaie se pot utiliza sgei.
O asociaie multiplicativ poate s fie
neordonat (instanele formeaz o mulime), sau
poate s fie ordonat (instanele formeaz o list
ordonat).
O relaie multiplicativ cu restricie de
calificare pune n relaie dou clase printr-un
calificant (atribut care reduce multiplicitatea
asociaiei printr-un criteriu pe care trebuie s-l
ndeplineasc obiectele asociate pentru a intra n
relaie).
La implementarea relaiilor de asociaie putem aplica cele dou metode amintite
anterior:
a) prin pointeri spre clasa asociat ncuibrii n clasa asociant n funcie de tipul relaiei
de asociere astfel:
pentru relaia de asociaie simpl se adaug clasei asociante nc un atribut de tip
pointer spre clasa asociat, mpreun cu relaxarea ncapsulrii pentru traversarea
asociaiei alegnd o metod convenabil dintre urmtoarele variante:
v modificarea proteciei datelor membru implicate n public,
v utilizarea de metode sau clase friend,
v extinderea interfeei prin metode de acces la componente.
pentru relaia de asociaie multipl se adaug clasei asociante mai multe atribute de tip
pointer n funcie de tipul asociaiei i ordinul de multiplicitate astfel:
v dac este relativ mic, se vor aduga pointeri distinci,
v iar n caz contrar se poate utiliza un ir de pointeri;
O1
legtur
asociaie
C1
O2
rol
2
rol
1
C2
i
n
s
t
a
n

i
e
r
e

i
n
s
t
a
n

i
e
r
e

asociaia
C1 C2
{ordonata}
asociaia
C1 C2 calificant
C
+
+
P
O
O

09.01.12 96
v dac relaia este supus unor restricii de ordonare, se pot utiliza liste ordonate.
b) prin clase distincte care realizeaz
abstractizarea asociaiilor dac legturile au
proprieti i operaii proprii (nemaifiind
necesar adugarea de atribute claselor care se
asociaz), aceast metod utilizndu-se n
special n cazul asociaiilor bidirecionale de tip
m-n), sau o legtur 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();
}

// Cl as asociant \\ << VectCaut.h >>
#include "VectSort.h"
class VectCaut { VectSort *v;
public: VectCaut (VectSort*);
int CautSec (int a);
int CautBin (int a);
};

// Cl as asociat \\ << VectSort.h >>

class VectSort { int *v, n;
public: VectSort (int = 10);
void Sort ( );
void Print( );
int* Adr ( );
int Dim ( );
~ VectSort ( );
};
C1 C2
m n
Cas.
C
+
+
P
O
O

09.01.12 97

// Cl as 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;
}

// Cl as 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;
}

C
+
+
P
O
O

09.01.12 98
25.2. Relaia de Agregare
Relaia de agregare este cea mai puternic
relaie de asociaie, n care o clas este o
component a altei clase, deci relaia este binar,
unidirecional, iar relaiile multiplicative sunt de
tip 1-n. Prin aceast relaie dintre clase, un obiect
al clasei agregate este parte constituent, atribut,
al clasei agregante, deci verbul caracteristic este a
avea (conine). Obiectele constituente pot fi
independente sau doar componente ale obiectului
care le include.
Aceast relaie (notat cu simbolul avnd semnificaia conine) are urmtoarele
dou proprieti de baz:
a) tanzitivitate : Dac Cx Cy i Cy Cz, atunci Cx Cz ,
b) antisimetrie : Dac Cx Cy atunci Cy
/
Cx .
Relaia de agregare poate fi:
a) fix numrul i tipul componentelor sunt fixe,
b) variabil permite un numr variabil de obiecte de acelai tip,
c) recursiv accept acelai tip ca tip agregat i agregant.
Exemplu:
// Relaia 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();
}

O1
conine
Conine
C1
O2
i
n
s
t
a
n

i
e
r
e

i
n
s
t
a
n

i
e
r
e

C2
C
+
+
P
O
O

09.01.12 99

// Cl as 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);
};

// Cl as 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;
}

// Cl as 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 ( );
};

// Cl as Agregat \\ << VectSort.Cpp >>
# include <iostream.h>
# include "VectSort.h"

// A fost deja descris la clase asociate. \\

C
+
+
P
O
O

09.01.12 100
n urmtorul exemplu se va folosi o clas Iterator pentru list simplu nlnuit 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();
}


C
+
+
P
O
O

09.01.12 101
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 utiliznd operatorul de
scop (::) aa cum se poate vedea n exemplul urmtor:

// Cl ase Imbri cat 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 utiliznd operatorul de
apartenen (.) dup cum se vede n urmtorul exemplul:
// Cl ase Incui bat 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();
}
C
+
+
P
O
O

09.01.12 102
Evident c din clasa ncuibat (Punct) nu avem acces la elementele clasei din care
face parte (Cerc). Dac se dorete acest lucru, atunci se poate proceda ca i n urmtorul
exemplu:
// Cl ase Incui bat 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 funcia Print descris n ambele variante), motiv
pentru care clasa Punct a fost declarat prieten.
n urmtorul exemplu sunt imbricate clasele R R
2
R
3
:
// Cl ase Incui bat 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();
}
C
+
+
P
O
O

09.01.12 103

25.4. Relaia de derivare
Prin aceast relaie putem modela similitudinile dintre clase dou sau mai multe
clase. Pornind de la o clas de baz (general) se pot deriva noi clase (prin diferenele
specifice). Obiectele clasei derivate motenesc atributele i metodele clasei de baz la care
se vor aduga noile elemente caracteristice (vor fi umflate), ceea ce permite reutilizarea
resurselor deja pregtite n clasele de baz (pentru obiectele similare). Verbul caracteristic
al acestei relaii de specializare este a fi ( este un fel de <a kind of>).
Motenirea permite pstrarea elementelor (date i
funcii ale) unei clase de baz (superclas), cu definirea de
noi elemente construind o nou clas derivat (subclas),
formnd n felul acesta ierarhii de clase. Motenirea poate
fi i multipl dac o clas motenete mai multe clase.
Deoarece aceast relaie este tranzitiv se utilizeaz i
termenii de strmo i descendent.






25.4.1. Clase derivate
Relaia de derivare se poate descrie prin construcii speciale fr a mai fi nevoie de o
relaxare a ncapsulrii, aa cum a fost necesar la relaiile prezentate anterior. Dac ntr-o
aplicaie se poate utiliza relaia de derivare, este de preferat n locul asociaiei sau agregrii
pentru c avem instrumente specializate n limbajul de programare.
O clas derivat se declar astfel:
class Clas_Derivat : List_clase_de_baz
{
Date i Funcii membru noi
};
Specializare
multipl
C1
C2 C3
Specializare
simpl
C1
C2
s
p
e
c
i
a
l
i
z
a
r
e

Motenire
multipl
C1 C2
C3
g
e
n
e
r
a
l
i
z
a
r
e

Ob
Od
Cd
Cb
e
s
t
e

u
n


e
s
t
e

o


C
+
+
P
O
O

09.01.12 104
Lista claselor de baz poate s conin i modificatorii de protecie (Mod_Pr)
public, protected sau private, deci o derivare poate s fie public, protejat sau privat,
accesul rezultat fiind redat n urmtoarele tabele.





De exemplu, dac cele dou
clase sunt descrise astfel:

class Cl_Baz
{
private: a
protected: b
public: c
};

class Cl_Derivat : Mod_Pr Cl_Baz
{
private: a
protected: b
public: c
};
atunci protecia membrilor din clasa
derivat este redat n schema
alturat.
Ordinea de executare a constructorilor la instanierea obiectelor dintr-o clas
derivat:
prima dat se execut constructorul clasei de baz, apoi constructorul clasei derivate (se
construite cadrul, apoi se adaug diferenele 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
a b c
x by cz
Cl_Baz
public:
Cl_Derivat
a b c
x bcy z
Cl_Baz
protected:
Cl_Derivat
a b c
bcx y z
Cl_Baz
private:
Cl_Derivat
Accesul n clasa de baz Mod_Pr Accesul n clasa derivat
private *
Private private
protected sau public Protected protected
Public neschimbat (protected sau public)

d
\
b

# +
+ - # +
# - # #
-
C
+
+
P
O
O

09.01.12 105
Deoarece relaia de derivare este poate cea mai important relaie dintre clase, sunt
oferite faciliti de implementare, care permit urmtoarele faciliti:
v economia de cod reutilizarea codului scris o singur dat dup care se motenete,
v extensibilitate re-specializare prin derivarea de noi ramuri dintr-o ierarhie,
v polimorfism ntr-o ierarhie de clase se poate implementa o comportare polimorfic,
v ncapsularerelaxare relaia de derivare ofer posibilitatea nchiderii resurselor
simultan cu deschiderea spre modificare i extensie.
Relaiile de derivare (de fapt i celelalte relaii dintre clase) sunt stabilite la
compilare, deci nu se mai pot modifica pe parcursul execuiei. Mai trebuie cunoscut faptul
c prin derivare nu se pot moteni constructorii, destructorii, elementele prietene (funcii,
clase sau metode friend) i nici operatorii redefinii.
Exemplu:
// Rel at i a de deri vare \\
#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();
}


C
+
+
P
O
O

09.01.12 106
Conversia unui obiect dintr-o clas derivat ntr-un obiect aparinnd clasei de baz
este permis, invers ns nu (sursa trebuie s acopere destinaia):
Contra_Exemplu:
// Conversi i l a 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 funcie care are ca parametru formal un obiect al clasei de baz este permis
apelul avnd ca parametru un obiect al clasei derivate, invers nu (o funcie care are ca
parametru formal un obiect al clasei derivate, nu poate fi apelat avnd ca parametru actual
un obiect al clasei de baz).
Exemplu:
// Conversi e la deri vare \\
#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 urmtor se pornete de la clasa de baz VectBaza i se construiete
clasa derivat Vect_Der :

C
+
+
P
O
O

09.01.12 107
// Relaia 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();
}

// Cl as de baz \\ << VectBaza.h >>

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

// Cl as 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;
}

C
+
+
P
O
O

09.01.12 108
// Cl as Derivat \\ << Vect_Der.h >>
#include "VectBaza.h"
class Vect_Der : public VectBaza {
public: Vect_Der (int=10);
int CautSec (int);
int CautBin (int);
};

// Cl as 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 operaia Contine (PC).

// 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();
} // Rez ul t at 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 trziu declarnd Distana ca funcie virtual (pentru legare dinamic).
C
+
+
P
O
O

09.01.12 109
Fa de motenirea simpl, n care dintr-
o singur clas de baz se deriveaz una sau
mai multe clase derivate (specializate),
motenirea multipl presupune existena mai
multor clase de baz din care un sau mai multe
clase motenesc diverse caracteristici.
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 motenirii multiple o clas de baz poate fi
prezent n mai multe exemplare ntr-o clas derivat, aa
cum se poate vedea n exemplul alturat, unde datele
membru ale clasei Animal vor fi motenite n dou
exemplare de ctre clasa Cine (unul prin clasa Domestic,
altul prin clasa Mamifer) i pot fi referite prin operatorul
de rezoluie ( :: ) aplicat clasei prin care se face motenirea
(Nume).
Aceast motenire repetitiv a unei clase de baz
este corect i se poate utiliza astfel:
class Cl_Baz { protected: Atribut };
class Cl_Der
1
: public Cl_Baz { };
class Cl_Der
2
: public Cl_Baz { };
class Clas_Derivat : public Cl_Der
1
, Cl_Der
2

{ Cl_Der
1
::Atribut Cl_Der
2
::Atribut };
Dac dorim realizarea unei singure copii a
atributelor motenite, vom folosi motenirea multipl
virtual:
class Cl_Baz { protected: Atribut };
class Cl_Der
1
: virtual public Cl_Baz { };
class Cl_Der
2
: virtual public Cl_Baz { };
class Clas_Derivat : public Cl_Der
1
, Cl_Der
2

{ Atribut };

Animal
Mamifer Domestic
Cine

Cl_Baz
Cl_Der
1
Cl_Der
2
Clas_Derivat
Cl_Baz

Cl_Der
1
Cl_Der
2
Clas_Derivat
Cl_Baz

Motenire simpl
Cb
Cd
1
Cd
2

Motenire multipl
Cb
1
Cb
2

Cd
C
+
+
P
O
O

09.01.12 110
Aa cum se poate vedea n exemplul urmtor, vom avea un nume de mamifer i un
nume domestic.

/ / Pr ogram Cl as e NeVi rt ual 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
C
+
+
P
O
O

09.01.12 111
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 motenire
dac se declar aceasta prin cuvntul virtual plasat naintea clasei (devenind astfel clas
virtual fa de clasa derivat).
Programul anterior modificat astfel nct numele s fie memorat ntr-un singur
exemplar este urmtorul:

/ / Pr ogram Cl as e Vi rt ual 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();
} / / Rez ul t at e:
Nume Animal : Lup
Greutate : 13
Pret : 1300
Lant : 8
C
+
+
P
O
O

09.01.12 112

Pentru o ierarhie ca cea din figura alturat,
n care avem clase virtuale (T) i nevirtuale (,), se
execut mai nti constructorii claselor de baz
virtuale apoi cei ai claselor nevirtuale, iar
constructorul clasei de baz se va executa pentru o
singur dat toate exemplarele virtuale i cte o dat
pentru fiecare exemplar nevirtual.

Exemplul:

/ / Pr og r am I er ar hi e Cl as e Vi r t ua l e/ Nevi r t ual 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();
} / / Rez ul t at e:
A : Ob.
F : Ob.
B : Ob.
C : Ob.
A : Ob.
D : Ob.
E : Ob.
G : Ob.



F
A
B C
G
D E

C
+
+
P
O
O

09.01.12 113
2 6 . Po l i mo r f i s m
Suprancrcarea (overloading), prin redefinirea unor funcii sau metode, permite
alegerea la compilare-link_editare a funciei sau a metodei dorite prin semntura acesteia,
fr a mai putea alege la execuie.
Polimorfismul permite ca la execuie s se decid ce metod s fie apelat, oferind
o facilitate a metodelor din clase aflate n relaie de derivare. Prin polimorfism se execut
aciuni diferite prin mesaje cu semnturi identice asupra obiectelor de tip diferit (obiecte din
clase diferite rspund diferit la acelai mesaj).
Dou obiecte sunt compatibile dac aparin aceleai 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:
v Cl asice metode legate static, la compilare-link_editare fiind fixat adresa de apel a
metodei, fr posibilitatea de a o schimba la rularea aplicaiei,
v Polimorifice metode legate dinamic, care permit ntrzierea deciziei referitoare la adresa
de apel a metodei, pn la execuie.
Legarea unei metode (binding), nelegnd prin aceasta cenexiunea logic dintre o
entitate i o proprietate a acesteia (corespondena dintre un mesaj trimis unui obiect, adic
ordinul de apel, i metoda care se execut ca rspuns la acesta) poate fi:
v Timpurie (static early-binding) compilatorul i editorul de legturi vor fixa adresa
metodei care se execut, fr ca aceasta s mai
poat fi modificat pe parcursul execuiei;
v Trzie (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
execuie. n funcie valoarea pointerului spre clasa
de baz, care poate conine i adresa unui obiect al
clasei derivate, se va alege metoda
corespunztoare.

C
+
+
P
O
O

09.01.12 114
26.1. Funcii membru Vi rt ual e
Implicit, o metod este legat static (early, la compilare), iar dac se dorete o
legare dinamic (late, la execuie) se va declara virtual prin scrierea cuvntului vi rt ual
naintea metodei. O metod virtual a unei clase de baz, poate fi motenit 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 urmtor c dac dorim ca rezultatul s fie
Baza/Derivata i la apelul funciei g, trebuie s declarm funcia f virtual, altfel
rezultatul ar fi Baza/Baza.

// Met od vi rt ual \\
# 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 urmtor vom utiliza variabile de tip referin la clasa de baz, respectiv
la clasa derivat.

// Met od vi rt ual \\
# 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();
}
C
+
+
P
O
O

09.01.12 115
n urmtorul exemplu se poate deduce necesitatea legrii dinamice, pentru a putea
calcula corect distana de la un punct la un cerc i respectiv la un segment (la o dreapt).
Din pcate pentru c metoda Contine exist n dublu exemplar (Stanga i Dreapta) apelul
nu se poate efectua cum ar fi de dorit!

// Met od vi rt ual \\
#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();
}

C
+
+
P
O
O

09.01.12 116
Aproape orice metod poate fi virtual, chiar i metodele inline, metodele friend
(dar nu i funciile friend) operatorii (dac nu se redefinesc prin funcii 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
afiat dac operatorul de nmulire a dou numere raionale nu este declarat vi rtual,
(deoarece operatorul *= va apela operatorul de nmulire pentru Q n loc de F cum ar
trebui, a i b fiind din clasa F). Se observ c la nmulirea a dou obiecte din clasa Q nu
sunt tiprite fraciile care se nmulesc, pe cnd la nmulirea a dou obiecte din clasa F
fraciile care se nmulesc sunt tiprite.

// 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();
} // Rez ul t at 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

C
+
+
P
O
O

09.01.12 117
26. 2. Clase abstracte - funcii membru virtuale pure
n clasa de baz se poate declara o comportare generic avnd un nume i o
semntur unic (urmnd 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, permind astfel solicitarea unui comportament
general, dar propriu fiecrei specializri.
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 conine cel puin o funcie membru virtual pur. O
funcie 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
conin funcii membru nedefinite (virtuale pure), nu se pot crea obiecte aparinnd acestora
(nu pot fi instaniate, dar se pot defini variabile de tip pointer sau referin la o clas
abstract), iar dac funciile virtuale nu sunt definite nici n clasele derivate, atunci i aceste
clase devin abstracte (o clas derivat dintr-o clas abstract rmne abstract dac nu s-au
redefinit toate metodele pure motenite, iar n caz contrar devine clas concret).
O clas abstract realizeaz implementarea unei noiuni care nu poate fi concretizat
(i atunci nu poate fi dect enunat), dar surprinde o caracteristic comun a claselor
specializate din aceasta (care vor conine implementrile efective). Deci, o clas abstract
va generaliza (abstractiza) comportamentul subclaselor specializate.
ntr-o ierarhie, clasa de baz poate avea nite
proprieti care nu se pot defini dect n clasele
derivate (anumite caracteristici depind de clasa
derivat). n exemplul alturat, cu toate c se
cunoate greutatea unui animal, nu se poate spune c
este slab sau gras dect pentru o clas derivat).
Animal
Porumbel Urs Cal

C
+
+
P
O
O

09.01.12 118
n exemplul urmtor vom da trei caracterizri pentru un anumit animal n funcie de
greutatea lui i cea medie (slab/gras), vrsta lui i cea medie (tnr/btrn), i viteza lui (de
deplasare) i cea medie (lent/rapid), acestea pentru un Porumbel, Urs sau Cal.

/ / Cl ase Abst ract e- Met ode 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();
} / / Rez ul t at e:
gras, tanar, lent
gras, batran, rapid
slab, tanar, rapid

C
+
+
P
O
O

09.01.12 119

n exemplul urmtor vom apela o funcie Draw pentru a
desena o figur oarecare (Punct, Ptrat sau Cerc) i o funcie Arie
care va aplica formula caracteristic fiecrei figuri geometrice:

/ / Cl as Abst ract - Met ode 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;
};
getche(); InitGraf();
Figur
Punct Ptrat Cerc

C
+
+
P
O
O

09.01.12 120
for (i=0; i<n; i++) { setcolor(15-i); Fig[i]->Draw();}
getche(); closegraph();
}
C
+
+
P
O
O

09.01.12 121
27. I er ar hi i pent ru I nt rr i / I ei r i
Pentru c nu exist instruciuni de intrare/ieire, s-au definit funcii (n C), respectiv
dou ierarhii de clase (n C++). Aceste dou ierarhii (reprezentate n figurile de mai jos i
declarate n fiierul iostream.h) realizeaz operaiile de intrare/ieire prin stream-uri (flux de
date surspdestinaie).
Clasa streambuf se folosete pentru gestio-
narea zonelor tampon i operaii de intrare/ieire
simple.
Clasa ios este clasa de baz vitual pentru
clasa istream (care face conversia dup un format
specificat, din caracterele unui obiect de tip
streambuf), clasa ostream (care face conversia
dup un format specificat, n caractere ale unui
obiect de tip streambuf) i clasa iostream (care face
conversii n ambele sensuri). Legtura dintre cele
dou ierarhii se realizeaz printr-o dat membru a
clasei 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 fiierul iostream.h sunt definite
streamurile cin ( istream_withassign, pentru stdin), cout ( ostream_withassign, pentru
stdout), clog i cerr ( ostream_withassign, pentru stderr, cu respectiv fr zone tampon).
27. 1. Operatorul de inserare <<
Operaiile de scriere se pot efectua cu operatorul de inserare << . Operandul stng
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
crei tip a fost suprancrcat operatorul << . Pentru tipurile standard a fost suprancrcat
printr-o funcie membru de forma:
ostream& operator << ( Tip_Standard );
strembuf
filebuf st rst reambuf

iostream_withassig
ios
istream ostream
iostream
istream_withassign ostream_withassig

C
+
+
P
O
O

09.01.12 122
Pentru tipurile abstracte programatorul poate suprancrca acest operator, aa cum
se poate vedea n cele ce urmeaz.
Pentru a putea tipri un obiect
cout << Obiect ;
vom suprancrcrca (ntr-o prim variant) operatorul de inserare (<<) printr-o funcie
prieten astfel:
class Clas { ...
friend ostream& operator << ( ostream&, Clas );
...
};
Exemplu:
/ / Program Operat or << Fri end; \ \
#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();
} / / Rez ul t at e:
r = 12/13
Se observ c acest operator se poate aplica nlnuit pentru c funcia prieten
returneaz o referin la stream-ul curent.
n cele ce urmeaz vom da o alt rezolvare fr a utiliza o funcie prieten (care
micoreaz gradul de protecie a datelor). Pentru o Clas vom scrie o funcie membru de
Tiprire, care va fi apelat de ctre funcia de suprancrcare a operatorului << astfel:
class Clas { ...
public: ostream& Tiprire ( ostream& s );
...
};
ostream& Tiprire ( ostream& s )
{ s << ... ;
return s;
}
ostream& operator << ( ostream&, Clas c )
{
return c.Tiprire(s);
}
C
+
+
P
O
O

09.01.12 123
Pentru exemplul anterior (Q) programul va fi urmtorul:
/ / Program Operat or << \ \
#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();
} / / Rez ul t at e:
r = 12/13
27. 2. Operatorul de extragere >>
Operaiile de citire se pot efectua cu operatorul de extragere >> . Operandul stng
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
crei tip (standard sau abstract) a fost suprancrcat operatorul >> . Pentru tipurile
standard a fost suprancrcat printr-o funcie membru de forma:
istream& operator >> ( Tip_Standard & );
Pentru tipurile abstracte programatorul poate suprancrca acest operator, aa cum
se poate vedea n cele ce urmeaz. Pentru a putea citi un obiect
cin >> Obiect ;
vom suprancrcrca (ntr-o prim variant) operatorul de extragere (>>) printr-o funcie
prieten astfel:
class Clas { ...
friend istream& operator >> ( istream&, Clas& );
...
};
C
+
+
P
O
O

09.01.12 124
Exemplu:
/ / Program Operat or >> Fri end; \ \
#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 nlnuit pentru c funcia prieten
returneaz o referin la stream-ul curent.
n cele ce urmeaz vom da o alt rezolvare fr a utiliza o funcie prieten (funcie
care micoreaz gradul de protecie a datelor). Pentru o Clas vom scrie o funcie membru
de Citire, (care va fi apelat de ctre funcia de suprancrcare 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 urmtorul:
/ / Program Operat or >> \ \
#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();

C
+
+
P
O
O

09.01.12 125
27.3. Intrri/Ieiri cu format
Tiprirea (afiarea) datelor dup un anumit format (ablon) precizat (asemntor
funciilor scanf i printf) se poate realiza i cu ajutorul ierarhiilor de clase definite n C++,
fie prin apelul funciilor membru setf, width, fill, precision, fie cu ajutorul unor
metode speciale numite manipulatori.
27.3.1. Funciile membru setf, width, fill,
precision
Clasa ios conine o dat membru x_flags care conine formatul operaiilor de intrare-
ieire. n aceeai clas mai este definit un tip enumerare prin care se poate referi formatul
corespunztor conversiei ataate operaiilor de transfer:
class ios { public:
enum {
skipws = 0x0001, // salt peste (ignor la citire) caracterele albe
left = 0x0002, // cadrare la stnga
right = 0x0004, // cadrare la dreapta
internal = 0x0008, // spaiile dup semn sau baz
dec = 0x0010, // conversie n zecimal
oct = 0x0020, // conversie n octal
hex = 0x0040, // conversie n heza
showbase = 0x0080, // afiarea bazei
showpoint = 0x0100, // afiare punct zecimal
uppercase = 0x0200, // cifre hexa cu litere mari
showpos = 0x0400, // afiare cu semn
scientific = 0x0800, // reale cu exponent
fixed = 0x1000, // reale fr 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 utiliznd funcia membru setf descris n continuare.
Metoda setf are urmtoarele dou forme:
1) long setf (long format);
2) long setf (long bit, long grup);
Funcia modific atributul x_flags preciznd ntraga valoare (varianta a)) sau
preciznd un grup de bii i bitul dorit din cadrul grupului (varianta b)). Grupele (i valorile
corespunztoare) sunt adjustfield (left, right, internal), basefield (dec, oct, hex) i floatfield
(scientific, fixed) n ambele variante funcia returneaz valoarea anterioar a atributului
x_flags. Referirea grupului i bitului dorit se face prin numele clasei urmat de operatorul de
rezoluie i bitul dorit (ios::b). Valoarea atributului x_flags se poate obine i prin apelul
metodei flags (cout.flags() ).
C
+
+
P
O
O

09.01.12 126
Atributul x_width conine lungimea minim a cmpului de afiare a unei date
(respectiv lungimea maxim a cmpului din care se face citirea), avnd valoarea implicit
nul (afiare pe lungimea minim necesar), care se poate modifica utiliznd funcia membru
width descris n continuare n ambele forme:
a) int width ( );
b) int width (int lungime);
Funcia returneaz valoarea atributului x_flags (varianta a)) sau modific atributul
x_width preciznd 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 conine caracterul de umplere necesar completrii cmpului de afiare
a datei n situaia n care lungimea acestuia este mai mare dect lungimea necesar, avnd
valoarea implicit spaiu ( ), care se poate modifica utiliznd funcia membru fill :
a) char fill ( );
b) char fill (char car);
Funcia returneaz valoarea atributului x_ fill (varianta a)) sau modific atributul x_
fill preciznd noul caracter de umplere (car) i returneaz valoarea anterioar (varianta b)).
Atributul x_precision conine precizia de afiare (numrul de zecimale) a unei date de
tip real, avnd valoarea implicit 0, care se poate modifica utiliznd funcia membru
precision:
a) int precision ( );
b) int precision (int n);
Funcia returneaz valoarea atributului x_ precision (varianta a)) sau modific
atributul x_ precision preciznd noua precizie (p) i returneaz valoarea anterioar (varianta
b)).
n exemplul urmtor se poate vedea apelul funciilor prezentate anterior precum i
rezultatele obinute:

// Operat orul de i nserare << cu f ormat \\
#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); }
C
+
+
P
O
O

09.01.12 127
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, acetia avnd avantajul c pot fi apelai nlnuit (deoarece returneaz
referin la stream). Primii apte manipulatori prezentai n continuare sunt declarai n
fiierul iostream.h, iar ultimii ase n fiierul 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 rnd nou i vidarea zonei tampon

1. setbase (int b) definete baza n care se face conversia
2. setiosflags (int f) setarea unor bii precizai
3. resetiosflags (long f) tergerea unor bii precizai
4. setw (int l) definete lungimea cmpului
5. setfill (int c) definete caracterul de umplere
6. setprecision (int p) definete numrul de zecimale

Exemplul urmtor utilizeaz manipulatorii pentru a realiza tiprirea rezultatelor
dorite:

C
+
+
P
O
O

09.01.12 128
// Operat orul de i nserare << cu mani pul at ori \\
#include <conio.h>
#include <iostream.h>
#include <iomanip.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; }
};
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 urmtor se utilizeaz manipulatorii pentru a realiza citirea datelor
utiliznd un format variabil (width(i+1)):

// Operat orul de ext ragere >> cu mani pul at ori \\
#include <conio.h>
#include <iostream.h>
#include <iomanip.h>
class N { char c[6];
public: N ( ) { c[0]=0; }
istream& Cit (istream& s) { s >> c; return s; }
ostream& Tip (ostream& s) { s << c; return s; }
};
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;
for (int i=1; i<=5; i++) { cout << i << " : ";
cin >> setw(i+1) >> n ; // cin.width(i+1);
cout << " _______________ n = " << n << endl;
}
getche();
}
Rezultate:
1 : 1234567890
_______________ n = 1
2 : _______________ n = 23
3 : _______________ n = 456
4 : _______________ n = 7890
5 : 1234567890
_______________ n = 12345

Rezultate:
n : 100
n = 100
n = 64 : 2001
n = 0x64
n = ...100
n/3= ____33.33

C
+
+
P
O
O

09.01.12 129
27.4. Tratarea erorilor la operaiile de intrare/ieire
Dac o operaie de intrare/ieire nu s-a ncheiat cu succes (nu s-a desfurat corect,
situaie n care vom spune c streamul ajunge ntr-o stare de eroare), programul poate lua o
decizie (controlnd n acest fel desfurarea transferurilor de date n scopul corectitudinii
desfurrii lor). Tipul erorii (un codul de retur) poate fi aflat verificnd biii datei membru
state (de tip int) prin tipul enumerare io_state definit n clasa ios astfel:
class ios { public:
enum {
goodbit = 0x00, // operaie corect
eofbit = 0x01, // sfrit de fiier
failbit = 0x02, // eroare intrare/ieire
badbit = 0x04, // operaie invalid
hardfail = 0x80, // eroare fatal
};

};
Valorile (biilor) atributului state se pot determina utiliznd urmtoarele funcii:
1) int good (); // biii de eroare (eofbit, failbit, badbit, hardfail) nu sunt setai,
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 biilor de stare (valoarea datei state).
Valorile biilor datei state pot fi modificate cu funcia:
void clear (int = 0);
La un apel fr paramteru actual se vor anula biii 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 anulai
Exemplu:
cin.clear (ios::bad_bit | cin.rdstate() ); // bad_bit restul neschimbai
Citirea (inclusiv a caracterelor albe) se poate realiza cu funcia membru getline
definit astfel:
istream& getline ([un]signed char* z, int n, char c = \n);
care citete cel mult n-1 caractere sau ntlnete caracterul c.
n exemplul urmtor se citesc mai multe cuvinte separate prin spaii:


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

C
+
+
P
O
O

09.01.12 130
n exemplul urmtor se repet citirea pn cnd numrul tastat este corect:

// Cont rol ul erori l or l a op. I/ E \\
#include <conio.h>
#include <iostream.h>
class N { int c;
public: N ( ) { c=0; }
istream& Cit (istream& s) { s >> c; return s; }
ostream& Tip (ostream& s) { s << c; return s; }
};
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; 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 strii de eroare a unui stream se mai poate face prin operatorul ! sau prin
conversia ntr-un pointer fr tip (void*) :
a) operatorul ! este suprancrcat cu metoda clasei ios:
int operator ! ( ); // returneaz o valoare egal cu a funciei fail();
De exemplu, n programul Propoziie.Cpp prezentat anterior instruciunea
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 strii de eroare a stream-ului, i poate fi
utilizat n construcii de forma
if ( s >> dat) ;
rezultatul (o referin la obiectul stream clasei istream) fiind NULL (0) dac funcia fail( )
{ 0.
Citirea caracterelor sau a datelor se poate realiza i cu funcia 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.
Rezultate:
n : a
State : 2
n : ^Z
State : 3
n : 123
State : 0
n = 123

C
+
+
P
O
O

09.01.12 131
n exemplul urmtor se poate vedea att utilizarea conversiei spre tipul void*,
precum i a funciei membru get ( n varianta b)):

// Cont rol ul 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); }

void main (void)
{
N n;
do {
cin >> n;
if (cin) cout << n << endl;
}
while (!cin.eof());
}

Rezultate:
: 123
= 123
: a
Err.
: 456
= 456
: xy
Err.
: ^Z

C
+
+
P
O
O

09.01.12 132
Cuprins
pag.
1. Redactarea programelor C .................................................................. 1
1.1. Generaliti ......................................................................................... 1
1.2. Structura unui program ....................................................................... 1
1.3. Funcii ................................................................................................ 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. Iniializarea variabilelor ....................................................................... 6
3. Expresii ................................................................................................. 7
3.1. Operatori ............................................................................................ 7
4. Operaii de intrare/ieire .................................................................... 11
4.1. Funcia Printf .................................................................................. 11
4.2. Funcia Scanf ................................................................................... 12
4.3. Funcia PutChar .............................................................................. 13
4.4. Funcia GetChar .............................................................................. 13
4.5. Funcia GetChe ................................................................................ 13
4.6. Funcia GetCh................................................................................... 13
5. Instruciuni .......................................................................................... 14
5.1. Instruciunea Vid ............................................................................ 14
5.2. Instruciunea Expresie ...................................................................... 14
5.3. Instruciunea Compus..................................................................... 14
5.4. Instruciunea If ................................................................................ 15
5.5. Instruciunea Switch ......................................................................... 15
5.6. Instruciunea While .......................................................................... 16
5.7. Instruciunea Do_While ................................................................... 16
5.8. Instruciunea For ............................................................................. 17
5.9. Instruciunea Break ........................................................................... 17
5.10. Instruciunea Continue ...................................................................... 17
C
+
+
P
O
O

09.01.12 133
5.11. Instruciunea GoTo ........................................................................... 17
5.12. Apelul unei funcii ............................................................................. 18
6. Pointeri ................................................................................................ 20
6.1. Declararea unui Pointer .................................................................... 20
6.2. Operaii cu Pointeri .......................................................................... 20
6.3. Alocare dinamic a memoriei ............................................................. 22
6.4. Pointeri la funcii ............................................................................ 22
6.5. Utilizarea parametrilor din linia de comand ...................................... 24
6.6. Declararea const antelor ................................................................. 24
6. 7. St i va ............................................................................................... 24
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. Cmpuri de biti ................................................................................ 28
9. Structuri de date dinamice ................................................................. 29
9.1. List simplu nlnuit ordonat ......................................................... 29
9.2. Abori binari ...................................................................................... 30
10. Utilizarea fiierelor ..................................................................... 32
10.1. Nivelul inferior.................................................................................. 32
10.2. Nivelul superior ................................................................................ 35
11. Funcii standard .......................................................................... 40
11.1. Macrouri de clasificare ...................................................................... 40
11.2. Macrouri de transformare a simbolurilor ............................................ 40
11.3. Conversii .......................................................................................... 40
11.4. Funcii de prelucrare a irurilor de caractere....................................... 41
11.5. Funcii de calcul ................................................................................ 41
11.6. Funcii pentru controlul proceselor .................................................... 41
11.7. Funcii pentru timp............................................................................ 42
11.8. Funcii diverse .................................................................................. 42
C
+
+
P
O
O

09.01.12 134
12. Ecranul n mod text..................................................................... 43
13. Ecranul n mod grafic ................................................................. 43
14. Faciliti C++ .............................................................................. 47
14.1. Extensii ale limbajului C .................................................................... 47
14.2. Operatori .......................................................................................... 48
14.3. Structur, uniune i enumerare .......................................................... 51
15. Funcii C++ ................................................................................. 53
15.1. Funcii Inline .................................................................................... 53
15.2. Funcii de tip referin ....................................................................... 54
15.3. Suprancrcarea funciilor .................................................................. 56
15.4. Iniializarea parametrilor formali ........................................................ 57
15.5. Funcii membru pentru Structuri ........................................................ 58
16. Ti p Abs t r ac t de Dat ........................................................ 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
19. Func i i i Cl as e Pr i e t e ne ( Fr i e nd) ............................... 72
20. Me mbr i s t at i c i ( St at i c ) // $: ............................................... 76
20.1. Atribute (Date membru) Statice // $: ................................................. 76
20.2. Metode (Funcii membru) Statice // $: .............................................. 78
21. Pointeri la Metode ....................................................................... 78
22. Suprancrcarea operatorilor ..................................................... 81
22.1. Operatorul de asignare (atribuire) i iniializare (=) ......................... 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
C
+
+
P
O
O

09.01.12 135
24. Clase ablon (Template) .............................................................. 91
24.1. Funcii ablon (Template) ................................................................. 91
24.2. Clase Template ................................................................................. 92
24.3. Implementarea elementelor Template ................................................. 93
25. Relaii ntre clase ........................................................................ 94
25.1. Relaia de Asociaie .......................................................................... 95
25.2. Relaia de Agregare .......................................................................... 98
25.3. Clase ncuibate(imbricate) ............................................................... 101
25.4. Relaia de derivare .......................................................................... 103
2 6 . P o l i m o r f i s m .......................................................................... 113
26.1. Funcii membru Vi rt ual e .............................................................. 114
26.2. Clase abstracte - funcii membru virtuale pure .............................. 117
27. I e r ar hi i pe nt r u I nt r r i / I e i r i ........................................ 121
27.1. Operatorul de inserare << ............................................................. 121
27.2. Operatorul de extragere >> .......................................................... 123
27.3. Intrri/Ieiri cu format ..................................................................... 125
27.4. Tratarea erorilor la operaiile de intrare/ieire ................................... 129
Cuprins .................................................................................................. 132
Bibliografie ........................................................................................... 136

C
+
+
P
O
O

09.01.12 136
Bibliografie

1. Dan Roman, Ingineria programrii obiectuale, Editura Albastr, Cluj_Napoca, 1996;
2. Dorin & Ioan Mircea Popovici, Iustin Tanase, Tehnologia orientat pe obiecte.
Aplicaii, Editura Teora, Bucureti, 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 nceptori, 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;