Documente Academic
Documente Profesional
Documente Cultură
Suport Curs C++ II PDF
Suport Curs C++ II PDF
Dorin BoKu
2001-2002
n loc de introducere
Dup iniierea n programare, cu sprijinul altor cursuri,
paralele cu programarea sau complementare n cel mai bun
neles al cuvntului, iat-ne btnd, cu nelepciune
sporit, la poarta unei lumi n care vom vedea aceleai
concepte ntr-o micare care respect rigorile unui joc nou,
mult mai interesant din punct de vedere al mptimiilor n
ale programrii. Avem de lmurit i adncit dou teme de
meditaie mari i importante pentru formarea oricrui
informatician :
Paradigma programrii obiect orientate
Universul C++ ale crui origini vin dinspre C i
dinspre nceputurile dintotdeauna ale programrii.
Dup experienele cursurilor introductive n programare, n
prezentul curs voi deplasa accentul de la ct mai mult
despre la esenialul despre, ceea ce va aduce
beneficii tuturor, sper.
Pentru titularul de curs este un prilej (nu tocmai comod) de
a scoate n eviden cunotinele i abilitile
indispensabile unei cltorii la captul creia, cei care nu
au abandonat, primesc certificatul simbolic de Oameni
care au ncercat limitele unui limbaj de cotitur pentru orice
programator. Care este rezultatul unei astfel de ncercri?
Depinde, ca ntotdeauna, de curiozitatea i complexul de
motive care i nsoesc pe participanii la cltorie.
Multe dintre tainele programrii n C/C++ vor trebui aflate n
momentul n care, optnd pentru meseria de specialist n
ingineria softului, vei avea motive, timp i condiii s o
facei.
Studentul care citete acest suport de curs trebuie s
neleag un lucru elementar: fr determinare clar nu se
poate face nimic cu temeinicie; dincolo de determinare se
afl foarte mult munc, nelept drmuit ntre
numeroasele borne care ateapt s fie trecute, cu o not
care s certifice un anumit coeficient de inteligen.
Autorul
Auto
Break
Case
Char
Const
Continue
Default
Do
struct
Int
double
switch
Long
else
typedef
Register
enum
union
Return
extern
unsigned
Short
float
for
void
Signed
Sizeof
goto
volatile
while
Static
if
Tabelul 1 Cele 32 cuvinte-cheie definite de standardul ANSI C
Directive preprocesor
includ
nevoie
Seciunea executabil
2 Expresii n C
n aceast seciune vom trece n revist propunerile limbajului C n ceea ce
provete posibilitatea de a utiliza expresii. Toate limbajele de programare
acord o atenie special noiunii de expresie deoarece, n ultim analiz, orice
transformare a datelor de intrare ale unui program este realizat prin intermediul
uneia sau a mai multor expresii. Aa cum vom descoperi pe parcurs, C este un
limbaj mult mai flexibil dect alte limbaje n materie de definire i utilizare a
expresiilor. Ceea ce este foarte limpede n acest moment este faptul c
expresiile sunt realizate cu ajutorul elementelor atomice numite date i
operatori. Datele pot fi reprezentate cu ajutorul constantelor sau prin intermediul
variabilelor. Ajungem, evident, la problema tipurilor de date suportate de C.
Tip de dat
char
unsigned char
signed char
int
unsigned int
signed int
short int
unsigned short int
signed short int
long int
signed long int
unsigned long int
float
double
long double
10
liter sau o liniu de subliniere; urmtoarele pot fi litere, cifre sau liniua de
subliniere.
Exemple de identificatori:
Coreci
numr_de pagini
_limita1
ok_
Incoreci
1_valoare_returnat
ok!
switch..conversie
2.4 Variabile C
Aa cum s-a aflat i n alte mprejurri, o variabil este numele unei locaii de
memorie utilizat pentru a pstra o valoare care poate fi modificat de
program.
nainte de a fi utilizate n program, variabilele trebuie declarate. Declararea unei
variabile n C are forma:
<Tip> <List_de_variabile>;
<Tip> trebuie s fie un tip de dat valid (predefinit sau definit de utilizator)
precedat, eventual, de un specificator de conversie.
<List_de_variabile> poate consta dintr-un nume de identificator sau mai multe
nume de identificatori separate prin virgul.
Exemple de declaraii de variabile:
int nr_pag;
char opt,ch;
unsigned i, j;
Variabilele se pot declara n trei moduri: n interiorul funciilor, n cadrul definiiei
parametrilor funciei i n afara oricrei funcii. Prin urmare, este vorba despre
variabile locale, parametri formali i variabile globale.
11
12
numar:);
scanf(%d,&i);
if (i>0)
{
char nume [40];
printf(Numele Dvs.:);
gets(nume);
}
}
Din exemplul de mai sus reinem doar faptul c, n situaia n care numrul
preluat de la tastatur (cu ajutorul rutinei de uz general scanf ) este mai mare
dect zero, atunci devine activ blocul de cod n care se declar variabila nume.
Aceast variabil este distrus la ieirea din acest bloc de cod.
Prin urmare, un avantaj potenial: variabilei nume i se aloc memorie numai
dac se activeaz blocul de cod, ceea ce nseamn economie de memorie.
Este absolut evident faptul c se declar ntr-un bloc de cod una sau mai multe
variabile strict necesare n acest bloc de cod; n acest mod prevenim, ntr-o
oarecare msur, apariia unor efecte secundare. Mai semnalm o diferen
important ntre modul de declarare a variabilelor locale n C fa de C++.
n C trebuie declarate toate variabilele locale la nceputul blocului n care
intenionm s le definim, nainte de orice instruciune executabil. n C++ nu
mai exist aceast restricie. Astfel c secvena de cod C:
void f(void)
{
int i;
i=10;
int j;
j=20;
}
este considerat greit de un compilator C i perfect acceptabil de ctre un
compilator C++.
Deoarece variabilele locale sunt create i distruse la fiecare intrare, respectiv
ieire din blocul n care au fost declarate, coninutul lor se pierde odat cu
prsirea blocului. Acest lucru este important s se tie cnd apelm o funcie.
La apelarea ei sunt create variabilele locale iar la ncheierea ei acestea sunt
distruse, deci variabilele locale nu pstreaz valorile lor ntre apelri. Putem
determina compilatorul s pstreze aceste valori utiliznd specificatorul de
stocare static asupra cruia vom reveni.
14
15
16
17
Exemplu de constant
1, 234, 2000, -243
100000, 23000L, -45L
9, -2000
10000U, 900U, 45000
120.15F, 3.75e-5F
120.15, 22122122, -0.9876432
1000.25L
Tabelul 3 Exemple de constante numerice
Dup cum se vede, constantele n virgul mobil sunt asimilate implicit tipului
double.
Constante hexazecimale i octale
Deoarece exist numeroase situaii n care avem nevoie de referiri la sistemele
de numeraie octal i hexazecimal, C permite utilizarea constantelor octale i
hexazecimale astfel:
O constant octal ncepe cu 0 (zero).
Exemplu:
int octala=017; /*In zecimal 15 */
O constant hexazecimal ncepe cu 0x.
Exemplu:
int hexa =0x100; /*In zecimal 256*/
18
Constante de tip ir
C admite, cum era i firesc i constanta de tip ir de caractere. O constant ir
este o succesiune de caractere delimitat de ghilimele. A nu se confunda irurile
de caractere cu caracterele. a i a sunt constante de tipuri diferite( disticie
care, n Pascal, nu este operat sintactic, vorbind.
Constante de tip backslash caracter
ncadrarea constantelor de tip caracter ntre apostrofuri funcioneaz pentru
majoritatea caracterelor afiabile. ns, altele, puine la numr, sunt imposibil de
introdus de la tastatur (constanta BEL, de exemplu). n acest scop C introduce
constante speciale, de tip backslash caracter. C admite mai multe coduri
backslash, cum rezult i din Tabelul 4. Pentru a se asigura portabilitatea
programelor sunt indicate codurile backslash n locul codurilor lor ASCII.
Codul
\b
\f
\n
\r
\t
\
\
\0
\\
\v
\a
\N
\xN
Semnificaia
Backspace
form feed (=Salt la pagin nou)
CR+LF
CR
tab orizontal
Ghilimele
Apostrof
Null
Backslash
tabulare vertical
Alert
constant n octal; N este constanta
constant n hexazecimal; N este constanta
Tabelul 4 Coduri backslash n C
2.11 Operatori n C
C dispune de foarte muli operatori. De fapt, C acord acestora o importan mult
mai mare n comparaie cu alte limbaje. C definete, n esen, patru clase de
operatori: aritmetici, relaionali, logici i de aciune la nivel de bit. Pentru
anumite sarcini, C are operatori suplimentari.
Operatorul de atribuire
Operatorul de atribuire poate fi folosit, n C, n cadrul oricrei expresii valide,
lucru care nu este permis n majoritatea limbajelor de programare (inclusiv
Pascal), care trateaz operatorul de atribuire ca pe un caz de instruciune
special. Sintaxa de aplicare a operatorului de atribuire n C este:
<Nume_variabil> = <Expresie>;
unde
<Expresie>
poate fi o constant sau o construcie legal de
complexitatea cerut n context. Atenie, se folosete = n loc de :=.
19
Tipul expresiei
char
char
char
char
int
int
float
double
short int
int
long int
long int
float
double
long double
Atribuiri multiple
C permite atribuirea aceleeai valori mai multor variabile prin utilizarea atribuirii
multiple ntr-o singur instruciune de atribuire. De exemplu instruciunea:
x = y = z = 0;
20
Aciune
Scdere, de asemenea i minus unar
Adunare
nmulire
mprire
Modul
Decrementare
Incrementare
Tabelul 6 Operatori aritmetici n C
Exist, totui, o diferen ntre forma cu prefix i forma cu sufix, dac operatorii
sunt utilizai ntr-o expresie.
Atunci cnd operatorii preced variabila, C
efectueaz operaiile corespunztoare lor, nainte de a evalua expresia.
Atunci cnd operatorii succed variabila, C efectuiaz operaiile corespunztoare
lor, dup evaluarea expresiei. Majoritatea compilatoarelor C/C++ produc rapid
un cod obiect eficient pentru operaiile de incrementare i decrementare (cod
mai bun dect cel obinut prin utilizarea atribuirii clasice echivalente). Pe acest
considerent, recomandarea de a utiliza aceti operatori de cte ori este posibil
este fireasc. n sfrit, ordinea de preceden a operatorilor aritmetici este:
++, -- (minus unar)
*, /, %
+, -
Operatori relaionali
Aciune
Mai mare dect
Mai mare sau egal
Mai mic dect
Mai mic sau egal
Egal
Diferit
Operatori logici
Aciune
AND (I)
OR (SAU)
NOT (NEGAT)
Tabelul 7 Operatorii relaionali i logici n C.
22
!
>, >=, <, <=
==, !=
&&
||
De ordinul cel mai cobort
Tabelul 8 Relaia de preceden ntre operatorii relaionali i logici
Evident, parantezele pot fi utilizate pentru a modifica ordinea fireasc de
evaluare a unei expresii relaionale i/sau logice.
De ordinul cel mai nalt
Aciune
AND
OR
OR exclusiv (XOR)
Complement fa de 1 (NOT)
Deplasare la dreapta
Deplasare la stnga
Tabelul 9 Operatorii de aciune pentru bii
23
Sensul operaiei de shiftare este cel precizat la un curs de Bazele logice ale
sistemelor de calcul.
24
O atribuire de tipul :
adr=&Numar_Elemente;
este util pentru a obine n variabila adr adresa din memorie a variabilei
Numar_Elemente. Aceast adres este adresa locaiei din memorie ncepnd de
la care se pstreaz coninutul variabilei Numar_Elemente.
Al doilea operator pentru pointeri este * , oarecum complementar operatorului
&. i operatorul * este unar, returnnd valoarea din variabila localizat la
adresa specificat. Astfel , dup execuia secvenei:
adr=&Numar_Elemente;
nr=*adr ;
variabila nr va conine aceeai valoare cu variabila Numar_Elemente,
presupunnd c cele dou variabile sunt compatibile ca tip.
Evident, exist, din punct de vedere al utilizatorului, primejdia de a utiliza confuz
aceti doi operatori, din moment ce * mai nseamn i nmulire iar & mai
nseamn i i logic la nivel de bii.
Variabilele care pstreaz pointeri trebuie declarate ca atare. Sintaxa de
declarare a unei variabile pointer este:
<Tip de baz> * <Nume_Variabila>;
Exemplu
#include <stdio.h>
void main(void)
{
int destinatar,sursa;
int *m;
sursa=10;
m=&sursa;
destinatar=*m;
printf (%d, destinatar);
}
Operatorii & i
destinatar .
25
sizeof este un operator unar utilizat n timpul compilrii care returneaz lungimea
n octei a variabilei sau a specificatorului de tip dintre parantezele asociate de
sintax operatorului. Sintaxa de utilizare a operatorului:
sizeof ( <Nume_Variabila>)
sau
sizeof (<Specificator_ de_ tip>)
sau
clrscr() /* Stergere ecran n mod text */
Acest tip de comentariu nu poate fi imbricat.
Compilatoarele C++ accept i comentarii care ncep cu secvena //, dar se pot
ntinde pe o singur linie, astfel:
clrscr() // Stergere ecran n mod text.
27
28
3.2
Instruciuni de selecie n C
31
32
33
gotoxy(20,14);
cout<<"Factorial("<<nr<<")="<<fact(nr);
getch();
}
long int fact(int n)
{
long int f;
int i;
f=1;
/*------------------------------------------------------------------/* Bucla for clasic cu o singur variabil de control
/*------------------------------------------------------------------for (i=2;i<=n;i++)
f=f*i;
return f;
}
Exemplul de cod C prezentat mai sus permite calculul factorialului pentru un
numr natural dat. Exemplul arat, anticipnd, modul de utilizare a conceptului
de funcie n C++.
Cteva variaiuni pe tema buclei for
Sintaxa C permite variante dintre cele mai neatepate de definire a unor bucle
for. Rigiditatea buclei for din Pascal este nlocuit n C cu o sintax care eman
mai mult putere, flexibilitate i aplicabilitate n situaii specifice de programare.
Una dintre cele mai folosite variaiuni folosete operatorul virgul, pentru a
permite ca bucla s fie controlat de dou sau mai multe variabile. De exemplu,
variabilele x i y controleaz urmtoarea bucl i amndou sunt iniializate n
interiorul instruciunii for.
:
for (x=0,y=0;x+y<10;++x)
{
y+=1; //Aceast scriere reste echivalent cu y=y+1;
printf(Y= %d,y);
}
:
Prezentm, mai jos, un exemplu practic de utilizare a unei bucle for controlat de
dou variabile: afiarea unui ir de caractere ncepnd de la ambele capete,
mergnd ctre mijlocul irului. Se observ prezena fiierului header <dos.h> n
care se afl prototipul funciei delay().
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>;
//Semnatura functie converg
34
35
#include <stdio.h>
#include <conio.h>
#include <ctype.h> //Contine prototipul functiei toupper
void main()
{
int sw;
char ras;
sw=1;
/* Bucla while n aciune
while(sw)
{
gotoxy(20,12);
printf("Continuam(D,N):");
ras=getch();
if (toupper(ras)=='N')
sw=0;
}
}
Bucla do-while (repetitive cu numr necunoscut de pai condiionate
posterior)
Spre deosebire de buclele for i while, care testeaz condiia din bucl la
nceputul execuiei lor, bucla do-while o verific la sfrit. Aceasta nseamn c
bucla do-while se execut cel puin odat. Forma sa general este:
do {
<Instruciune>;
} while <Condiie>;
Bucla do-while se repet pn cnd <Condiie> devine fals. Dm, mai jos, un
exemplu practic de utilizare a buclei do-while (afiarea/ selectarea opiunilor unui
program C).
:
char prelopt()
{
int c;
clrscr();
gotoxy(20,9);
printf( "Optiunile programului...");
gotoxy(20,11);
printf("1-Preluare elemente vector");
gotoxy(20,12);
printf("2-Determinare suma");
gotoxy(20,13);
printf("3-Terminare program");
36
gotoxy(20,15);
printf("Optiunea Dvs.:");
/* Utilizare bucl do-while
do
c=getch();
while ((c!='1')&&(c!='2')&&(c!='3'));
return c;
};
:
Alte instruciuni C
Aa cum rezult i din exemplele prezentate, n C mai sunt intens folosite
urmtoarele instruciuni: return, exit, break , continue i goto.
Instruciunea return este utilizat pentru ntoarcerea dintr-o funcie. Este
considerat ca instruciune de salt deoarece determin execuia programului s
revin la prima instruciune dup funcia apelat n care apare return. Forma
general a instruciunii return este:
return [<Expresie>]
Aceast sintax arat c dac <Expresie> este prezent atunci rezultatul
evalurii expresiei este valoarea returnat de funcie. O funcie void nu trebuie
s returneze nimic, deci return poate s apar fr <Expresie>. ntr-o funcie
return poate s apar de cte ori este necesar. n C++ o funcie care nu este
void trebuie s returneze o valoare.
Funcia exit()
Este utilizat pentru ieirea imediat dintr-un program, returnnd, eventual un
cod de retur. Sintaxa de apel este:
exit (<Cod_de_retur>);
<Cod de retur> poate fi interpretat de procesul care a apelat programul, de
regul, sistemul de operare. Exit acioneaz ca un break generalizat.
Instruciunea break
Are dou utilizri. Poate fi folosit, dup cum am vzut deja pentru a ncheia un
case dintr-o instruciune switch, sau pentru a determina ncheierea imediat a
unei bucle.
Instruciunea continue
Foreaz trecerea la urmtoarea iteraie a unei bucle, determinnd ignorarea
restului codului iteraiei n care se afl.
Nu facem meniuni speciale referitor la instruciunea goto.
37
38
39
}
while (car!='\033');
}
Prototipul funciei toupper() se afl (aa cum am mai spus-o) n fiierul antet
ctype.h. Se observ c citirea se face cu ecou pe ecranul monitorului. Este cazul
s spunem c programatorul n C/C++ are de fcut o serie de descoperiri
folositoare n ceea ce privete oferta numeroaselor fiiere antet livrate odat cu
compilatorul. Prezentarea tuturor acestor funcii, fie i numai prina antet, nu este
de loc o treab uoar, din punct de vedere al volumului. De aceea. n acest
suport de curs adresm cititorului invitaia de a descoperi, cu ajutorul help-ului on
line i a unor cri care nu fac economie de spaiu, potenialul structurat n
fiierele antet.
40
#include <stdio.h>
#include <conio.h>
void main()
{
char s;
char *p;
clrscr();
gotoxy(20,10);
p=&s
printf("Introduceti un sir de caractere:");
gets(p);
gotoxy(20,11);
printf("Sirul introdus
:");
puts(p);
getch();
clrscr();
}
Operaii I/O cu iruri de caractere se pot efectua i cu funciile scanf() i printf(),
mult mai versatile dect gets() i puts() , dup cum vom vedea n continuare.
printf()
Returneaz, cu destinaia ecran, numrul de caractere scrise sau, dac apare o
eroare, o valoare negativ. Parametrul format se compune din dou tipuri de
simboluri. Primul tip l formeaz caracterele care vor fi afiate pe ecran. Al doilea
tip se refer la specificatorii de format cu ajutorul crora se stabilete modul n
care sunt afiate argumentele care urmeaz. Un specificator de format ncepe cu
un semn % i este urmat de un cod de format. Trebuie s existe acelai numr
de argumente ca i acela al specificatorilor de format i, totodat, specificatorii
de format i argumentele se asociaz n ordinea de la stnga la dreapta.
41
Format
Caracter
Numere ntregi n baza 10, cu semn
Numere ntregi n baza 10, cu semn
Notaie tiinific (cu litera e)
Notaie tiinific (cu litera E)
Numr zecimal n virgul mobil
Folosete %e sau %f , anume, care din ele este mai mic
Folosete %E sau %f , anume, care din ele este mai mic
Numr n octal, fr semn
ir de caractere
Numere ntregi zecimale fr semn
Numere hexazecimale fr semn (cu litere mici)
Numere hexazecimale, fr semn, cu litere mari
Afieaz un pointer
Argumentul asociat este un pointer de tip ntreg n care a fost
plasat numrul de caractere scrise pn atunci.
Afieaz un semn %
clrscr();
printf("Acesta%n este un test...\n",&numara);
printf("Aliniere la dreapta.......\n");
printf("%10d\n",numara);
printf("Aliniere la stanga .......\n");
printf("%-d\n",numara);
printf("Completare cu zerouri.....\n");
printf("%010d\n",numara);
getch();
}
scanf()
Este o rutin de uz general pentru intrri de la consol. Ea poate s citeasc
toate tipurile de date ncorporate i s fac automat conversia numerelor n
format intern corect. Se aseamn mult cu complementara ei printf(). Ca funcie,
scanf() returneaz numrul de elemente crora li s-a atribuit cu succes o
valoare. Dac apare o eroare scanf() returneaz EOF. Argumentul format
determin modul n care vor fi citite valorile n variabilele din lista de argumente.
Codurile de format disponibile pentru scanf() sunt prezentate n tabelul de mai
jos.
Cod
%c
%d
%I
%e
%E
%f
%g
%o
%s
%u
%x
%p
%n
%u
%[]
Format
Citete un singur caracter
Citete un numr ntreg n baza 10
Citete un numr ntreg n baza 10
Citete un numr n virgul mobil
Citete un numr n virgul mobil
Citete un numr n virgul mobil
Citete un numr n virgul mobil
Citete un numr n octal
Citete un ir de caractere
Numere ntregi zecimale fr semn
Citete un numr n hexazecimal
Citete un pointer
Argumentul asociat este un pointer de tip ntreg n care a fost
plasat numrul de caractere citite pn atunci.
Citete un ntreg fr semn
Caut un set de caractere
Tabelul 10. O parte din codurile pentru formatarea operaiilor I/I relativ la
periferice standard
Primul exemplu de cod prezentat mai jos ilustreaz ideea de scanset posibil la
utilizarea funciei scanf(). Definirea unui scanset nseamn, de fapt c citirea
corespunztoare unei variabile este validat ct timp caracterele citite se
potrivesc celor definite n scanset.
43
44
Constanta
LASTMODE
BW40
C40
BW80
C80
MONO
C4350
Valoare
-1
0
1
2
3
7
64
Mod Text
Caracterisrici
Precedentul mod text
Black and white
40 coloane
Color
40 coloane
Black and white
80 coloane
Color
80 coloane
Monochrome
80 coloane
EGA and VGA
50 linii
Tabelul 11. Moduri video text standard
Aceste moduri text pot fi selectate cu ajutorul funciei textmode(), al crei antet
se afl tot n conio.h i face parte tot din arsenalul C de lucru cu ecranul n mod
text. Tot n mod text, putem controla culorile textului i ale fondului (backgroundul). Sintaxa funciilor cu care realizm controlul culorilor este:
textcolor(<Culoare>);
textbackground(<Culoare>);
Parametrul <Culoare> poate lua una din valorile prezentate n tabelul de mai jos:
Constanta
Valoare
Fond
Text
BLACK
0
Da
Da
BLUE
1
Da
Da
GREEN
2
Da
Da
CYAN
3
Da
Da
RED
4
Da
Da
MAGENTA
5
Da
Da
BROWN
6
Da
Da
LIGHTGRAY
7
Da
Da
DARKGRAY
8
Da
Da
LIGHTBLUE
9
Nu
Da
LIGHTGREEN
10
Nu
Da
LIGHTCYAN
11
Nu
Da
LIGHTRED
12
Nu
Da
LIGHTMAGENTA 13
Nu
Da
YYELLOW
14
Nu
Da
WHITE
15
Nu
Da
BLINK
128
Nu
***
Tabelul 12. Valori admise pentru culoare text si fond. Moduri video text standard
*** Codul BLINK se adaug la culoarea textului pentru a obine efectul de
blinking.
45
46
47
gotoxy(col,linia);
cprintf(sir);
}
}
//Construire fereastra cu rama dreptunghiulara de dimensiuni specificate
void makewin2(int ass,int oss,int adj,int odj)
{
short int i;
int sw;
sw=(ass>0) && (ass<81) && (adj>0) && (adj<81) && (ass<=adj);
sw=sw && (oss>0) && (oss<25) && (odj>0) && (odj<25) && (oss<=odj);
if(sw)
{
for(i=ass;i<=adj;i++)
{
gotoxy(i,oss-1);cprintf("\315");
gotoxy(i,odj+1);cprintf("\315");
}
for(i=oss;i<=odj;i++)
{
gotoxy(ass-1,i);cprintf("\272");
gotoxy(adj+1,i);cprintf("\272");
}
gotoxy(ass-1,oss-1);cprintf("\311");
gotoxy(adj+1,oss-1);cprintf("\273");
gotoxy(ass-1,odj+1);cprintf("\310");
gotoxy(adj+1,odj+1);cprintf("\274");
}
else
{
gotoxy(1,24);
printf("Coordonate ecran eronate!!!");
getch();
}
}
Ca un comentariu la exemplul de cod C prezentat mai sus i la alte exemple
prezentate deja, facem precizarea c directiva de includere #include este soluia
C pentru o modularizare a codului, orientat pe clasificarea tipurilor de
capabiliti de prelucrare n fiiere speciale numite fiiere antet. Fiierele antet
sunt incluse n codurile surs ale programelor noastre de cte ori avem nevoie
de o capabilitate al crei prototip se afl n acele fiiere antet.
48
5 Matrice i iruri
O matrice este o colecie de variabile de acelai tip, apelate cu acelai nume.
Accesul la un anumit element al matricei se face cu ajutorul unui indice. n C
toate matricile constau n locaii de memorie contigue. Cel mai mic indice
corespunde primului element iar cel mai mare ultimului element. Matricele pot
avea una sau mai multe dimensiuni. Ca i n alte limbaje, cea mai simpl matrice
este irul. n C irul este o matrice de caractere terminate cu un caracter NULL.
Aceast caracteristic ofer limbajului C mai mult putere i eficien dect
posed alte limbaje.
Semnalm, de asemenea, faptul c n C, exist o strns legtur ntre matrice
i pointeri.
49
float *p;
float sir[10];
p=sir;
Utilitate
Copiaz s2 n s1
Concateneaz s2 la sfritul s1
Returneaz lungimea lui s1
Returneaz 0 dac s1 i s2 sunt identice; un numr
mai mic dect 0 dac s1<s2 n sens lexicografic; un
numr mai mare dect 0 dac s1>s2 n sens
lexicografic.
strchr(s1,ch)
Returneaz un pointer la prima apariie a caracterului
ch n s1.
strstr(s1,s2)
Returneaz un pointer la prima apariie a lui s2 n s1.
Tabelul 13. Funcii C pentru lucrul cu iruri de caractere pstrate n fiierul antet
string.h
Atenie! strcmp() returneaz fals dac irurile sunt egale.
50
51
52
}
}
char prelopt()
{
char opt;
clrscr();
gotoxy(20,9);
cprintf("Optiunile programului....");
gotoxy(20,10);
cprintf("1- Preluare vectori");
gotoxy(20,11);
cprintf("2- Determinare ortogonalitate....");
gotoxy(20,12);
cprintf("3- Terminare program");
makewin2(20,9,55,12);
gotoxy(20,15);
cprintf("Optiunea Dvs.:");
makewin2(20,15,55,15);
do
{
gotoxy(20+strlen("Optiunea Dvs.:"),15);
opt=getch();
}
while (strchr(optiuni,opt)==NULL);
return opt;
}
void prelvec()
{
int i,col;
clrscr();
gotoxy(20,9);
cprintf("Dimensiune vectori:");
makewin2(20,9,20+strlen("Dimensiune vectori:"),9);
gotoxy(22+strlen("Dimensiune vectori:"),9);
col=strlen("Dimensiune vectori:");
makewin2(22+col,9,30+col,9);
gotoxy(23+col,9);
cscanf("%d",&dims);
clrscr();
gotoxy(20,9);
cprintf("Preluarea componentelor primului vector...");
makewin2(20,9,20+strlen("Preluarea componentelor primului vector..."),12);
for (i=0;i<dims;i++)
{
53
gotoxy(20,10);
cprintf("Elementul [ %d ]=",i);
cscanf("%f",&sir1[i]);
}
clrscr();
gotoxy(20,9);
cprintf("Preluarea componentelor celui de-al doilea vector...");
makewin2(20,9,20+strlen("Preluarea componentelor celui de-al doilea
vector..."),12);
for (i=0;i<dims;i++)
{
gotoxy(20,10);
cprintf("Elementul [ %d ]=",i);
cscanf("%f",&sir2[i]);
}
}
int ortogon()
{
float suma;
int i;
suma=0;
for (i=0;i<dims;i++)
suma=suma+sir1[i]*sir2[i];
clrscr();
if (suma)
{
gotoxy(20,10);
textcolor(RED+BLINK);
cprintf("Vectorii nu sunt ortogonali!!");
makewin2(20,10,21+strlen("Vectorii nu sunt ortogonali!!"),10);
getch();
textcolor(WHITE);
}
else
{
gotoxy(20,10);
textcolor(GREEN+BLINK);
cprintf("Vectorii sunt ortogonali!!");
makewin2(20,10,21+strlen("Vectorii sunt ortogonali!!"),10);
getch();
textcolor(WHITE);
};
}
54
55
6 Pointeri
Un pointer este o variabil care poate conine o adres de memorie. Aceast
adres este localizarea n memorie a unui alt obiect (de regul o alt variabil).
De exemplu, dac o variabil conine adresa alteia, despre prima se spune c
este un pointer la cea de-a doua. O variabil de tip pointer se declar n C astfel:
<Tip> * <Nume>;
unde <Tip> este tipul de baz al pointerului iar <Nume> este numele variabilei
pointer. Tipul de baz al pointerului definete tipul de variabil ctre care indic
pointerul. Practic, orice tip de pointer poate s indice orice n memorie.
Problema este, ns, c aritmetica pointerilor este integral raportat la tipul
de baz al pointerului.
Operatori pentru pointeri
Exist doi operatori speciali pentru pointeri: * i &. & este un operator unar care
returneaz adresa din memorie a operandului su. Operatorul * returneaz
valoarea nregistrat la adresa care l urmeaz. Evident c operatorul & se aplic
oricrui tip de variabil dar operatorul * cere dup el, neaprat, o variabil
pointer.
Expresii cu pointeri
n general, expresiile care implic pointeri se conformeaz acelorai reguli ca i
celelalte expresii. Exist, totui, o serie de particulariti pe care le vom evidenia
n acest paragraf n ceea ce privete aritmetica pointerilor.
Astfel:
Atribuirile sunt permise ntre pointeri concordani ca tip.
Pointerilor li se poate aplica operatorul ++ (incrementare) ca mai jos
:
int *p;
int mat[10];
:
p=&mat[0];
:
p++; // Operatorul de incrementare aplicat pointerului p
p- -;
:
n urma aplicrii operatorului de incrementare pointerului p, care coninea adresa
primului element al tabloului unidimensional mat, offset-ul acestuia este
incrementat cu 2, adic att ct este lungimea n octei a tipului de baz al
pointerului p.
Pointerilor li se poate aplica operatorul - - (decrementare) .
n urma aplicrii operatorului de decrementare pointerului p, care coninea
adresa celui de-al doilea element al tabloului unidimensional mat, offset-ul
acestuia este decrementat cu 2, adic att ct este lungimea n octei a tipului de
baz al pointerului p.
56
De asemenea, putem aduna sau scdea ntregi la, sau din pointeri. De
exemplu:
:
p=p+10;
:
face ca p s indice al 10-lea element de acelai tip cu tipul de baz al lui p,
relativ la elementul curent. n exemplul de mai jos ilustrm utilitatea aritmeticii
pointerilor n contextul lucrului cu matrice.
#include<stdio.h>
#include<conio.h>
int matr[10][10];
//matrice de intregi bidimensionala
int *p;
// pointer la intregi
int dimm;
void main()
{
int i,j,el;
clrscr();
gotoxy(20,10);cprintf("Dimensiune matrice :");
scanf("%d",&dimm);
clrscr();
for(i=0;i<dimm;i++)
for(j=0;j<dimm;j++)
{
gotoxy(20,12);
cprintf("Elementul[ %d , %d ]=",i,j);
scanf("%d",&el);
matr[i][j]=el;
};
p=&matr[0][0];
//p refera primul element al matricei
for (i=0;i<dimm;i++)
cprintf("\r\n Ref_poin=%d",*(p+i));
//modificare offset p in expresie
getch();
p=&matr[0][0];
for (i=0;i<dimm;i++)
{
cprintf("\r\n Ref_poin=%d",*(p));
p=p+1;
//modificare offset p prin incrementare
}
getch();
p=&matr[0][0];
for (i=0;i<dimm;i++)
{
cprintf("\r\n Ref_poin=%d",*(p));
p++;
57
}
getch();
}
Pointerii pot fi comparati n cadrul expresiilor relaionale. Dai pointerii p
i q, este perfect valabil instruciunea:
if (p<q) cprintf (p indica o memorie de adresa mai mica decat q\n);
Evident, n C se poate vorbi de matrice de pointeri, de indirectare multipl i,
evident, de alocarea dinamic a memoriei aferente unor pointeri.
Funcii de alocare dinamic n C
Pointerii ofer suportul necesar pentru sistemul puternic de alocare dinamic a
memoriei n C. Alocarea dinamic este caracteristica prin care un program poate
obine memorie n timpul execuiei. Dup cum se tie, variabilelor globale li se
aloc memorie n timpul compilrii. Variabilele locale folosesc memoria de tip
stiv. n mod cert, nici variabilele globale nici cele locale nu pot fi adugate n
timpul execuiei programului. Exist situaii n care necesarul real de memorie
este cunoscut de-abia n timpul execuiei programului.
Chiar dac C++ accept pe deplin sistemul de alocare dinamic al lui C,
el i definete propriul sistem, care conine mai multe mbuntiri fa de
cele din C.
Memoria alocat de funciile de alocare dinamic din C este obinut din HEAPzona de memorie liber situat ntre zona permanent a memoriei programului i
stiv.
Nucleul sistemului de alocare din C const din funciile malloc() i free().
Aceste instrumente de alocare lucreaz n pereche, folosind zona de memorie
liber pentru a stabili i a pstra o list cu memoria disponibil.
Funcia malloc() aloc memorie, avnd urmtorul prototip:
void *malloc(size_t numar_de_octei);
n acest prototip, numar_de_octei este numrul de octei din memorie pe care
dorim s-l alocm programului. Funcia malloc() returneaz un pointer de tipul
void, ceea ce nseamn c l putei atribui oricrui tip de pointer.
Prototipul funciei free este:
void free(void *p);
Funcia free returneaz n sistem memoria alocat anterior pointerului p. Este
esenial s nu se apeleze free cu un argument impropriu; deoarece acest fapt
poate aduce prejudicii gestiunii de ctre sistem a memoriei libere. Exemplul de
mai jos arat modul efectiv de utilizare a funciilor malloc i free, precum i
58
59
7 Structuri
O structur este, pragmatic vorbind, un grup de variabile reunite sub acelai
nume, ceea ce permite un mod convenabil de manipulare a unor date care au
afiniti semantice ntre ele. O declarare de structur formeaz un ablon care
poate fi folosit pentru a crea structuri efective. n C, variabilele care fac parte din
structur se numesc membri ai structurii. Uzual, membrii structurii se mai
numesc i elemente sau cmpuri. Aa cum vom vedea mai jos, o structur
poate ncapsula i metode de prelucrare a datelor, dac programatorul dorete
s abstractizeze tipuri de date cu suport struct.
Sintaxa general pentru declararea unei structuri este:
struct <Nume_generic>
{
<Tip> <Nume_membru_1>;
<Tip> <Nume_membru_2>;
:
<Tip> <Nume_membru_n>;
:
<Tip returnat> <Nume functie>(<Lista de parametri>);
} <Variabila_1>,[<Variabila_k>];
n cazul n care n definiia structurii este ncapsulat i o metod atunci la
implementare se folosete sintaxa:
<Tip returnat> <Structur>::<Nume functie>(<Lista de parametri>);
{
//Corp funcie
};
Pentru mai mult claritate se poate urmri exemplul de mai jos.
#include<stdio.h>
#include<conio.h>
typedef struct
{
char matricol[6];
char nume[30];
float media;
void setstud(char matr[],char num[],float med);
} TStud;
void TStud::setstud(char matr[],char num[],float med)
{
strcpy(matricol,matr);
strcpy(nume,num);
media=med;
60
};
void main()
{
clrscr();
TStud stud;
stud.setstud("12","Mihai Guramare",10);
printf("Matricol :%s\n",stud.matricol);
printf("Nume
:%s\n",stud.nume);
printf("Media
:%f",stud.media);
getch();
}
Dup cum se vede deja, numele variabilei structurate, urmat de un punct i
numele membrului permite adresarea acelui membru. Adic, n general vorbind:
<Variabila_structurat> . <Nume_membru>
n codul de mai jos se arat modul concret de declarare a unei structuri i de
asociere a acestei declaraii cu un nume de tip prin intermediul cuvntului cheie
typedef.
#include<conio.h>
#include<iostream.h>
#include<string.h>
void main()
{
typedef struct TPers{
char nume[30];
float salariu;
} TPers;
TPers pers;
strcpy(pers.nume,"Test typedef + struct.");
pers.salariu=1200000;
clrscr();
cout<<pers.nume<<"\r\n"<<pers.salariu;
getch();
}
n mod evident, structurile pot fi asociate i cu pointerii
prin declaraii asemntoare celor din codul alternativ de
mai jos.
#include<conio.h>
#include<iostream.h>
#include<string.h>
void main()
{
61
int nr=1;
int *pointer;
void main()
{
int i;
pointer=&nr;
memcpy(&Octet,pointer,sizeof(int));
clrscr();
printf("Bitul 0
: %i\n",Octet.bit);
printf("Bitul de semn: %i\n",Octet.bits);
getch();
}
63
8 Uniuni
O uniune este o locaie de memorie care este partajat n momente diferite ntre
dou sau mai multe variabile diferite.
Sintaxa generala i modul de utilizare pot fi deduse din exemplul de mai jos.
#include<stdio.h>
#include<conio.h>
#include<string.h>
typedef union
{
int codsal;
float salar;
} TUSal;
void main()
{
clrscr();
TUSal vunion;
vunion.codsal=10;
printf("Cod confidential salariu:%i\n",vunion.codsal);
vunion.salar=1000.50;
printf("Salariu
:%f",vunion.salar);
getch();
}
n acest exemplu variabilele codsal i salar, de tipuri diferire, partajeaz
aceeai locaie de memorie, dar, important de tiut, n momente diferire ale
execuiei unui programului, dup cum se observ, de altfel i din exemplu.
ncheiem aici partea intitulat BAZELE C++. LIMBAJUL C, cu meniunea c
exist nenumrate alte aspecte ale programrii n C care necesit timp i
rbdare pentru a nelege toate consecinele stilului C de programare, nelegere
folositoare i n abordarea C++. Dintre aceste aspecte semnalez: fluxurile C,
abloanele C, suprascrierea funciilor, etc. Pentru toate acestea exist, ns
suport C++ mult mai adecvat i mai comod de multe ori pentru programarea cu
adevrat n spirit obiect orientat.
64
II Programarea C++
65
1 Introducere
Programarea orientat pe obiecte (POO) este expresia, n materie de codificare
a proiectelor, a paradigmei care presupune modelarea orientat pe obiecte a
sistemelor soft.
POO este o paradigm care ctig tot mai muli adereni datorit calitilor
pe care le au produsele i sistemele soft realizate n spiritul conceptelor i
principiilor promovate de aceasta. Rezultant a unor direcii diverse de
cercetare i experimentare (programare structurat, programare modular,
programare orientat pe structuri abstracte, reprezentarea cunotinelor n
sisteme expert, etc.) POO, aplicat corect poate rezolva, parial sau
integral, multe din problemele obsedante ale ingineriei softului, n genere:
reutilizarea codului, extinderea/modificarea cu minim de efort a sistemelor
soft, ascunderea detaliilor de implementare fa de anumite categorii de
utilizatori ai sistemelor soft. n acest mod platforma POO poate ajuta
programatorii i companiile de soft s realizeze produse i sisteme soft
performante, n timp util i la un pre sczut.
1. 1 Concepte POO
Orice demers de modelare orientat pe obiecte apeleaz la o serie de concepte
specifice paradigmei POO.
Astfel, pentru modelarea unui sistem soft se opereaz frecvent cu:
1. Concepte ale teoriei generale a sistemelor (sistem, subsistem,
descompunere, agregare, structur, etc.)
2. Concepte care provin din arsenalul conceptual al modelrii n genere
a sistemelor i produselor soft (modul, modularizare, interfa, tip de dat,
structur de date, ascunderea informaiei, etc.).
Tuturor acestora li se adaug principiile cu ajutorul crora aceste concepte devin
operaionale.
Paradigma POO a intrat n competiia pentru modernizarea i mbuntirea
real a procesului de realizare a unui sistem soft cu un set propriu de concepte i
principii.
Prezentm mai nti conceptele cheie ale paradigmei POO.
Conceptul de clas, prin care se desemneaz o colecie de obiecte (de natur
material sau spiritual) care au n comun faptul c pot fi caracterizate similar
din punct de vedere informaional i comportamental.
Este evident faptul c identificarea unei clase este n mod normal, rezultatul unui
demers cognitiv care presupune caracterizarea unui obiect prin nsuirile lui
(informaionale i comportamentale) care i definesc apartenena la o anumit
clas de obiecte. Aadar, conceptul de clas adun laolalt datele i metodele
de prelucrare a acestora.
n esen definirea unei clase se bazeaz pe analiza, clasificarea i
abstractizarea nsuirilor obiectelor de un anumit tip.
66
67
Este evident faptul c obiectul care emite mesajul trebuie s cunoasc protocolul
de comunicaie al obiectului receptor.
De asemenea, se subnelege faptul c mesajul trimis de obiectul emitor va
provoca o reacie(= un rspuns) din partea obiectului receptor.
Conceptul de metod prin intermediul cruia se d o expresie procedeelor care
definesc comportamentul i, direct sau indirect, protocolul de comunicaie al unei
clase.
Pentru mai mult exactitate, este bine s se neleag faptul c "metoda" este o
denumire generic pentru un procedeu de prelucrare care face parte din
protocolul de comunicare al unei clase. Metoda poate fi implementat n C, de
exemplu, ca funcie, constructor sau destructor. Asupra semnificaiei noiunilor de
constructor i destructor vom mai reveni .
1. 2 Principiile POO
Noutatea POO, ca paradigm este ilustrat i de principiile pe care le
promoveaz pentru a completa potenialul oferit de concepte. Promovarea
sistematic a principiilor pe care le prezentm n continuare promite, dar
nu garanteaz, realizarea unor produse, sisteme sau platforme soft
remarcabile din punct de vedere al performanelor i al efortului de
ntreinere.
1.2.1 Principiul ncapsulrii
nelegerea acestui principiu presupune dou nivele de abordare.
@ Ca metod de concepie, ncapsularea se refer la capacitatea de a separa
aspectele externe ale unui obiect (interfaa), accesibile altor obiecte, de
aspectele implementaionale, interne obiectului, care sunt ascunse fa de
celelalte obiecte. Utilizatorul unui obiect poate accesa doar anumite metode ale
acestuia, numite publice, n timp ce atributele i celelalte metode i rmn
inaccesibile (acestea se numesc private).
ncapsularea este foarte important atunci cnd dorim s schimbm
implementarea anumitor metode (cu scopul de a optimiza un algoritm sau de a
elimina posibile erori).
ncapsularea ne va mpiedica s modificm toate caracteristicile obiectului iar
aplicaiile care utilizeaz obiectul nu vor avea de suferit deoarece protocolul de
comunicaie al obiectului motenit de la interfaa clasei (rezultatul ncapsulrii
ca metod de concepie) nu s-a schimbat.
@Ca implementare, la nivelul unui limbaj de programare, ncapsularea este
asigurat de exigenele sintactice specifice.
68
69
70
#include <conio.h>
#include <string.h>
#include <iostream.h>
// Definitie clasa fara declarare de variabile obiect.
class Persoana
{
public:
char nume[30];
int matricol;
float salariu;
void setfields(char n[30], int m, float s);
void afis();
};
// Implementare functie setfields
void Persoana:: setfields(char *n, int m, float s)
{
strcpy(nume,n);
matricol=m;
salariu=s;
}
// Implementare functie afis
void Persoana:: afis()
{
clrscr();
cout<<nume<<"\n"<<salariu;
getch();
}
//Implementare functie principala
void main()
{
// Declarare variabila obiect
Persoana pers;
pers.setfields("Radu Vasile",1,10000);
pers.afis();
}
n exemplul prezentat am folosit specificatorul de acces public pentru a permite
funciei principale, care a declarat variabila obiect pers, accesul la membrii clasei
definitoare a variabilei pers. n programarea obiect orientat adevrat n C++,
efectul de ascundere a membrilor unei clase este intens utilizat, interzicnd
71
72
int stack::pop()
{
if(top==0)
{
gotoxy(20,24);
cout<<"Depasire inferioara stiva!!!";
getch();
return 0;
};
top--;
return st[top];
}
//Functia principala
void main()
{
int i;
stack st1,st2;
st1.init();
st2.init();
for (i=0;i<=9;i++)
{
st1.push(i);
st2.push(9-i);
}
clrscr();
for (i=0;i<=9;i++)
{
gotoxy(35,wherey()+1);
cout<<st1.pop()<<"*****";
cout<<st2.pop()<<endl;
}
getch();
}
73
74
}
void main()
{
CD ob;
ob.setij(2,3);
ob.dispij();
ob.setk();
ob.dispk ();
}
//OK!
//OK
//ilegal!
//OK!, membru public n CD
75
ob.setk();
ob.disptot ();
ob.dispij();
//OK!
//ilegal! Membru protected n CD
}
Constructori i destructori
Este un fapt obinuit necesitatea ca unele elemente ale unui obiect s fie
iniializate. Pentru a degreva programatorul de o asemenea sarcin de rutin,
compilatorul C++ genereaz cod care permite obiectelor s se iniializeze
singure. Aceast iniializare automat este efectuat prin intermediul unei funcii
membru speciale a clasei definitoare numit constructor.
Constructorul este o funcie care are acelasi nume cu clasa.
Un constructor al unui obiect este apelat automat la crearea obiectului.
Un constructor al unui obiect este apelat o singur dat pentru obiecte
globale sau pentru cele locale de tip static.
Constructorul este o funcie fr tip ceea ce nu reclam, totui cuvntul
cheie void n locul tipului.
Pentru obiecte locale constructorul este apelat de fiecare dat cnd este
ntlnit declararea acestuia.
Complementul constructorului este destructorul. De multe ori un obiect trebuie
s efectueze anumite aciuni cnd este distrus.
Este evident faptul c obiectele locale sunt distruse la prsirea blocului n care
apar iar obiectele globale la terminarea programului.
Cnd este distrus un obiect, este apelat destructorul clasei definitoare.
Destructorul are acelai nume cu constructorul, dar precedat de un
caracter ~.
O clas are un singur destructor i acest destructor nu poate avea
parametri formali.
Att constructorul ct i destructorul, n C++ nu pot s returneze valori.
De semnalat faptul c n situaia n care programatorul nu specific un
constructor explicit la definirea unei clase, la crearea unei instane a clasei se
folosete constructorul implicit ataat de compilator fiecrei clase.
Constructorul implicit nu are parametri formali, ceea ce are drept consecin
faptul c nu este permis iniializarea la declarare a datelor membre ale
obiectelor.
De asemenea, constructorul implicit nu este generat n cazul n care clasa are
ataat un alt constructor fr parametri.
Programatorul poate nzestra clasa cu o proprie funcie constructor. n acest
scop trebuie inut cont de faptul c o metod constructor are ntotdeauna numele
clasei din care face parte.
Programatorul poate nzestra clasa i cu parametri formali ceea ce permite i o
formul elegant de iniializare a datelor membre ale obiectelor clasei respective.
76
77
y.dispa();
}
Evident, o clas poate avea mai muli constructori, ceea ce este tot n beneficiul
programatorilor.
Crearea obiectelor n C++
Obiectele pot fi create static sau dinamic.
Aa cum s-a vzut i n exemplul de mai sus sintaxa pentru varianta static este:
<Clasa> <Obiect>[(<Lista de valori>)];
sau
<Clasa> <Obiect>[=<Valoare>];
Sintaxa ne arat c odat cu crearea instanei se poate face i iniializarea
datelor membre ale obiectului cu ajutorul constructorilor parametrizai.
Pentru a nelege alocarea dinamic a memoriei pentru obiecte trebuie s facem
o scurt prezentare a problematicii alocrii dinamice structurate a memoriei n
C++.
Operatori de alocare dinamic a memoriei n C++
n C, alocarea dinamic a memoriei este realizat cu ajutorul funciior malloc() i
free().
Din motive de compatibilitate i nu numai, aceste funcii sunt valabile i n C++.
Totodat, C++ are un sistem alternativ de alocare dinamic bazat pe operatorii
new i delete.
Sintaxa general pentru new i delete este:
<Pointer>=new <Tip>;
delete <Pointer> ;
<Pointer> este o variabil pointer, compatibil ca tip cu <Tip>. Aadar, <Pointer>
poate pstra adresa ctre zona de memorie n care ncap date avnd tipul <Tip>.
De subliniat c operatorul delete trebuie folosit doar cu un pointer valid, alocat
deja prin utilizarea operatorului new. n caz contrar, rezultatele sunt imprevizibile.
Fa de malloc()i free(), operatorii new i delete prezint cteva avantaje:
@ new aloc automat memorie suficient pentru a pstra obiectele de
tipul specificat. Nu mai este necesar folosirea operatorului sizeof.
@ new returneaz automat un pointer de tipul specificat. Nu mai este
necesar s folosim modelatorii de tip ca n cazul funciei malloc().
@ Att new ct i delete pot fi suprancrcai, ceea ce v permite crearea
unui sistem propriu de alocare dinamic a memoriei. Despre suprancrcare
vom discuta n paragrafele 2.4 i 2.7 .
n plus, operatorul new mai are i alte capabiliti:
@Permite iniializarea memoriei alocate unui tip de baz cu o valoare dat,
utiliznd sintaxa:
78
79
80
{
if(top==0)
{
gotoxy(20,24);
cout<<"Depasire inferioara stiva!!!";
getch();
return 0;
};
top--;
return st[top];
}
//Functia principala
void main()
{
int i;
stack st1,st2;
for (i=0;i<=9;i++)
{
st1.push(i);
st2.push(9-i);
}
clrscr();
for (i=0;i<=9;i++)
{
gotoxy(35,wherey()+1);
cout<<st1.pop()<<"*****";
cout<<st2.pop()<<endl;
}
getch();
}
81
clas derivat ofer operaiile efective pe care le execut funcia. Utilizate static,
funciile virtuale se comport ca oricare alt funcie membru a clasei .
Capabilitile funciilor virtuale ies n eviden atunci cnd sunt apelate n context
dinamic.
Exemplu
#include <iostream.h>
#include <conio.h>
//Clasa de baza care are doua functii membri publici
//o functie ordinara
//cealalta functie virtuala
class CB
{
public:
void f()
{
cout<<"CB::f()"<<endl;
getch();
}
virtual void g() //funcie virtual
{
cout<<"CB::g()"<<endl;
getch();
}
};
//Clasa derivata din clasa de baza
class CD:public CB
{
public:
void f()
{
cout<<"CD::f()"<<endl;
getch();
}
virtual void g()
{
cout<<"CD::g()"<<endl;
getch();
}
};
//Functie care permite utilizarea polimorfismului
//Parametrul functiei este un pointer la un obiect de tip CB
//De retinut ca un parametru de tip CD este compatibil
//cu tipul lui p
82
83
84
cout<<abs(-10);
cout<<abs(-10.0);
cout<<abs(-10L);
getch();
}
int abs(int i)
{
gotoxy(20,10);cout<<"Varianta int !!! :";
return i<0 ?-i:i;
}
double abs(double d)
{
gotoxy(20,12);cout<<"Varianta double!!! :";
return d<0 ?-d:d;
}
long abs(long l)
{
gotoxy(20,14);cout<<"Varianta long !!! :";
return l<0 ?-l:l;
}
Acest program implementeaz i utilizeaz trei funcii cu acelai nume (abs())
dar diferite prin proprietile listelor de parametri formali. Fiecare returneaz un
mesaj specific i valoarea absolut a argumentului. Numele abs() reprezint
aciunea generic care urmeaz s fie efectuat, compilatorul fiind acela care
alege metoda potrivit tipului de parametru actual asociat cu numele funciei
generice. Este uor de bnuit puternicul impact al suprancrcrii n cazul
programrii generice.
Este posibil s se permit unei funcii care nu este membru al unei clase s aib
acces la membrii privai ai clasei declarnd-o ca funcie prieten a clasei (friend).
Aadar, o funcie prieten are acces la membrii private i protected ai clasei
creia i este prieten. Sintaxa pentru declararea unei funcii prietene este:
friend <Tip> >Nume_funcie>[(<Lista_parametri>)]
Declararea funciei friend se face n interiorul clasei dar implementarea nu este
legat de definirea clasei.
A se vedea i exemplul de mai jos pentru mai multe detalii.
#include<conio.h>
#include <iostream.h>
#define liber 0
#define ocupat 1
//Declarare anticipata clasa
class Clasa2;
class Clasa1
{
//<ocupat> daca o metoda a clasei a scris pe ecran
//<liber> in caz contrar
int stare;
public:
void setare_stare(int val);
friend int ecran_liber(Clasa1 a,Clasa2 b);
};
class Clasa2
{
//<ocupat> daca o metoda a clasei a scris pe ecran
//<liber> in caz contrar
int stare;
public:
void setare_stare(int val);
friend int ecran_liber(Clasa1 a,Clasa2 b);
};
void Clasa1::setare_stare(int val)
{
stare=val;
}
void Clasa2::setare_stare(int val)
{
stare=val;
}
86
87
88
89
};
void main()
{
complex tamp1,tamp2;
complex *pod1,*pod2;
complex ob1(10,10),ob2(11,11);
clrscr();
gotoxy(20,10);cout<<"Primul numar complex
->:";
ob1.disp_nc();
getch();
gotoxy(20,11);cout<<"Al doilea numar complex->:";
ob2.disp_nc();
getch();
ob1=ob1+ob2;
gotoxy(20,13);cout<<"Suma numerelor complexe->:";
ob1.disp_nc();
getch();
pod1=new complex(200,200);
pod2=new complex(300,300);
tamp1=*pod1;
clrscr();
gotoxy(20,10);cout<<"Al treilea numar complex
tamp1.disp_nc();
->:";
tamp2=*pod2;
gotoxy(20,11);cout<<"Al patrulea numar complex
tamp2.disp_nc();
->:";
90
91
92
Pentru sistemul I/O din C/C++ toate fluxurile sunt la fel dar nu i
fiierele.
Dac fiierul admite cereri de poziionare, deschiderea fiierului iniializeaz
pointerul de fiier la o valoare care indic nceputul fiierului. Pe msur ce se
fac operaii de citire/scriere, pointerul de fiier este incrementat corespunztor
naturii operaiei.
Un fiier se disociaz de un flux n urma operaiei de nchidere. Dac este nchis
un fiier deschis n operaii de scriere, coninutul fluxului asociat este scris la
dispozitivul extern (acest proces se numete flushing=golire a fluxului ).
Toate fiierele se nchid automat cnd programul se termin normal. n caz de
blocaj sau dac programul se termin ca urmare a apelului funciei abort()
fiierele nu se nchid.
Cu meniunea c n fiierul antet stdio.h se gsesc structurile de control de tip
FILE, indispensabile pentru lucrul cu fiiere n C, prezentm, n continuare
contextul C++ referitor la sistemul I/O.
Semnificaie
Echipament implicit
Intrare standard
Tastatura
Ieire standard
Ecran
Ieire standard pentru eroare
Ecran
Versiune cu memorie tampon pentru Ecran
cerr
Tabelul 15. Fluxurile predefinite C++
Fluxurile cin, cout, cerr corespund fluxurilor stdin, stdout, stderr din C. Implicit,
fluxurile standard sunt folosite pentru a comunica cu consola. ns, n mediile
care admit redirecionarea I/O, fluxurile standard pot fi redirecionate spre alte
echipamente sau fiiere.
93
Exemplu de folosire
cout<<dec<<intvar;
endl
cout<<endl
ends
cout<<ends
flush
cout<<flush
hex
cout<<hex<<intvar;
cin>>hex>>intvar
oct
cout<<oct<<intvar;
cin>>oct>>intvar;
cout<<resetioflags(ios::dec);
resetiosflags(long
f)
setbase(int baza)
cout<<setbase(10);
cin>>setbase(8);
setfill(int ch)
cout<<setfill(.);
cin>>setfill( );
setiosflags(long f)
cout<<setiosflags(ios::dec);
cin>> setiosflags(ios::hex);
94
Efect
Convertete ntregi n cifre
zecimale;
corespunde
formatului %d din C
Trimite o nou linie n
ostream
i
descarc
bufferul
Insereaz un caracter nul
ntr-un flux
Descarc bufferul fluxului
ostream
Conversie hexazecimal
corespunztoare
formatului %x din ANSI C
Conversie octal (formatul
%o din C)
Reiniializeaz biii de
formatare specificai de
argumentul ntreg de tip
long
Stabilete
baza
de
conversie la argumentul
ntreg (trebuie s fie
0,8,10 sau 16). Valoarea 0
este baza implicit.
Stabilete
caracterul
folosit pentru completarea
cmpurilor de mrime
specificat
Stabilete
biii
de
formatare specificai de
setprecision(int p)
setw(int w)
ws
double nr;
clrscr();
gotoxy(10,6);
nr=7./3.;
gotoxy(5,6);
cout<<"Afisare numar in virgula mobila/ format implicit...";
gotoxy(10,7);
cout<<nr;
gotoxy(5,9);
cout<<"Afisare numar in virgula mobila/ cu precizia specificata...";
gotoxy(10,10);
cout<<setprecision(10)<<nr;
gotoxy(5,12);
cout<<"Afisare numar in virgula mobila/ format virgula fixa...";
gotoxy(10,13);
cout.setf(ios::fixed);
cout<<setprecision(10)<<nr;
gotoxy(5,15);
cout<<"Afisare numar in virgula mobila/ format virgula fixa...";
gotoxy(10,16);
cout.setf(ios::scientific);
cout<<setprecision(10)<<nr;
gotoxy(5,18);
cout<<"Afisare numar in virgula mobila/ format virgula fixa...";
gotoxy(10,19);
cout.setf(ios::scientific|ios::showpos);
cout<<setprecision(10)<<nr;
getch();
}
Fiiere utilizator n C++
Chiar dac abordarea operaiilor I/O din C++ formeaz un sistem integrat,
operaiile cu fiiere (altele dect cele predefinite), sunt suficient de specializate
pentru a fi necesar s la discutm separat.
Pentru a efectua operaii I/O cu fiiere conform paradigmei C++, trebuie s
includei n programul Dvs. fiierul antet FSTREAM.H. Acesta definete mai
multe clase, printre care ifstream, ofstream i fstream. Aceste clase sunt
derivate din istream i, respectiv, din ostream la care ne-am referit i mai sus.
Deschiderea i nchiderea unui fiier
Un fiier se deschide n C++ legndu-l de un flux. nainte de a putea s
deschidei un fiier, trebuie, pentru nceput, s avei un flux. Exist trei tipuri de
96
Operaie
Adaug date n fiier
Cnd se deschide
pentru prima dat, opereaz
poziionarea n fiier la sfritul fiierului (ate nseamn la
sfrit)
Deschide fiierul n mod binar, inhibnd interpretarea
ios::binary
caracterelor <CR> <LF>
Deschide fiierul pentru citire
ios::in
Nu efectueaz deschiderea fiierului dac acesta nu exist
ios::nocreate
deja
Dac fiierul exist, ncercarea de a-l deschide pentru ieire
ios::noreplace
eueaz, cu excepia cazului n care ios::app sau ios::ate
sunt operate
Deschide fiierul pentru scriere
ios::out
Trunchiaz fiierul dac el exist deja
ios:trunc
Tabelul 17. Valorile parametrului care stabilete modul de deschidere a
unui fiier
Putei specifica mai mult de un mod de lucru pentru un fiier, folosind operatorul
pe bii SAU cu modurile respective. De exemplu, pentru deschiderea unui fiier
pentru ieire i poziionarea pointerului la sfritul lui se folosesc modurile
ios::out i ios::ate astfel:
ofstream oflux(o_fisier,ios::out | ios::ate);
ceea ce ne arat al doilea procedeu de deschidere a unui fiier, utiliznd
constructorul clasei ofstream sau, de ce nu, ifstream, dac este cazul.
Pentru a nchide un fiier, folosii funcia membru close(). Aceast funcie nu
preia nici un parametru i nu returneaz nici o valoare. De analizat utilizarea
funciei close() n exemplele care vor urma.
97
98
Exist dou modaliti de a scrie i citi date binare ntr-un fiier. Prima
modalitate se refer la utilizarea funciilor get() i put(). Aceste funcii sunt
orientate pe octei, ceea ce nseamn c get() va citi un octet de date iar put() va
scrie un octet de date.
Funcia get() are mai multe forme; o prezentm, n continuare, mpreun cu
omoloaga ei put(), pe cea mai des folosit:
istream &get(char &ch);
ostream &put(char ch);
Funcia get() citete un singur caracter din streamul asociat i memoreaz
valoarea sa n ch. De asemenea, se mai observ c funcia returneaz o
referin ctre flux. Funcia put() scrie ch n flux i returneaz fluxului o referin.
Ca un exemplu de utilizare a funciilor get() i put() prezentm codul de mai jos,
care realizeaz copierea unui fiier n altul. Dac numele executabilului asociat
acestui cod este copyf, atunci sintaxa de lansare n execuie a programului este:
copyf <fisier_sursa> <fisier_destinatie>
#include<stdlib.h>
#include <fstream.h>
void main(int argc, char *argv)
{
//Verific daca sunt suficiente argumente
if(argc<3)
{
cerr<<"Mod de utilizare : filecopy <fisier sursa> <fisier destinatie>\n";
exit(0);
}
//Deschide fisierul de intrare si il conecteaza la fluxul ins
ifstream ins(argv[1]);
if(!ins)
{
cerr<<"Nu pot deschide fisierul sursa:"<<argv[1];
exit(1);
}
//Deschide fisierul de iesire si il conecteaza la fluxul outs
ofstream outs(argv[2]);
if(!outs)
{
cerr<<"Nu pot deschide fisierul sursa:"<<argv[2];
exit(1);
}
//Citeste din sursa si scrie in destinatie
char c;
while(ins.get(c) && outs) outs.put(c);
99
}
A doua modalitate de a citi i scrie blocuri de date n binar este folosirea funciilor
din C++ read() i write(). Prototipurile lor sunt:
istream &read(unsigned char *buf, int numar);
ostream &write(const unsigned char *buf, int numar);
Funcia read() citete numar octei din fluxul asociat i l pune n buffer-ul indicat
de buf . Funcia write() scrie n fluxul asociat numar octei citii din buffer-ul spre
care indic buf.
Detectarea EOF
Putei s detectai sfritul fiierului folosind funcia membru eof() ,care are acest
prototip:
int eof();
Ea returneaz o valoare nenul cnd a fost atins sfritul fiierului; altfel,
returneaz zero. Utilizarea funciei eof() i alte elemente legate de lucrul cu
fiiere, prezentm n codul de mai jos, care realizeaz afiarea coninutului unui
fiier att n hexazecimal ct i n cod ASCII, atunci cnd codul asociat este
printabil.
#include <fstream.h>
#include <ctype.h>
#include <iomanip.h>
#include <stdlib.h>
#include<conio.h>
void main(int argc,char *argv[])
{
if (argc!=2)
{
cerr<<"Mod de utilizare : lishex <nume fisier CPP>\n";
exit(0);
}
ifstream in(argv[1],ios::in|ios::binary);
if (!in)
{
cerr<<"Fisierul nu poate fi deschis!";
exit(0);
}
register int i,j;
int count=0;
char c[16];
cout.setf(ios::uppercase);
clrscr();
100
while(!in.eof())
{
for(i=0;i<16 && !in.eof();i++)
{
in.get(c[i]);
}
if (i<16) i--;
for(j=0;j<i;j++)
cout<<setw(3)<<hex<<(int) c[j];
for(;j<16;j++)
cout<<"\t";
for(j=0;j<i;j++)
if(isprint(c[j])) cout<<c[j];
else cout<<".";
cout<<endl;
count++;
if(count==16)
{
count=0;
cout<<"Press ENTER to continue!";
getch();
clrscr();
cout<<endl;
}
}
in.close();
}
Accesul aleator n fiiere
n sistemul de I/O din C++, accesul aleator se efectueaz folosind funciile
seekg() i seekp(). Formele lor cele mai uzuale sunt:
istream &seekg(streamoff offset, seek_dir origine);
ostream &seekp(streamoff offset, seek_dir origine);
streamoff este un tip definit n IOSTREAM.H, capabil s conin cea mai mare
valoare valid pe care o poate avea offset, iar seek_dir este o enumerare care
are aceste valori:
ios::beg
ios::cur
ios::end
Sistemul de I/O din C++ opereaz cu doi pointeri asociai unui fiier. Unul este
pointerul de get , care specific unde va aprea urmtoarea operaie de intrare
n fiier. Cellalt este pointerul de put i specific unde va avea loc urmtoarea
101
102
103
104
clrscr();
i=10;
j=2;
k=13;
l=-7;
//Exemple de utilizare sablon
gotoxy(20,10);cout<<"Apel max cu parametri variabili de tip float..."<<max(k,l);
gotoxy(20,12);cout<<"Apel max cu parametri variabili de tip int ..."<<max(i,j);
gotoxy(20,13);cout<<"Apel max cu parametri valoare float ..."<<max(13.,-7.);
getch();
}
Prezentm, totodat, un exemplu de funcie generic pentru compararea unor
date dup valoarea unei chei ncapsulate n aceste date.
#include <conio.h>
#include <stdio.h>
#include <string.h>
#include <iostream.h>
#include <ctype.h>
//Definirea unei <functii generice> pentru compararea
//unor date dupa valoarea unei chei incapsulate
//in aceste date
template <class T>
int comp(T i1,T i2)
{
if (i1.key<i2.key) return -1;
if (i1.key==i2.key) return 0;
if (i1.key>i2.key) return 1;
};
//Structura aleasa pentru exemplificare
//cheia generica incapsulata este campul <key>
struct tpers
{
char np[30];
int key;
};
//Instantiere <struct tpers>
struct tpers tam,pers[50];
void main()
{
105
clrscr();
int i=0;
//***************************************
//Citire persoane de la tastatura
do
{
gotoxy(20,12);
cout<<"Numele persoanei:";clreol();
cin>>pers[i].np;
gotoxy(20,13);
cout<<"Matricola:";clreol();
cin>>pers[i].key;
gotoxy(20,14);
cout<<"Mai aveti(D,N):";
i++;
}
//***************************************
//Listare persoane pe ecranul monitorului
//in ordinea citirii de la tastatura
while(toupper(getch())!='N');
clrscr();
cout<<"Listare persoane in ordinea citirii de la tastatura..."<<endl;
cout<<"_______________________________________________"<<endl;
for(int j=0;j<i;j++)
{
if (wherey()>10)
{
cout<<"______________________________________________"<<endl;
cout<<"Pentru continuare apasati o tasta..."<<endl;
getch();
clrscr();
cout<<"Listare persoane in ordinea citirii de la tastatura..."<<endl;
cout<<"_______________________________________________"<<endl;
};
cout.width(30);cout.setf(ios::left);
cout<<pers[j].np<<" "<<pers[j].key<<endl;
};
getch();
//*************************************
//Sortare persoane
int sortat;
do
{
sortat=1;
106
for(int j=0;j<i-1;j++)
{
switch(comp(pers[j],pers[j+1]))
{
case 1: {
tam=pers[j];
pers[j]=pers[j+1];
pers[j+1]=tam;
sortat=0;
};
};
};
}
while(!sortat);
//****************************************
//Listare persoane dupa sortare in ordinea
//crescatoare a matricolelor
clrscr();
cout<<"Listare persoane dupa sortare........................."<<endl;
cout<<"____________________________________________"<<endl;
for(int k=0;k<i;k++)
{
if (wherey()>10)
{
cout<<"_____________________________________________"<<endl;
cout<<"Pentru continuare apasati o tasta..."<<endl;
getch();
clrscr();
cout<<"Listare persoane dupa sortare........................."<<endl;
cout<<"______________________________________________"<<endl;
};
cout.width(30);cout.setf(ios::left);
cout<<pers[k].np<<" "<<pers[k].key<<endl;
};
getch();
}
Clase TEMPLATE
O clas template definete un ablon pe baza cruia se pot genera clase
propriu-zise. Din acest motiv, o clas template se mai numete i clas generic
, clas generator sau metaclas.
Astfel c, o clas template devine o clas de clase, reprezentnd cel mai
nalt nivel de abstractizare admis de programarea obiect orientat.
107
108
//***************************************
//Implementare supraincarcare operator [ ]
template <class ATip> ATip &genmat<ATip>::operator[ ](int i)
{
if(i<0 ||i>SIZE-1)
{
cerr<<"Valoare indice eronata...";
getch();
exit(1);
};
return a[i];
};
//***************************************
//Functia principala
void main()
{
genmat<int> intob;
genmat<double> doubob;
int i;
clrscr();
cout<<"Matrice de intregi..."<<endl;
for(i=0;i<SIZE;i++)
intob[i]=i;
for(i=0;i<SIZE;i++)
cout<<intob[i]<<endl;
getch();
clrscr();
cout<<"Matrice de reali dubla precizie..."<<endl;
for(i=0;i<SIZE;i++)
doubob[i]=(double)i/3;
for(i=0;i<SIZE;i++)
cout<<doubob[i]<<endl;
getch();
clrscr();
intob[100]=100;
};
Tot pentru exemplificare s considerm i o situaie deosebit de simpl. Ni se
cere s construim o clas template corespunztoare conceptului de stiv, din
care, ulterior, s se poat concretiza clase care simuleaz stiva pentru tipuri de
date diferite.
//Clasa sablon CSTack
template <Class T>
109
class Cstack
{
T * v;
//pointer la varful stivei
T * p;
//pointer la pozitia curenta din stiva
int dim;
//dimensiunea stivei
public:
Cstack(int sz)
{
v=p=new T [dim=sz]; //alocare dinamica de memorie pentru p i v
}
~Cstack()
{
delete [ ] v;
}
void push(T a)
{
*p++=a;
};
T pop()
{
return *-p
}
}
Dup ce o astfel de clas template a fost declarat i definit, se poate trece
deja la instanierea de obiecte. Singura deosebire fa de folosirea unei clase
obinuite const n faptul c trebuie specificat tipul concret care nlocuiete tipul
generic T. Ca un exemplu, s instaniem un obiect stiv (CStack) , n care ncap
maximum 100 elemente de tip char.
CStack<char> sc(100);
n acest caz, compilatorul genereaz clasa ce rezult prin nlocuirea lui T cu
char, dup care instaniaz obiectul sc. Constructorul acestuia primete ca
argument valoarea 100. Pentru mai multe detalii urmrii exemplul de mai jos.
#include <iostream.h>
#include <conio.h>
// Definirea clasei stack. Se vede c instanele ei nu sunt protejate fa de
//excepii.
//Despre excepii urmeaz s discutm
template <class T>
class CStack
{
T *v;
110
T *top;
int dims;
public:
CStack( int sz) //constructor
{
v=top=new T[dims=sz];
}
~CStack()
{
delete [ ] v;
}
//destructor
void push(T a)
{
*top++=a;
}
T pop()
{
return *--top;
}
};
//Functia principala
void main()
{
int i;
//Primul exemplu de instantiere a stivei generice ;numere ntregi
CStack<int> st1(20);
//ncarcare stiva
for (i=0;i<=9;i++)
{
st1.push(i);
}
//Vizualizare continut stiva
clrscr();
for (i=0;i<=9;i++)
{
gotoxy(35, wherey()+1);
cout<<st1.pop()<<"*****";
}
getch();
111
112
4 Tratarea excepiilor
Programatorii adevrai trebuie s ia n calcul i posibilitatea de a crea programe
robuste, care fac fa att cerinelor specificate dar nerafinate suficient, ct i
cerinelor nespecificate dar formulate de utilizator, din diverse motive.
Programele care au aceste caliti se numesc robuste.
n programarea clasic soluia acestei probleme se putea numi, destul de exact
spus, programare defensiv. Seamn puin cu conducerea preventiv din
oferie dac ne gndim c programnd defensiv, n fond punem rul nainte,
deci nu ne bazm pe cumsecdenia i buna pregtire a utilizatorului.
Pentru a face fa cerinelor legate de problema tratrii excepiilor (aa se
numesc n jargon profesional erorile care apar n timpul execuiei programelor)
anumite limbaje de programare ofer suport adecvat. A include aici limbaje
precum Delphi, C++, Java, Visual C.
Nu toate compilatoarele de C++ ofer suport, dar standardul ANSI C++ cere
acest lucru n mod explicit. Compilatoarele din familia Borland incepnd cu
versiunea 4.0 ofer acest suport.
Esenialul din punctul de vedere al programatorului C++ este ca el s-i formeze
abilitatea de a scrie n jurul aplicaiilor cod C++ care ndeplinete funcia de
handler de excepii.
Suportul sintactic C++ pentru tratarea excepiilor se rezum la trei cuvinte cheie,
a cror semantic preliminar o prezentm n Tabelul xxxxx.
Cuvntul cheie
try
Semnificaie
Delimiteaz o poriune de cod n care se instituie
controlul sistemului asupra excepiilor n timpul rulrii.
Lanseaz o excepie de un anumit tip
throw
Capteaz o excepie lansat
catch
Tabelul 18 Cuvintele cheie ale limbajului C++ referitoare la tratarea excepiilor
113
114
XHandler,
test
are
};
void main()
{
cout<<"Start:"<<endl;
try
{
cout<<"Inauntrul blocului try"<<endl;
XHandler(1);
XHandler(2);
XHandler(0);
}
catch(int i)
{
cout<<"Am captat o exceptie. Valoarea este:";
cout<<i<<endl;
};
cout<<"Sfarsit";
};
};
Un comentariu pe marginea celor prezentate pn acum ar fi urmtorul: o
instruciune catch se execut numai dac programul lanseaz o excepie n
cadrul blocului try situat imediat nainte. n caz c o astfel de excepie nu se
lanseaz blocul catch va fi ignorat.
116
if(test==2)
throw 121.25;
}
catch(int i)
{
cout<<"Am captat exceptia #:"<<i<<endl;
}
catch(char *sir)
{
cout<<"Am
captat
exceptia
de
tip
caractere:"<<sir<<endl;
}
catch(double d)
{
cout<<"Am captat exceptia #:"<<d<<endl;
}
};
sir
de
void main()
{
XHandler(0);
XHandler(1);
XHandler(2);
cout<<"Sfarsit";
};
117
118
{
cout<<"Am captat o exceptie de tip intreg"<<endl;
}
catch()
{
cout<<"Am captat o exceptie generica"<<endl;
}
};
void main()
{
cout<<"Start:"<<endl;
XHandler(0);
XHandler(1);
XHandler(2);
cout<<"Sfarsit";
};
Restrictionarea exceptiilor
Pe msur ce programele dumneavoastr devin mai complexe, ele vor apela
frecvent funcii din cadrul unui bloc try. Atunci cnd programele dumneavoastr
apeleaz funcii dintr-un bloc try, putei restriciona tipurile de excepii pe care
funcia apelat le poate lansa. De asemenea putei preveni lansarea oricrei
excepii dintr-o anumit funcie.
Sintaxa pentru restricionare este:
tip_returnat nume_functie(lista_arg) throw(lista_tipuri )
{
//Cod functie
}
Sintaxa care inhib lansare oricrei excepii este:
tip_returnat nume_functie(lista_arg) throw()
{
//Cod functie
}
Este bine s subliniem c atunci cnd declarai o funcie cu clauza throw ea
poate s lanseze doar acele tipuri precizate n list. Dac funcia lanseaz orice
al tip programul este abortat.
Un exemplu n continuare.
119
#include <iostream.h>
void XHandler(int test) throw(int, char, double)
{
if(test==0)
throw test;
if(test==1)
throw 'a';
if(test==2)
throw 121.25;
}
void main()
{
cout<<"Start:"<<endl;
try
{
XHandler(0);
}
catch(int i)
{
cout<<"Am captat un intreg"<<endl;
}
catch(char c)
{
cout<<"Am captat un caracter"<<endl;
}
catch(double d)
{
cout<<"Am captat un double"<<endl;
}
cout<<"Sfarsit";
};
throw "Salve";
}
catch(char *)
{
cout<<"Am captat char* in XHandler "<<endl;
throw;
}
void main()
{
cout<<"Start"<<endl;
try
{
XHandler();
}
catch(char *)
{
cout<<"Am captat char * in main"<<endl;
}
cout<<"Sfarsit";
};
121
{
cout<<Introduceti numaratorul (0 pentru stop):"<<endl;
cin i;
cout<<Introduceti numitorul
:"<<endl;
cin j;
div(i,j);
} while (i!=0);
};
122
123
124
textbackground(CYAN);
clrscr();
gotoxy(20,8) ;cprintf("Optiunile programului sunt:");
gotoxy(20,9) ;cprintf("1-Preluare elemente sir");
gotoxy(20,10);cprintf("2-Sortare/afisare sir");
gotoxy(20,11);cprintf("3-Terminare program");
makewin2(20,8,60,11);
makewin2(20,14,60,14);
gotoxy(20,14);cprintf("Optiunea Dvs.:");
c=getch();
};
}
while (strchr(_optiune,c)==NULL);
return c;
125
if (x[i]>x[i+1])
{
aux=x[i];
x[i]=x[i+1];
x[i+1]=aux;
sortat=0;
}
}
}
while(!sortat);
//Afisare sir sortat
clrscr();
makewin2(20,5,60,5);
gotoxy(20,5);
printf("Sirul sortat este...");
makewin2(20,8,60,7+dims);
gotoxy(20,7);
for (i=0;i<dims;i++)
{
gotoxy(20,wherey()+1);
printf("Element[%d]= %6.2f",i,x[i]);
}
getch();
};
126
2 Fier antet care ncapsuleaz cteva faciliti de lucru n mod text, utile
pentru realizarea unor interfee agreabile ale programelor cu utilizatorii.
Numit n exemplul precedent prin facilcrt.h.
#include <conio.h>
#include <stdio.h>
#include <string.h>
#define css 1
//Afisare text dinspre capete...
void converg(int end,int linie,char *mesaj)
{
int i,j,ls,cs;
ls=(end-strlen(mesaj))/2;
cs=ls+strlen(mesaj)-1;
for (i=ls,j=cs;i<=j;i++,j--)
{
gotoxy(i,linie);
printf("%c",mesaj[i-ls]);
delay(50);
//prototipul in fisierul antet <dos.h>
gotoxy(j,linie);
printf("%c",mesaj[strlen(mesaj)-1-cs+j]);
}
getch();
//Activare video-invers
void avideo()
{
textcolor(BLACK);
textbackground(WHITE);
}
//dezactivare video-invers
void dvideo()
{
textcolor(WHITE);
textbackground(BLACK);
}
//Afisare centrata text in interiorul unei linii
void acentext(int ls, int ld, int linia, char *sir)
{
int sw;
int col;
sw=(ls>=1) && (ls<=79) && (ld<=80) && (ld>=2) && (ls<ld);
127
128
129
130
};
for(i=0;i<nl;i++)
for(j=0;j<nc;j++)
q[j][i]=p[i][j];
//Functia principala
void main()
{
int **pmat;
int **q;
int nl=6,nc=2;
clrscr();
almemmat(pmat,nl,nc);
almemmat(q,nc,nl);
citmat(pmat,nl,nc);
transpun(pmat,q,nl,nc);
afismat(q,nc,nl);
getch();
};
131
132
while(y>0)
{
temp=list[0];
list[0]=list[y-1];
list[y-1]=temp;
--y;
walk_down(list,0,y);
}
}
void main()
{
list_type list;
int i,nrel;
clrscr();
gotoxy(20,10);
cout<<"Numar de elemente in lista:";
cin>>nrel;
clrscr();
for(i=0;i<nrel;i++)
{
gotoxy(20,11);
clreol();
cout<<"Elementul[ "<<i<<" ]=";
cin>>list[i];
}
heap_sort(list,nrel);
clrscr();
for(i=0;i<nrel;i++)
cout<<list[i]<<endl;
getch();
}
133
134
int cont;
clrscr();
gotoxy(20,10);
cout<<"Caracterul:";
makewin2(20,10,60,11);
gotoxy(20+strlen("Caracterul:"),10);
cin>>c;
if(sfs)
{
ifstream in(nf,ios::in | ios::binary);
if(!in)
{
sfs=0;
gotoxy(1,24);
textcolor(RED+BLINK);
cprintf("Fisierul indicat nu poate fi deschis...");
getch();
sfs=0;
textcolor(WHITE);
}
else
{
char ch;
cont=0;
while(in)
{
in.get(ch);
if(ch==c)
cont++;
}
gotoxy(20,11);
cout<<"Numar de aparitii:"<<cont;
getch();
}
}
else
{
gotoxy(1,24);
textcolor(RED+BLINK);
cprintf("Selectati mai intai fisierul...");
getch();
textcolor(WHITE);
}
135
char *n;
sfs=1;
clrscr();
gotoxy(20,10);
cout<<"Numele fisierului de rasfoit:";
makewin2(15,10,65,10);
do
{
strcpy(n,"");
gotoxy(20+strlen("Numele fisierului de rasfoit:"),10);
gets(n);
}
while(strlen(n)==0);
return n;
136
clrscr();
}
cout<<ch;
}
getch();
}
}
else
{
gotoxy(1,24);
textcolor(RED+BLINK);
cprintf("Selectati mai intai fisierul...");
getch();
textcolor(WHITE);
}
137
138
139
gotoxy(1,1);
for(int i=0;i<78;i++)
printf("\xf");
gotoxy(16,2);printf("Cod
gotoxy(36,2);printf("Cod
gotoxy(56,2);printf("Cod
for(i=0;i<78;i++)
printf("\xf");
Caracter");
Caracter");
Caracter\n");
}
//Afisare coduri ASCII pe trei coloane
void codasc()
{
int nrcan=2;
int i,j,cc;
int lin=1;
int col=1;
clrscr();
antet();
for(i=0;i<256;i++)
{
if(lin>19)
if(col==3)
{
gotoxy(1,24);
gotoxy(1,23);
for(j=0;j<78;j++)
printf("\xf");
printf("\nESC-pentru terminare\\Alta tasta pentru
continuare...");
if(getch()=='\033') return;
col=lin=1;
clrscr();
antet();
}
else
{
lin=1;
col++;
}
switch(col)
{
case 1:
{
cc=startcol1;
break;
}
140
case 2:
{
cc=startcol2;
break;
}
case 3:
{
cc=startcol3;
break;
};
}
lin++;
gotoxy(cc,nrcan+lin);printf("%i",i);
gotoxy(cc+7,nrcan+lin);printf("%c",(char)i);
};
gotoxy(1,23);
for(j=0;j<78;j++)
printf("\xf");
gotoxy(1,24);
printf("Pentru terminare apasati o tasta....");
getch();
}
//Afisare centrata text pe o linie specificata
int afcent(int lin,char s[80])
{
int col;
int parer=0;
if((lin<1)||(lin>24))
parer++;
if(!strlen(s))
parer=parer+2;
if(parer)
return parer;
col=(80-strlen(s))/2;
gotoxy(col,lin);
printf("%s",s);
return parer;
}
141
142
143
144
145
};
146
147
void main()
{
char op;
sfs=0;
do
{
op=prelopt();
switch(op)
{
case '1': nf=selnumef();
break;
case '2': crefis();
break;
case '3': adinfis();
break;
case '4': {
clrscr();
gotoxy(10,12);
cout<<"Numar intrebare inregistrare de
sters:";
cin>>nri;
steinfis(nri);
break;
};
case '5': vizfis();
break;
case '6': {
clrscr();
gotoxy(10,12);
cout<<"Numar inregistrare de selectat:";
cin>>nri;
selin(nri);
break;
};
case '7': break;
}
}
while (op!='7');
};
void selin(int ni)
{
if (sfs)
{
ifstream ftestin;
ftestin.open(nf,ios::in|ios::binary);
ftestin.seekg((ni-1)*sizeof(t_inr_fis),ios::beg);
148
}
else
{
gotoxy(1,24);
cout<<"Selectati sau creati mai intai un fisier!....";
getch();
}
};
void steinfis(int nrint)
{
ifstream ftestin;
ofstream fmanout;
if(!sfs)
{
cerr<<"Fisier neselectat....";
getch();
}
else
{
fmanout.open("man",ios::out|ios::binary);
clrscr();
ftestin.open(nf,ios::in|ios::binary);
while (!ftestin.eof())
{
ftestin.read((unsigned char*)&inr,sizeof(t_inr_fis));
if ((inr.nr_intrebare!=nrint)&&(!ftestin.eof()))
fmanout.write((unsigned char*) &inr,
sizeof(t_inr_fis));
};
fmanout.close();ftestin.close();
};
};
149
//Implementare crefis()
void crefis()
{
ofstream ftestout;
clrscr();
gotoxy(20,10);
cout<<"Nume fisier de creat:";
cin>>nf;
ftestout.open(nf,ios::out|ios::binary);
sfs=1;
char ras;
do
{
clrscr();
gotoxy(20,10);cout<<"Numar intrebare:";
cin>>inr.nr_intrebare;
gotoxy(20,11);cout<<"Raspuns corect :";
cin>>inr.alt_corecta;
ftestout.write((unsigned char *) &inr,
sizeof(t_inr_fis));
gotoxy(20,12);cout<<"Mai aveti de introdus(D,N):";
ras=getch();
}
while (!(toupper(ras)=='N'));
ftestout.close();
}
//Implementare adinfis()
void adinfis()
{
if (sfs)
{
ofstream ftestout;
clrscr();
gotoxy(20,10);
ftestout.open(nf,ios::app|ios::binary);
char ras;
do
{
clrscr();
gotoxy(20,10);cout<<"Numar intrebare:";
cin>>inr.nr_intrebare;
gotoxy(20,11);cout<<"Raspuns corect :";
cin>>inr.alt_corecta;
ftestout.write((unsigned char *) &inr,
sizeof(t_inr_fis));
150
}
while (!(toupper(ras)=='N'));
ftestout.close();
}
else
{
gotoxy(1,24);
cout<<"Selectati sau creati mai intai un fisier!....";
getch();
}
}
//Implementare vizfis()
void vizfis()
{
if (sfs)
{
ifstream ftestin;
ftestin.open(nf,ios::in|ios::binary);
while (!ftestin.eof())
{
clrscr();
ftestin.read((unsigned char*)&inr,sizeof(t_inr_fis));
if(!ftestin.eof())
{
gotoxy(10,12);
cout<<"Nr. intrebare
:";
cout<<inr.nr_intrebare;
gotoxy(10,13);
cout<<"Alternativa corecta:";
cout<<inr.alt_corecta;
getch();
};
};
ftestin.close();
}
else
{
gotoxy(1,24);
cout<<"Selectati sau creati mai intai un fisier!....";
getch();
}
}
151
//Implementare selnumef()
char *selnumef()
{
char *n;
sfs=1;
clrscr();
gotoxy(20,10);
cout<<"Numele fisierului de lucru:";
do
{
strcpy(n,"");
gotoxy(20+strlen("Numele fisierului de lucru:"),10);
gets(n);
}
while(strlen(n)==0);
return n;
}
//Implementare prelopt()
char prelopt()
{
clrscr();
gotoxy(20,8);
cout<<"Optiunile programului...";
gotoxy(20,9);
cout<<"__________________________________________";
gotoxy(20,11);
cout<<"1-Selectare fisier structura test";
gotoxy(20,12);
cout<<"2-Creare fisier structura test";
gotoxy(20,13);
cout<<"3-Adaugare date in fisierul structura test";
gotoxy(20,14);
cout<<"4-Stergerea unei inregistrari din fisier";
gotoxy(20,15);
cout<<"5-Vizualizare date fisier structura";
gotoxy(20,16);
cout<<"6-Afisare inregistrare de numar specificat";
gotoxy(20,17);
cout<<"7-Terminare program";
gotoxy(20,19);
cout<<"__________________________________________";
gotoxy(20,20);
cout<<" Alegerea Dvs.:";
gotoxy(20+strlen(" Alegerea Dvs.:"),20);
char op;
152
};
do
op=getch();
while (strchr(optiuni,op)==NULL);
return op;
153
BIBLIOGRAFIE MINIMAL
[1]. N. Barkakati
Lista crilor din care se poate nva cte ceva despre C++ si lumea
POO este deschis, la fel de deschis ca mintea oricrui student care nu
i-a greit culoarul pe care alearg pentru a deveni un profesionist.
154
Subiecte
pentru
examenul
la
disciplina
Programare Obiect Orientat, Anul II INFO
FUNDAMENTE
Locul limbajului C/C++ printre celelalte limbaje de programare.
Elemente caracteristice.
Tipuri de date fundamentale. Modificarea tipurilor de date
fundamentale.
Variabile n C/C++. Variabile locale. Variabile globale.
Modelatori de acces. Specificatori de clase de stocare.
Operatori n C/C++.
Reprezentarea structurilor de prelucrare n C/C++. Structuri
secveniale.
Reprezentarea structurilor de prelucrare n C/C++. Structuri
alternative.
Reprezentarea structurilor de prelucrare n C/C++. Structuri
repetitive.
Tablouri C/C++.
Pointeri.
memoriei.
155
Uniuni.
PARADIGMA POO
Concepte n programarea obiect orientat.
Principii n programarea obiect orientat.
Implementarea conceptelor i principiilor OO n C++.
Constructori, destructori, crearea obiectelor n C++.
Metodele virtuale i polimorfismul n programarea OO n C++.
PROGRAMARE AVANSAT N C/C++
Suprancrcarea funciior n programarea C/C++.
Suprancrcarea operatorilor n programarea C++.
Funcii inline. Funcii prietene.
Fluxuri C/C++.
Programarea generic n C/C++. Funcii generice.
Programarea generic n C/C++. Clase generice.
Programarea excepiilor n C/C++.
156
157
158