Sunteți pe pagina 1din 30

Lucrarea de laborator nr.

1
Tema: Reprezentarea tipurilor de date ale limbajului C++ n memoria calculatorului. Operatorii
limbajului C++. Construciile elementare ale limbajului C++ (instruciunile for, while, do-while,
if-else, switch-break, goto). Tipuri de date recursive, operaii asupra listelor, arborilor.
Construirea i elaborarea programelor recursive. Fiierele.

Scopul lucrrii: familiarizarea studenilor cu reprezentarea tipurilor de date ale limbajului C++
n memoria calculatorului, operatorii limbajului C++, construciile elementare ale limbajului
C++ (instruciunile for, while, do-while, if-else, switch-break, goto), tipuri de date recursive,
operaii asupra listelor, arborilor, construirea i elaborarea programelor recursive, lucrul cu
fiierele.

Consideraiile teoretice necesare:


Tipurile simple i structurate ale limbajului C++ .
Identificatorii limbajului C++ snt formai cu ajutorul caracterelor alfanumerice i
caracterul de subliniere _. Primul caracter al unui identificator nu poate fi o cifr.
Pi //legal
mesaj //legal
maxx //legal
x3 //legal
3x //ILEGAL
n cadrul mulimii identificatorilor posibili, remarcm o
clas aparte, reprezentnd cuvintele-cheie. Cele mai frecvente
cuvintele-cheie ale limbajul C++snt
auto delete float interrupt register template
break do for long return this
case double friend near short typedef
char else goto new signed union
class enum huge operator sizeof unsigned
const export if private static virtual
continue extern inline protected struct void
default far int public switch while
Cuvintele-cheie nu trebuie utilizai ca nume de variabile.
Declararea variabilelor trebuie efectuat nainte de a fi folosite, la nceputul
programului sau chiar n funcie de contextul problemei n interiorul programului nemijlocit
nainte de utilizare, cnd apare necesitarea introducerii variabilei. 0 declaraie specific un tip i
este urmat de o list de una sau mai multe variabile de acel tip, ca n exemplul de mai jos:
int i,n;
char c, linie[80];
Domeniu de aciune a variabilelor. Variabilele pot fi iniializate n momentul declaraiei
lor. Dac numele este urmat de semnul egal i de o constant, aceasta servete la iniializare, ca
n urmtoarele exemple:
char backslash = '\\';
int i = 0;
float eps = 1.0e-5;

1
Dac variabila este extern sau static, iniializarea are loc o singur dat, nainte ca
programul s-i nceap execuia. Variabilele automate, iniializate explicit, snt iniializate la
fiecare apel al funciei n care snt coninute. Variabilele automate pentru care nu exist o
iniializare explicit au valoare nedefinit. Variabilele externe i statice se iniializeaz implicit
cu zero, dar este un bun stil de programare acela de a efectua iniializarea lor n orice caz.
Fiecare variabil i constant posed un tip, care determin dimensiunea spaiului necesar
memorrii lor. Tipurile datelor se pot divide n dou categorii: tipuri fundamentale i tipuri
derivate sau structurate.
Tipurile fundamentale ale limbajului C++ snt
char reprezentnd tipul caracter pe 1 octet,
int ntreg pe 2 octei
long ntreg pe 4 octei
float, nsemnnd un numr real pe 4 octei
double, ataat unui numr real pe 8 octei
Aceste tipuri admit diferite variante, numite tipuri de baz de date.
Tipurile enumerabile snt introduse prin sintaxa
nume {membrul,membru2, . . . ) varl,var2, . . . ;
De exemplu,
enum CULORI {ROU , VERDE, ALBASTRU }
culoarea_punct, culoare_linie;
CULORI culoare_cerc, culoare_fond;
definete tipul de dat CULORI i declar variabilele culoarea_punct i culoare_linie urmate de
declarrile a nc dou variabile culoare_cerc i culoare_fond de tipul enumerabil.
Membrii unui tip enumerabil trebuie s fie numai de tip ntreg. Valoarea fiecruia este
obinut prin incrementarea cu 1 a valorii membrului anterior, primul membru avnd, implicit,
valoarea 0. Iniializarea unui membru cu o valoare oarecare, avndu-se n vedere c doi membri
ai aceluiai tip nu pot avea aceeai valoare. Valorile membrilor urmtori se stabilesc conform
regulilor menionate. Exemple de tipuri de date enumerabile:
enum ANOTIMP (IARNA=1, PRIMVARA, VARA, TOAMNA) ;
enum BOOLEAN {fals, adevrat) condiie;
enum DIRECIE {SUS, JOS, DREAPTA, STNGA=5};
Putem defini tipuri enumerabile fr a specifica numele acestora. Procednd astfel, putem grupa
un set de constante fr a denumi acea mulime, de exemplu,
enum {bine, foarte_bine, cel_mai_bine};
Utilizarea variabilelor de tip enumerabil. Limbajul C++ permite atribuiri de tipul
condiie=0;
while (! condiie)
{ cout <<Utilizarea variabilei enumerabile;
condiie=true; }
Este bine ca astfel de atribuiri s fie nsoii de conversia de tip corespunztoare.
condiie=false;
condiie=(enum BOOLEAN) 0;
Enumerrile, definite n interiorul structurilor limbajului C++, nu snt vizibile n afara acestora.
Tipurile structurate snt obinute de la tipurile de baz. Tipurile derivate acceptate de
limbajul C++ snt: pointeri, referine, tablouri, structuri, uniuni i clase.

2
Pointerul este o variabil care conine adresa unei alte variabile de orice tip. Pentru a
defini un pointer, vom specifica tipul datei a crei adres urmeaz s o memoreze.
int *ip; // pointer ctre un ntreg
char **s; // pointer la un pointer pe caractere.
S considerm o variabil de tip int i i un pointer pi ctre un ntreg.
int i=15, j;
int *pi=NULL;
pi=&i;
*pi=20; // i=20;
Deoarece operatorul adres & furnizeaz adresa unei variabile, instruciunea pi=&i asigneaz
variabilei pi adresa lui i.(de exemplu, adresa 1000). Un alt operator unar ce nsoete clasa
pointerilor este * care furnizeaz coninutul locaiei de memorie de pe adresa indicat de ctre
pointer, de exemplu,
*pi=i; // adic 15;
Dac j este un alt int, atunci j=*pi asigneaz lui j coninutul locaiei indicate de pi. Are loc
urmtoarea echivalen: j=*pi; adic j=i;
Pointerii pot aprea n expresii. De exemplu, dac pi conine adresa lui i, atunci *pi poate
aprea n orice context n care ar putea aprea i, cum ar fi
j=*pi+l; // adic j=i+l;
printf("%d\n",*pi);
d=sqrt((double)*pi);
n expresii ca j=*pi+1; operatorii unari * i & snt prioritari fa de cei aritmetici, astfel, aceast
expresie adun 1 i asigneaz valoarea obinut lui j ori de cte ori pointerul pi avanseaz.
Referiri prin pointeri pot aprea i n membrul stng al atribuirilor. Dac pi conine adresa
lui i, atunci *pi=0 l pune pe i ca 0, iar *pi+=1 l incrementeaz pe i, ca i (*pi)++. n ultimul
exemplu parantezele snt necesare, fr ele se incrementeaz pi n loc
s incrementeze ceea ce indic pi, deoarece operatorii unari * i ++ snt evaluai de la dreapta
spre stnga. De exemplu,
void main()
{ int *pi, i=10;
float *pf, f=12.5;
double *pd, d=0.001;
char *pc, c=a;
*pi=i; *pf=f; *pd=d; *pc=c;
printf(pi=%p, pf=%p, pd=%p, pc=%p, pi, pf, pd, pc);
printf(*pi=%i, *pf=%f, *pd=%e, *pc=%c, *pi, *pf, *pd, *pc);
printf(pi++ =%p, pf++ =%p, pd++ =%p, pc++=%p, pi++, pf++, pd++, pc++);
printf((*pi)++ =%p, (*pf)++ =%p, (*pd)++ =%p, (*pc)++ = %p, (*pi)++ ,
(*pf)++, (*pd)++, (*pc)++);
}
Rezultatul ndeplinirii programului:
pi=8F1C, pf=0758, pd=074C, pc=1330*pi=10, *pf=12.500000, *pd=1.000000e-03, *pc=a
pi++ =8F1C, pf++ =0758,
pd++ =074C, pc++=1330(*pi)++ =1B57, (*pf)++ =0000,
(*pd)++ =0000, (*pc)++ = 0000

3
Deoarece pointerii snt variabile, ei pot fi manevrai ca orice alt variabil. Dac pj este
un alt pointer la int, atunci
pj=pi;
copiaz coninutul lui pi n pj, adic pj va indica la variabila adresa creia este indicat n pi,
astfel c pj se va modifica odat cu pi. Pointerii pot conine adrese ctre elemente fr tip, cu
void. Putem atribui unui pointer void valoarea unui pointer non-void fr a fi necesar o operaie
de conversie de tip typecast.
char *cp; // pointer ctre un caracter
void *vp; // pointer ctre void
vp=cp; // legal - pointerul la caracter depus n
//pointerul ctre void
cp=vp; // ILEGAL - lipsete conversia de tip
cp=(char*) vp; // legal - pointerul ctre void depus n pointerul ctre caracter cu
conversie de tip.
Referina prezint o legtur cu o variabil, coninnd o adres. Spre deosebire de
pointeri, n a cror declarare se utilizeaz simbolul *, pentru a defini o referin, vom folosi
simbolul &.
int i; // declararea unui ntreg
int *p=&i; // definirea unui pointer la i
int &r=i; // definirea unei referine la i
Att p, ct i r acioneaz asupra lui i.
i=55; // aciune asupra lui i
*p=13; // aciune asupra lui i
r=20; // aciune asupra lui i.
Exist ns o diferen major ntre p i r, nu numai n modul de apelare, ci i datorit faptului c
p poate, la un moment dat, s fie n legtur cu o alt variabil, a crei locaie de memorie o va
conine, diferit de cea a lui i, n timp ce r nu-i poate schimba referina, acesta nefiind altceva
dect o redenumire a variabilei i. n ceea ce privete utilizarea referinelor, va trebui s inem cont
de urmtoarele restricii:
referinele trebuie iniializate chiar n momentul declarrii lor,
odat fiind iniializate, referinelor nu li se pot schimba locaiile la care se refer,
nu snt permise referine la referine i pointeri ctre referine, dar putem avea o referin la
un pointer.
Referinele pot fi utilizate drept constante, pot fi iniializate cu constante, funcii sau chiar
structuri.
Tablourile, din rndul crora fac parte vectorii i matricele, snt tipuri de date foarte
apropiate pointerilor i referinelor. Vom vedea c orice operaie, care poate fi rezolvat prin
indexarea tablourilor, poate fi rezolvat i cu ajutorul pointerilor. Astfel, declaraia
char linie[80];
definete linie ca fiind un ir de 80 de caractere i, n acelai timp, linie va constitui un pointer la
caracter. Dac pc este un pointer la un caracter, declarat prin
char *pc;
atunci atribuirea pc=&1inie[0]; face ca pc s indice primul element al tabloului linie (de indice
zero). Aceasta nseamn c pc conine adresa lui linie[0]. Acum atribuirea
c=*pc;

4
va copia coninutul lui linie[0] n c. Dac pc indic un element al lui linie, atunci, prin definiie,
pc+1 indic elementul urmtor i, n general, pc-i indic cu i elemente naintea elementului
indicat de pc, iar pc+i cu i elemente dup acelai element. Dac pc indic elementul linie[0],
*(pc+1) indic coninutul lui linie[1], pc+i este adresa lui linie[i], iar *(pc+i) este coninutul lui
linie[i]. Observm c operatorul de indexare [], de forma E1[E2], este identic cu*((E1)+(E2)).
Aceste remarci snt adevrate indiferent de tipul variabilelor din tabloul linie. Definiia adunrii
unitii la un pointer i, prin extensie, toat aritmetica pointerilor const, de fapt, n calcularea
dimensiunii memoriei ocupate de obiectul indicat. Astfel, n pc+i i este nmulit cu lungimea
obiectelor pe care le indic pc, nainte de a fi adunat la pc.
Corespondena ntre indexare i aritmetica pointerilor este foarte strns. Referina la un
tablou este convertit de ctre compilator ntr-un pointer spre nceputul tabloului. Numele acestui
tablou este o expresie de tip pointer.
Evalund elementul linie[i], limbajul C++ l convertete n *(linie+i), cele dou forme
fiind echivalente. Aplicnd operatorul & ambilor termeni ai acestei echivalene, rezult c linie[i]
este identic cu linie+i, unde linie+i fiind adresa elementului i din tabloul linie. Dac pc este un
pointer, el poate fi utilizat n expresii cu un indice pc[i] fiind identic cu *(pc+i). Un pointer este
o variabil. Deci,
pc=linie; // i
pc++;
snt operaii permise. Numele unui tablou este o constant i nu o variabil, construcii de tipul
linie++ fiind interzise. Singurele operaii permise a fi efectuate asupra numelor tablourilor, n
afara celor de indexare, snt cele care pot aciona asupra constantelor
Aritmetica adreselor pentru pointeri i tablouri constituie unul din punctele forte ale
limbajului C++. Se garanteaz c nici un pointer care conine adresa unei date nu va conine
valoarea zero, valoare rezervat semnalelor de eveniment anormal. Aceast valoare este atribuit
constantei simbolice NULL pentru a indica mai clar c aceasta este o valoare special pentru un
pointer. n general, ntregii nu pot fi asignai pointerilor, zero fiind un caz special.
Exist situaii n care pointerii pot fi separai. Dac p i q indic elemente ale aceluiai
tablou, operatorii <, >, =, etc. lucreaz conform regulilor cunoscute. p<q este adevrat, de
exemplu, n cazul n care p indic un element anterior elementului pe care l indic q. Relaiile
== i != snt i ele permise. Orice pointer poate fi testat cu NULL, dar nu exist nici o ans n a
compara pointeri situai n tablouri diferite.
Este valabil i operaia de scdere a pointerilor. Astfel, dac p i q indic elementele
aceluiai tablou, p-q este numrul de elemente dintre p i q. O funcie, deosebit de util n lucrul
cu iruri de caractere, este strlen(), care returneaz lungimea irului de caractere transmis ca
parametru.
int strlen(char *s)
{ char *p=s;
while (*p!='\0') p++;
return p-s; }
Prin declarare p este iniializat cu s i indic primul caracter din s. n cadrul ciclului while
este examinat coninutul irului de caractere, indirect, prin intermediul pointerului p, caracter
dup caracter, pn cnd se ntlnete '\0'', acesta din urm semnificnd sfritul irului. Dac
while ar testa doar dac expresia este zero, este posibil omiterea testului explicit, astfel de
cicluri fiind deseori scrise sub forma
while (*p) p++;

5
Deoarece p indic irul de caractere, p++ face ca p s avanseze de fiecare dat la caracterul
urmtor, iar p-s d numrul de caractere parcurse (lungimea irului). Aritmetica pointerilor este
consistent: dac am fi lucrat cu float, care ocup mai mult memorie dect char, i dac p ar fi
fost un pointer la float, p++ ar fi avansat la urmtorul float. Toate manipulrile de pointeri iau
automat n considerare lungimea obiectului referit.
S implementm, de exemplu, o funcie de comparare a dou iruri de caractere. Funcia
strcmp(s, t) compar irurile de caractere s i t i returneaz valoare negativ, nul sau pozitiv,
n funcie de relaia dintre s i t (care poate fi s<t, s=t sau s>t). Valoarea returnat este obinut
prin scderea caracterului de pe prima poziie, unde s difer de t. Pentru claritatea problemei,
vom prezenta dou variante, una utiliznd tablourile, iar cea de a doua utiliznd pointerii.
Varianta cu tablourile:
strcmp(char s[], char t[])
{ int i=0;
while (s[i]==t[i])
if (s[i++]=='\0') return 0;
return s[i]-t[i];}
Varianta cu pointerii:
strcmp(char *s, char *t)
{ for(;*s==*t;s++,t++)
if(*s=='\0') return(0);
return (*s-*t);}
Dac ++ i - - snt folosii ca operatori prefixai, pot aprea alte combinaii de *, ++ i - -, dei
mai puin frecvente. De exemplu: *++p incrementeaz pe p nainte de a aduce caracterul spre
care indic p. *- - p decrementeaz pe p n aceleai condiii.
Alte operaii, n afara celor menionate deja (adunarea sau scderea unui pointer cu
ntreg, scderea sau compararea a doi pointeri), snt ilegale. Nu este permis adunarea,
mprirea, deplasarea logic sau adunarea unui float sau double la pointer.
Tablourile multidimensionale pot fi definite cu ajutorul tablourilor de tablouri, de
exemplu.:
char ecran [25][80];
excepie fcnd tablourile de referine, acestea din urm nefiind permise datorit faptului c nu
snt permii pointerii la referine.
Dac E este un tablou n-dimensional de dimensiuni i, j, ..., k, atunci apariiile lui E n
expresii snt convertite n pointer la un tablou n-1-dimensional de dimensiuni j, ..., k. Dac la
acesta se aplic explicit sau implicit (prin indexare) operatorul *, rezultatul este tabloul n-1-
dimensional indicat de pointer, care, la rndul su, este convertit imediat n pointer.
Tablourile snt memorate pe linii i, deci, ultimii indici, de la stnga la dreapta, variaz
mai repede dect primii. Prima dimensiune a unui tablou se folosete numai pentru a determina
spaiul ocupat de acesta, ea nefiind luat n consideraie dect la determinarea unui element de
indici dai. Este permis omiterea primei dimensiuni a unui tablou, dac tabloul este extern,
alocarea fcndu-se n cadrul altui modul sau cnd se efectueaz iniializarea tabloului n
declaraie, n acest caz fiind determinat dimensiunea din numrul de elemente iniializate.
Iniializarea tablourilor poate avea loc chiar n cadrul declarrii acestora
int point[2]={10,19};
char mesaj1[6]={'S1,'a','l','u','t','\0'};
char mesaj2[6]="Salut";

6
Observm c irurile de caractere se comport oarecum ciudat. Att mesaj1, ct i mesaj2 snt
iruri de 6 caractere avnd drept terminator de ir caracterul nul. Diferena ntre cele dou iruri
nu se afl n coninutul lor, ci n cadrul iniializrii lor. n cazul iniializrii prin acolade, { },
caracterul nul nu este subneles, prezena acestuia rmnnd la latitudinea noastr, n schimb,
adoptnd o iniializare prin ghilimele, , va trebui s dimensionm corespunztor irului de
caractere, innd cont de prezena terminatorului de ir. n exemplul mesaj2 avem 5 litere plus
caracterul nul, fiind necesare 6 locaii n vederea memorrii cuvntului Salut.
Dimensionarea tablourilor se realizeaz n concordan cu necesitile aplicaiei. Exist
posibilitatea iniializrilor pariale, care nu utilizeaz ntreg spaiu rezervat. n cazul irurilor de
caractere, restul spaiului rmas neutilizat va conine numai caracterul nul. n restul situaiilor,
coninutul tabloului fiind aleator, se recomand iniializarea acestuia n cadrul unui ciclu.
Tablouri de pointeri. Pointerii snt ei nii variabile, de aceea ei snt utilizai n tablouri
de pointeri. Pentru exemplificare, vom considera un program care sorteaz un set de linii de text
n ordine alfabetic. Cu toate c algoritmul de sortare este unul comun, deosebirea dintre sortarea
unui tablou de numere i a unuia de iruri de caractere const n aceea c liniile de text de
lungimi diferite nu pot fi comparate sau deplasate printr-o singur operaie. Avem nevoie de o
reprezentare a datelor care s se poat face eficient i potrivit regulilor de gestionare a liniilor de
text de lungimi diferite.
Introducem noiunea de tablou de pointeri. Dac liniile de sortare snt memorate cap la
cap ntr-un ir de caractere, atunci fiecare linie poate fi accesat printr-un pointer la primul su
caracter. Pointerii nii pot fi memorai ntr-un tablou. Dou linii pot fi comparate prin
transmiterea pointerilor respectivi lui strcmp(). Cnd dou linii neordonate trebuie inversate, se
inverseaz pointerii lor n tabelul de pointeri, nu nsi liniile. Acest mod de lucru elimin cuplul
de probleme legate de gestionarea memoriei i poate deplasa liniile.
Procesul de sortare const din trei etape:
- citirea tuturor liniilor la intrare,
- sortarea liniilor,
- tiprirea liniilor n ordine.
mprim programul n funcii care efectueaz aceste trei etape. Funcia de intrare trebuie s
colecteze i s salveze caracterele din fiecare linie i s construiasc un tablou de pointeri pe
linii. Va trebui s numere liniile la intrare. Aceast informaie este necesar pentru sortare i
tiprire. Deoarece funcia de intrare poate opera doar cu un numr finit de linii, ea va returna o
valoare, cum ar fi -1, n cazul n care se vor prezenta mai multe linii. Funcia de ieire trebuie
doar s tipreasc liniile n ordinea n care apar n tabloul de pointeri.
#include <stdio.h>
#include <string.h>
#include <conio.h>
#define LINII 100
#define MAXLEN 1000
int citeste_linii(char *s[])
{ printf("Introdu un text (maxlen=1000)\n");
printf("Pentru introducerea unei linii noi se utilizeaz tasta ENTER.\n");
printf("Sfritul textului se va marca prin '*'. \n\n");
char c;
int i=0, j=0;
while((c=getchar())!='*')

7
{ if (c=='\n')
{ s[i][j]='\0'; i++;j=0; }
else s[i][j++]=c;
}
return i+1; }
void scrie_linii (char *linieptr[],int maxlinii)
{ for( int i=0; i<maxlinii;i++)
printf("%s\n", linieptr[i]); }
void sortare_linii(char *v[],int n)
{ char *temp;
for(int k=n/2;k>0;k/=2)
for(int i=k;i<n;i++)
for(int j=i-k;j>=0;j-=k)
{ if (strcmp(v[j],v[j+k])<=0) break;
temp=v[j];
v[j]=v[j+k];
v[j+k]=temp; } }
void main()
{ clrscr();
char *linieptr[LINII];
int nlinii;
if ((nlinii=citeste_linii(linieptr))>=0)
{ printf("\n Textul pn la sortare:\n");
scrie_linii(linieptr,nlinii);
sortare_linii(linieptr,nlinii);
printf("\n Textul dup sortare \n");
scrie_linii(linieptr,nlinii);
}
else printf("Input prea mare pentru sortare \n"); }
Rezultatul ndeplinirii programului:
Introdu un text (maxlen=1000)
Pentru introducerea unei linii noi se utilizeaz tasta ENTER.
Sfrsitul textului se va marca prin '*'.
ashdgasghddgjahsdgjaghdjhagsdhgdhjgdh*
Textul pn la sortare:
ashdgasghddgjahsdgjaghdjhagsdhgdhjgdh va marca prin '*'.
Textul dup sortare
ashdgasghddgjahsdgjaghdjhagsdhgdhjgdh va marca prin '*'.
Declararea variabilei linieptr:
char *linieptr[LINII];
arat c linieptr este un tablou de LINII elemente, fiecare element fiind un pointer la char.
linieptr[i] este un pointer la caractere, iar *linieptr[i] acceseaz un caracter. Dac linieptr este el
nsui un tablou care este transmis lui scrie_linii(), el poate fi tratat ca un pointer, iar funcia
poate fi scris.
void scrie_linii(char *linieptr[],int nlinii)
{ while (- - nlinii>=0)

8
printf("%s\n",*linieptr++); }
*linieptr adreseaz iniial prima linie, iar, cu fiecare incrementare, el avanseaz linia urmtoare
pn cnd nlinii se epuizeaz.
Sortarea are loc n cadrul funciei sortare_linii(). Dac orice element individual din v este
un pointer la caractere, temp va fi un astfel de pointer, nct cei doi pot fi copiai unul n altul.
Fiind date declaraiile
int a[10][10]; int *b[10];
utilizrile lui a i b pot fi similare, n sensul c a[5][5] i b[5][5] snt referine legale ale
aceluiai int. Toate cele 100 celule de memorie ale tabloului a trebuie alocate, iar gsirea fiecrui
element se face prin calculul obinuit al indicelui. Pentru tabloul b, prin declararea sa, se aloc
10 pointeri, fiecare dintre acetia urmnd s indice un tablou de ntregi. Presupunnd c fiecare
indic la 10 elemente din tablou, vom obine 100 celule de memorie rezervate, plus cele 10
celule pentru pointeri. Astfel, tabloul de pointeri utilizeaz mai mult spaiu i poate cere un mod
explicit de iniializare. Dar exist dou avantaje: accesarea unui element se face indirect prin
intermediul unui pointer, n loc s se fac prin nmulire i adunare (cum este n cazul tabloului
multidimensional), iar liniile tabloului pot fi de lungimi diferite. Aceasta nseamn c nu orice
element al lui b este constrns s indice la un vector de 10 elemente, unii pot indica la cte 2
elemente, alii la cte 20 de elemente sau chiar la nici unul.
Structura este o colecie de elemente de tipuri diferite i care pot fi referii att separat, ct
i mpreun. Definirea unei structuri se realizeaz cu ajutorul cuvntului-cheie struct. Ea are
urmtoarea sintax:
struct [tip structur] { tip_1 element_1;

tip_ n element_n
} obiect_ de_ tip_ structur;
unde tip structur descrie organizarea structurii,
tip1,..., tipn indic tipul elementelor structurii,
element1, ..., element sunt numele elementelor structurii,
obiect_ de_ tip_ structur este una sau o list de variabile pentru care se aloc memorie. De
exemplu,
struct punct { float x,y;} p;
S-a definit o structur p ca fiind de tip punct, punctul fiind compus din dou elemente x i y
reale. Asupra componentelor unei structuri putem aciona prin intermediul operatorului de
apartenen, ., de exemplu:
p.x=10; p.y=30;
Exist posibilitatea efecturii operaiilor cu ntreaga structur, atribuirea fiind, de exemplu :
p={10,30);
0 declaraie de structur care nu este urmat de o list de variabile nu produce alocarea
memoriei, ci descrie organizarea structurii., de exemplu:
typedef struct { char name[25]; int id, age;
char prp; } student;
Definirea unei structuri permite determinarea unui nou tip de date. n continuare definind
pointeri la aceast structur, tablouri, ale cror elemente snt de tipul acestei structuri, i elemente
de acest tip pot fi definite noi structuri de date mai compuse.
Un alt aspect al utilitii structurilor l constituie tratarea tablourilor de structuri, de
exemplu:

9
punct hexagon[6]; punct octogon[8];
Accesul ctre membrii componeni ai fiecrui element al vectorului se realizeaz prin
combinarea accesului indexat, caracteristic tablourilor, cu cel utilizat n cazul structurilor:
hexagon[i].x=10;
n cazul definirii unui pointer la o structur, accesul la componentele acelei structuri se va
efectua prin expresii de forma
punct *pptr;
pptr->x=10; // Echivalent cu p.x=10;
(*pptr) .y=30; // Echivalent cu p.y=30;
Parantezele au rolul de a indica ordinea n care acioneaz cei doi operatori * i ., prioritar
fiind *.
Unele elemente ale unei structuri pot fi cmpuri de bii. Un cmp de bii este o
configuraie de bii adiaceni, ce apar ntr-un element de tip int. Cmpurile snt declarate de tip
unsigned, iar numele cmpului este urmat de dou puncte : i un numr ce reprezint numrul
de bii ocupai de cmpul respectiv:
unsigned nume_cmp:nr_bii;
Cmpurile pot fi accesate ca orice alt element de structur. Orice cmp trebuie s aib toi biii n
interiorul unei zone de tip int (nu poate avea bii n dou cuvinte diferite). Ordinea de alocare a
memoriei pentru cmpuri este dependent de sistem. Unele sisteme fac alocarea de la stnga la
dreapta, iar altele invers. Nu se pot utiliza tablouri de cmpuri. Cmpurile nu au adres i nu li se
poate aplica operatorul de adresare &.
Un caz special de structuri l constituie union. Acestea snt structuri alternative pentru
care dimensiunea spaiului necesar memorrii lor este egal cu cea mai mare dimensiune
necesar memorrii unei componente a acelei structuri. De exemplu, variabila este de tipul
union un_tip
{ int uint; float ufloat; char uchar;
punct upunct; // upunct este de tipul structurii punct
} variabila;
Toate componentele uniunii ocup aceeai zon n cadrul memoriei. Spre deosebire de structuri,
n uniune este accesibil o singur component a unei uniuni. Uniunea se definete n aceeai
manier ca i structurile, cuvntul-cheie utilizat fiind union.
Operatorii
Operatori i expresii. Aciunile desfurate n cadrul oricrui program, n marea lor
majoritate, se efectueaz prin expresiile formate prin combinaii de date i operatori. Limbajul
C++ posed toi operatorii limbajului C i completeaz aceast list cu operatori proprii. Din lista
operatorilor disponibili ai limbajului C++ indicm operatorii caracteristici lui new pentru
alocarea memoriei, delete pentru eliberarea memoriei alocate cu operatorul new, :: operatorul
de scop sau de rezoliie.
n funcie de numrul de operanzi, operatorii se pot clasifica n trei categorii: operatori
unari, binari i ternari.
Operatori unari. Formarea expresiilor n care intervin operatorii unari se produce de la
dreapta la stnga.
Operatorul de indirectare: * se poate aplica unei expresii de tip pointer (*expresie) i are
drept rezultat o valoare (lvalue sau adres) care se refer la obiectul indicat de pointer.
Operatorul de adresare: & poate fi aplicat unei valori (&lvalue) i are ca rezultat un
pointer la obiectul definit de lvalue i are acelai tip ca i tipul lvalue.

10
Operatorul unar minus: - se aplic unei expresii (-expresie) n vederea inversrii
semnului acesteia.
Operatorul negaie logic: ! se poate aplica unei expresii aritmetice sau unui pointer (!
expresie) i are ca rezultat 1, dac valoarea operandului este 0, i 0, n caz contrar, tipul
rezultatului fiind int.
Operatorul negaie pe bii: ~ se aplic unei expresii de tip ntreg (~expresie) i
transform 0 n 1 i 1 n 0 n toi biii rezultai dup conversiile uzuale.
Operatorul de incrementare: ++ incrementeaz cu 1 valoarea operandului.
Operatorul de decrementare: - - decrementeaz cu 1 valoarea operandului.
Operatorul ++, ca i operatorul - -, poate fi utilizat att ca prefix, ct i ca sufix. n cazul
utilizrii lor ca prefix, nti se acioneaz cu operatorul asupra valorii operandului i apoi se
utilizeaz noua valoare a acestuia. n cazul utilizrii lor ca sufix, nti se utilizeaz valoarea
acestuia, apoi se acioneaz cu operatorul asupra valorii operandului.
Conversia unei expresii (typecast): este de tipul (tip) expresie sau (expresia) i produce
conversia valorii expresiei la tipul specificat.
Operatorul dimensiune: sizeof este de tipul sizeof (expresie) sau sizeof (tip) i ne indic
dimensiunea n octei a operandului, determinat din declaraiile elementelor ce apar n expresie.
Operatorul de alocare a memoriei: new apare sub forma
pointer_la_nume = new nume [ iniializator]
i ncearc s creeze un obiect nume prin alocarea unui numr egal cu sizeof(nume) de octei n
memoria heap, adresa acestuia fiind returnat. n cazul n care alocarea nu este efectuat cu
succes, se returneaz valoarea NULL
Operatorul de eliberare a memoriei: delete are sintax de forma
delete pointer_la_nume
i elibereaz memoria alocat ncepnd de la adresa coninut de pointer_la_nume.
Operatorul virgul: , produce expresii de forma
expresie, expresie;
El efectueaz evaluarea expresiilor de la stnga la dreapta i are ca rezultat i tip valoarea i tipul
ultimei expresii. Gruparea cu paranteze este permis i produce o singur valoare. De exemplu:
void main()
{int s;
for(int i=0,s=0;i<10,i++) s+=I;
cout<< Suma este de <<s<<endl;
}
Operatori binari
Operatorii aritmetici: +, -, *, / acioneaz respectnd regulile binecunoscute de calculare
a expresiilor. Trebuie fcut o observaie asupra operatorului de mprire /. n cazul n care
ambii operanzi snt ntregi, rezultatul este ntreg (prin trunchierea rezultatului real).
Operatorul modulo: % furnizeaz restul mpririi primului operand la cel de al doilea.
De exemplu, un numr este par, dac este divizibil cu 2. Deci
if (x%2==0) cout "x este par";
else cout "x este impar";
Operatorul de deplasare la stnga: are ca rezultat deplasarea ctre stnga a valorii
operandului stng cu un numr de bii egal cu valoarea operandului drept, biii eliberai astfel
fiind completai cu valoarea 0.

11
Operatorul de deplasare la dreapta: acioneaz n mod similar cu precedentul, singurul
element care difer fa de operatorul anterior fiind sensul deplasrii. De exemplu, funcia
definit mai jos Biti (x,4,3) returneaz 3 bii din poziiile 4,3 i 2, aliniai la dreapta.
Biti (unsigned x,unsigned p,unsigned n)
{return (x(p+1-n))&~ (~0n) ; }
Operatorii de comparaie: <, <=, >, >=, = =(egal), !=(neegal) au ca rezultat o valoare de
tip int care este 0 n cazul n care condiia nu este ndeplinit i 1 n caz contrar. Pointerii pot fi
comparai numai pe aceeai structur de date, iar ultimii doi operatori permit compararea
pointerului cu NULL, care corespunde adresei vide.
Operatorii logici binari pe bii: & (i), | (sau),^ (sau exclusiv) furnizeaz un rezultat de
tip int (0 pentru valoarea false i 1 pentru valoarea true). De exemplu, funcia numr_biti()
controleaz numrul de bii pe 1 dintr-un argument ntreg
numr_biti (unsigned n)
{ int b;
for (b=0; n!=0; n=1)
if (n&O1) b++;
return b; /}
Operatorii logici binari: && (i), || (or). Pentru ambii operatori se efectueaz evaluri de
la stnga spre dreapta pn la prima expresie de valoare 0 (pentru &&) sau, respectiv, nenul
(pentru || ), cnd valoarea ntregii expresii devine 0 i, respectiv, 1.
Operatorii de atribuire: op= unde op face parte din mulimea { +, -, *, /, %, , , &, ^, |}
se grupeaz de la dreapta la stnga, tipul expresiei de atribuire este tipul operandului stng, iar
rezultatul aciunii operatorului se regsete tot n acest operand. Orice expresie de tipul x op= y
este echivalent cu x =x op y.
Operatori ternari
Operatorul condiional: (condiie) ? : produce expresii de
forma (expr1) ? expr2 : expr3, n care se evalueaz exp1. n cazul n care aceasta este nenul, se
returneaz valoarea expresiei expr2, n caz contrar, se returneaz valoarea lui expr3. De exemplu,
ciclul urmtor tiprete N elemente ale unui tablou, 10 pe linie, cu fiecare coloan separat
printr-un blanc i cu fiecare linie (inclusiv ultima) terminat cu un singur caracter \n linie
nou:
for (i=0;i<N;i++)
printf("%6d %c",a[i],(i%10==9||i==N-1)?-\n':' );
Acest exemplu poate fi scris prin intermediul instruciunii if n felul urmtor:
for (i=0;i<N;i++)
if,(i%10==9||i==N-1)
printf("%6d %c",a[i],-\n');
else printf("%6d %c",a[i],' );
Instruciuni
Expresiile snt utilizate n scrierea instruciunilor. O instruciune este o expresie care se
ncheie cu punct i virgul ;". Instruciunile pot fi scrise pe mai multe linii program, spaiile
nesemnificative fiind ignorate. Pe o linie de program putem scrie multe instruciuni.
Instruciunile pot aprea n diferite forme: de atribuiri, de declaraii, instruciuni condiionale, de
ciclare, de salt, instruciuni compuse.
Instruciunea compus (blocul de instruciuni) grupeaz declaraii i instruciuni n
vederea utilizrii unui bloc de instruciuni echivalent cu o instruciune compus. Forma general

12
este:
{lista_declaraii lista_instruciuni}
Instruciunea condiional if, if-else are una din formele:
if (expr) instruciune;
if (expr) instruciune_l; else instruciune_2;
Instruciunea if evalueaz expresia expr. n cazul n care se obine o valoare nenul, se trece la
executarea instruciune_1, iar dac aceast valoare este nul i exist instruciune_2, se va
executa instruciune_2. n cazul absenei variantei else se va trece la execuia instruciunii
imediat urmtoare instruciunii if.
Instruciunea de ciclu condiionat anterior while este
while (expr) instruciune;
Att timp ct valoarea expresiei expr este nenul, se execut instruciune. De exemplu,
i=0;
while (i<n) a[i++]=0.0;
Evaluarea expresiei are loc naintea execuiei instruciunii, fapt pentru care aceast instruciune
este din clasa ciclurilor cu precondiie. Din acest motiv este posibil ca corpul ciclului s nu se
execute nici mcar o dat, dac condiia ciclului este fals. Execuia programului va trece la
instruciunea imediat urmtoare instruciunii de ciclu.
Instruciunea de ciclu condiionat posterior do-while are forma do
instruciune while (expr);
instruciune se va executa pn ce valoarea expresiei expr devine fals. Spre deosebire de
instruciunea while, n ciclul do-while evaluarea expresiei are loc dup fiecare executare a
corpului ciclului. Datorit acestui fapt instruciune se va executa cel puin o singur dat, iar
instruciunea do se ncadreaz n categoria ciclurilor cu postcondiie. De exemplu:
i=0;
do
{ a[i++]=0.0; }
while (i<n);
Ciclul do-while este folosit mai puin dect ciclul for. Cu toate acestea, prezena sa se impune n
cazurile n care este necesar executarea corpului unui ciclu cel puin o dat, urmnd ca ulterior
s se execute n funcie de ndeplinirea condiiei finale, indicate n contextul ciclului while.
Instruciunea de ciclu aritmetic for are urmtoarea form general for
(expr_1; expr_2; expr_3) instruciune;
i este echivalent cu urmtoarea succesiune de instruciuni:
expr_1;
while (expr_2)
( instruciune;
expr_3; )
Oricare dintre cele trei expresii poate lipsi, absena expresiei expr_2 fiind nlocuit, implicit, cu
valoarea 1. De exemplu,
for (int i=0; i<=n; i++) a[i]=0.0;
for ( int k=0, number_of_nums=0, number_of_chars=0; k<strlen(text); k++)
{ cout text[k] \n;
if (is_num(text[k])) number_of_nums++;
if (is_alpha(text[k])) number_of_chars++;
}

13
Ciclul for este util de folosit atunci cnd exist o simpl iniializare i reiniializare, deoarece se
pstreaz instruciunile de control al ciclului mpreun.
Instruciunea switch face parte din categoria instruciunilor de selectare. Transferul
controlului se va efectua la una din variantele posibile, n funcie de valoarea unei expresii de
control. Sintaxa instruciunii este switch (expr) instruciune;
unde instruciune este o instruciune compus, n care fiecare instruciune individual trebuie
etichetat cu o etichet de forma
case expresie_constanta:
unde expresie_constanta trebuie s fie de tip int i nu pot fi dou etichete egale n aceeai
instruciune switch. Cel mult o instruciune poate fi etichetat cu default:
La execuia unei instruciuni switch se evalueaz expresia expr i se compar valoarea
obinut cu fiecare constant ce apare n etichetele asociate instruciunii. Dac se gsete o astfel
de constant, controlul este dat instruciunii ce urmeaz ei, n caz contrar, controlul fiind
transferat la instruciunea de dup eticheta default, dac aceasta exist, sau instruciunii imediat
urmtoare instruciunii switch.
Pentru a se meniona sfritul unei instruciuni ataate unui caz, se va utiliza una dintre
instruciunile goto, break sau return. La nceputul unei instruciuni switch pot aprea declaraii,
dar nu se vor efectua iniializri ale variabilelor de tip auto sau register. De exemplu,
switch (text[k])
{ case A : numr_caractere++; break;
case B: numr_caractere++; break;
// se vor completa toate cazurile posibile
case 'Z' : numr_caractere++; break;
case ' a : numr_caractere++; break;
// se vor completa toate cazurile posibile
case z: numr_caractere++; break;
case 0: :numr cifre++;
// se vor completa toate cazurile posibile
case '9':numr cifre++; }
Instruciunea break are forma break;
Are ca efect terminarea execuiei unui ciclu de tip while, do-while, for sau switch, controlul fiind
transferat primei instruciuni din corpul blocului cel mai interior.
Instruciunea continue are forma continue;
Are drept efect trecerea controlului urmtorului ciclu ntr-o instruciune de tip while sau for n
care apare i nu are nici un efect dac nu apare n corpul unor astfel de instruciuni. Cnd este
ntlnit, ea se trece la urmtoarea iteraie a ciclului (while, for, do-while). n cazul lui while i
do-while, aceasta nseamn c partea de control se execut imediat. n cazul ciclului for,
controlul va trece la faza de reiniializare. De obicei, instruciunea continue nu se va aplica
instruciunii switch. Ca exemplu, fragmentul urmtor sumeaz numai elementele pozitive dintr-
un tablou a, n care valorile negative snt omise.
int s;
for (int i=0,s=0; i<N; i++)
{ if (a[i]<0) continue; //sare indicii elementelor negative
s+=a[I]; }
Instruciunea return admite urmtoarele dou forme
return; sau return (expr);

14
cea din urm fiind echivalent cu urmtoarea
return expr;
Efectul instruciunii return este trecerea controlului la funcia care a apelat funcia respectiv fr
transmiterea unei valori n prima variant sau cu transmiterea unei valori n ultimele -dou
variante.
Instruciunea goto i etichete. Limbajul C++ ofer instruciunea goto pentru ramificare.
Formal, instruciunea goto nu este necesar i uor se poate scrie programe fr ea. Cu toate
acestea, exist cteva situaii n care goto i poate gsi locul. Cea mai obinuit folosire este
aceea de a abandona prelucrarea n anumite structuri puternic imbricate, de exemplu, de a iei
afar din dou cicluri deodat, instruciunea break nu poate fi folosit, deoarece ea prsete
numai ciclul cel mai din interior. Astfel:
for(...)
for(...)
( ...
if(dezastru) goto error;}
error:;
O posibilitate de cutare a primului element negativ ntr-un tablou bidimensional ar fi:
for (i=0; i<N; i++)
for(j=0; j<M; j++)
if (v[i][j]<0) goto found;
found: // s-a gsit n poziia i, j
Programul cu un goto poate fi scris ntotdeauna fr goto, chiar dac preul pentru aceasta este o
variabil suplimentar sau nite controluri repetate. De exemplu, cutarea n tablou devine:
found=0;
for (i=0; i<N && found; i++)
for (j=0; j<M && found; j++) found = v[i][j]<0;
if (found) { .. } // a fost gsit la i-1, j-1
else {..} // nu s-a gsit
Instruciunea vid are forma ; i este utilizat pentru a evita existena unei etichete
chiar n faa unei acolade de nchidere a unui bloc sau n cazul n care corpul unui ciclu nu
conine nici o instruciune.

Tipuri de date recursive, operaii asupra listelor, arborilor.


Listele simplu i dublu lnuite, arborii snt formate din elemente definite de structuri cu
autoreferire. Ele snt consecutiviti de elemente de acelai tip, numrul crora se schimb
dinamic n procesul de executare a programului. Lista liniar F, care const din elemente D1,
D2,...,Dn, grafic se poate reprezenta n modul urmtor:
D1 D2 D3 ... Dn
Asupra elementelor listelor se pot efectua urmtoarele operaii:
- de cutare a elementului dup criteriul dat;
- de determinare a primului element n lista liniar;
- insertarea unui element nou nainte sau dup o component indicat a listei liniare;
- eliminarea unui element din list;
- sortarea componentelor listei.
Metodele de stocare a listelor liniare se divid n metode consecutive i stocare lnuit.

15
Elementele listei liniare, utilizate de metodele consecutive, se aloc ntr-un tablou d de
dimensiune fix, de exemplu, 100, i lungimea listei este indicat de variabila l, adic se declar
float d[100]; int l;
Dimensiunea 100 mrginete dimensiunea maximal a listei liniare. Lista F n tabloul d se
formeaz n modul urmtor:
d[0]=7; d[1]=10; l=2;
Lista obinut se pstreaz n memorie n conformitate cu schema:

l: 2
d: 7 10 ...
[0] [1] [2] [3] [98] [99]
Pentru organizarea elementelor n form de list simplu lnuit, se utilizeaz structurile
care snt legate cte o component n lan, nceputul creia (prima structur) este indicat de
pointerul dl. Structura care definete elementul listei conine n afar de componenta
informaional i un pointer la urmtorul element din list. Descrierea acestui tip de structur cu
autoreferire i pointerul n cauz se face n modul urmtor:
typedef struct nod // structura cu autoreferire
{float val; // valoarea componentei informaionale
struct nod *urm ; // pointerul la urmtorul element din lan
} DL;
DL *p; // pointerul la elementul curent
DL *prim; // pointerul la nceputul listei
Pentru alocarea memoriei elementelor listei n C++, se utilizeaz operatorul de alocare: new
care apare sub forma
pointer_la_nume = new nume [ iniializator];
care ncearc s creeze un obiect nume prin alocarea unui numr egal cu sizeof(nume) de octei n
memoria heap, adresa acestuia este returnat i asignat variabilei pointer_la_nume. n cazul n
care alocarea nu este efectuat cu succes, se returneaz valoarea NULL.
Operatorul de eliberare delete este apelat printr-o instruciune de forma
delete pointer_la_nume ;
elibereaz memoria alocat ncepnd cu adresa coninut de pointer_la_nume. De exemplu,
p=new(DL);
p->val=10;
p->n=NULL;
dl=new(DL));
dl->val=7;
dl->n=p;
n ultimul element al listei pointerul la elementul vecin are valoarea NULL. Lista are urmtoarea
form:

Operaii asupra listelor simplu lnuite

16
Fiecare element al listei simplu lnuite reprezint o structur alctuit din dou
componente: val folosit pentru componenta informaional i p pentru pointer la urmtorul
element din lista lnuit. Pointerul dl indic adresa de alocare pentru primul element al listei.
Pentru toate operaiile asupra listei se va utiliza urmtoarea descriere a structurii elementelor
liste:
typedef struct nod
{ float val;
struct nod * urm;
} NOD;
int i,j;
NOD * prim, * r, * p;
Pentru executarea operaiilor pot fi utilizate urmtoarele fragmente de program:
1) formarea listei simplu lnuite:
float x=5; int n=1;
p=new(nod);
r=p;
p->val=x;
p->urm=NULL;
prim=p;
while (p->val !=0)
{ p=new(nod); n++;
p->val=x-1.0*n;
r->urm=p;
p->urm=NULL;
r=p; }
2) tiparul elementului j:
r=prim;j=2;
while(r!=NULL && j<n-1)
{ if (r==NULL) printf("\n nu este elementul %d ",j);
else printf("\n elementul %d este egal cu %f ",j++,r->val);
r=r->urm; }
3) tiparul ambilor vecini ai elementului determinat de pointerul p :

p=prim;
if((r=p->urm)==NULL) printf("\n nu are vecin din dreapta");
else printf("\n vecinul din dreapta este %f", r->val);
if(prim==p) printf("\n nu are vecin din stnga" );
else { r=prim;
while( r->urm!=p ) r=r->urm;
printf("\n vecinul de stnga este %f", r->val); }
4) eliminarea elementului care este succesorul elementului n cauz, la care indic pointerul

17
p=prim;
if ((r=p->urm)==NULL) printf("\n nu este succesorul ");
p->urm=r->urm; delete(r->urm);
5) insertarea noului element cu valoarea newval=100 dup elementul determinat de pointerul p:

r=new(NOD);
r->urm=p->urm; r->val=100; p->urm=r;
Organizarea listelor dublu lnuite
Lista dublu lnuit este o list n care fiecare element conine doi pointeri: unul la
precedentul element, altul la succesorul element din list. Lista dublu lnuit n program se
poate determina cu ajutorul urmtoarelor descrieri:
typedef struct ndd
{ float val; // valoarea informaional a componentei
struct ndd * succesor; // pointer la succesorul element al //listei n
struct ndd *precedent; // pointer la precedentul element al //listei m
} NDD;
NDD * prim, * p, * r;
Interpretarea grafic a listei F=< 2,5,7,1 > ca list dublu lnuit este urmtoarea:

Insertarea noului element cu valoarea newval dup elementul determinat de pointerul p, se


efectueaz de operatorii
r=new(NDD);
r->val=newval;
r->succesor=p->succesor;
(p->succesor)->precedent=r;
p->=r;
Eliminarea elementului urmat de elementul la care indic pointerul p se efectueaz n modul
urmtor:
p->succesor=r;
p->succesor=(p->succesor)->succesor;
( (p->succesor)->succesor )->precedent=p;
delete r;
Lista liniar este ciclic, dac ultimul element al listei indic la primul element, iar pointerul dl
indic la ultimul element al listei. Schema listei ciclice pentru lista F=< 2,5,7,1 > este
urmtoarea:

La rezolvarea problemelor pot aprea diferite tipuri de liste lnuite.


Stiv i coad
n funcie de metoda de acces la elementele listei liniare, pot fi cercetate urmtoarele
tipuri de liste liniare: stive, cozi i cozi de tip vagon.

18
Stiva este o consecutivitate de elemente de acelai tip variabile scalare, tablouri,
structuri sau uniuni. Stiva reprezint o structur dinamic, numrul de elemente a creia variaz.
Dac stiva n-are elemente, ea este vid.
Asupra elementelor stivei pot fi efectuate urmtoarele operaii:
- verificarea dac stiva este vid,
- includerea unui element nou n vrful stivei;
- eliminarea elementului din vrful stivei;
- accesarea elementului din vrful stivei, dac stiva nu este vid.
Astfel, operaia de includere i eliminare a elementului, de asemenea, accesarea
elementului are loc numai asupra elementului din vrful stivei.
Coada este o list liniar n care elementele listei se elimin din capul listei i elementele
noi se includ prin coada listei.
Coad de tip vagon este o list liniar n care includerea i eliminarea elementelor din
list se efectueaz din ambele capete (vrful i sfritul) ale listei.
Stiva i coada se organizeaz att static prin intermediul tabloului, ct i dinamic prin
list (simplu sau dublu lnuit).
Vom cerceta cum se utilizeaz lista n form de stiv pentru implementarea calculrii
expresiei aritmetice n form invers polonez. n astfel de mod de prezentare a expresiei
operaiile se nregistreaz n ordinea executrii lor, iar operanzii se afl nemijlocit n faa
operaiei. De exemplu, expresia (6+8)*5-6/2 n forma invers polonez are forma: 6 8 + 5 * 6 2
/-
Utiliznd noiunea de stiv, expresia aritmetic n form invers polonez se execut
print-o singur trecere de examinare a expresiei. Fiecare numr se introduce n stiv, iar operaia
se execut asupra urmtoarelor dou elemente din vrful stivei, nlocuindu-le cu rezultatul
operaiei efectuate. Dinamica schimbrilor din stiv va fi urmtoarea:
S = < >; <6>; <6,8>; <14>; <14,5>; <70>;
<70,6>; <70,6,2>; <70,3>; <67>.
Mai jos este descris funcia eval, care calculeaz valoarea expresiei indicate n tabloul m n
form de expresie invers polonez, m[i]>0 indic numrul nenegativ, iar valoarea m[i]<0 -
operaia. n calitate de coduri pentru operaiile de adunare, scdere, nmulire i mprire se aleg
numerele: -1, -2, -3, -4. Pentru organizarea stivei se utilizeaz tabloul interior stack. Parametrii
funciei snt tabloul de intrare m i lungimea sa l.
float eval (float *m, int l)
{ int p,n;
float stack[50],c;
for(int i=0; i < l ;i++)
if ((n=m[i])<0)
{ c=st[p--];
switch(n)
{ case -1: stack[p]+=c; break;
case -2: stack[p]-=c; break;
case -3: stack[p]*=c; break;
case -4: stack[p]/=c; } }
else stack[++p]=n;
return(stack[p]); }
Arbori

19
Arborii snt structuri de date dinamice, cu autoreferire. Prin arbore se nelege o mulime
finit i nevid de elemente (noduri): A={A1, A2,..., An}, n>0 cu urmtoarele proprieti:
exist un nod i numai unul care se numete rdcina arborelui,
celelalte noduri formeaz submulimi ale lui A, care formeaz fiecare cte un arbore, arborii
respectivi se numesc subarbori ai rdcinii.
ntr-un arbore exist noduri crora nu le corespund subarbori. Astfel de noduri se numesc
terminale.
n multe aplicaii se utilizeaz noiunea de arbori binari. Dac mulimea de elemente a
arborelui binar este vid, se consider c arborele const numai din rdcin. Dac mulimea de
elemente este nevid, arborele binar se divide n dou submulimi: subarborele drept i cel de
stnga. Arborele binar este ordonat, deoarece n fiecare nod subarborele stng se consider c
precede subarborele drept. Un nod al unui arbore binar poate s aib numai un descendent:
subarborele drept sau subarborele stng. De exemplu, un nod al unui arbore binar poate fi o
structur care poate fi definit n felul urmtor:
typedef struct tnod
{ int nr, int f; //declaraii
struct tnod *st; // este pointerul spre subarborele stng al //nodului curent
struct tnod *dr; // este pointerul spre subarborele drept al //nodului curent
} TNOD;
Asupra arborilor binari pot fi definite urmtoarele operaii:
afiarea componentelor informaionale ale nodului,
specificarea criteriului de determinare a poziiei n care s se inserteze n arbore nodul
curent;
determinarea echivalenei a doi arbori;
insertarea unui nod terminal ntr-un arbore binar;
accesarea unui nod al arborelui,
parcurgerea unui arbore;
tergerea unui arbore.
Afiarea componentelor informaionale ale nodului se poate de efectuat prin funcia:
void prelucrare (TNOD *p)
{printf(numrul = %d apariii= %d \n, p->nr, p->f);}
Criteriul de determinare a poziiei, n care s se inserteze n arbore nodul curent, se
definete de funcia:
int criteriu(TNOD *p, *q)
{ if (q->nr < p -> nr )
return 1; // insertarea nodului curent
//n subarborele stng al nodului spre care indic
//pointerul p
if (q->nr > p-> nr )
return 1; // insertarea nodului curent
//n subarborele drept al nodului spre care indic //pointerul p
}
Insertarea unui nod terminal ntr-un arbore binar poate fi efectuat prin urmtoarea
funcie:
TNOD* insert_nod()
{ TNOD *parb, *p, *q;

20
int n=sizeof(TNOD);
if (parb ==0)
{ parb=p; return p; }
int i;
q=parb;
for(;;)
if ((i=criteriu(q,p)) <0) {q->st=p; return p; }
else { q=q->st; continue; }
if (i>0)
if (q->dr ==0)
{q->dr=p; return p;}
else {q=q->dr; continue; }
return eq(q,p); }
}
if(p==0)
{ printf(eroare: memorie insuficient\n); exit(1);}
elibnod(p); return 0; }
Accesarea unui nod al unui arbore poate fi realizat prin urmtoarea funcie:
TNOD * cauta (TNOD *p)
{TNOD *parb, *q;
if (parb==0) return 0;
int i;
for (q=parb;q;)
if ((i=criteriu(q,parb))==0) return q;
else if(I<0) q=q->st;
else q=q->dr;
return 0; }
Parcurgerea unui arbore poate fi efectuat n trei modaliti: n preordine; n inordine; n
postordine.
Parcurgerea n preordine presupune accesul la rdcin i apoi parcurgerea celor doi
subarbori ai si: mai nti subarborele stng, apoi cel drept.
void preord (TNOD *p)
{ if (p!=0)
{ prelucrare(p); preord(p->st); preord(p->dr); }
}
Parcurgerea n inordine presupune parcurgerea mai nti a subarborelui stng, apoi accesul
la rdcin i n continuare se parcurge subarborele drept.
void inord (TNOD *p)
{ if (p!=0)
{inord(p->st); prelucrare(p); inord(p->dr);}
}
Parcurgerea n postordine presupune parcurgerea mai nti a subarborelui stng, apoi a
arborelui drept i, n final, accesul la rdcina arborelui.
void postord (TNOD *p)
{ if (p!=0)
{ postord(p->st); postord(p->dr); prelucrare(p); }

21
}
tergerea unui arbore poate fi efectuat de urmtoarea funcie:
void elib_nod(TNOD *p)
{ delete(p); }
void sterge_arbore (TNOD *p)
{ if (p!=0)
{ postord(p->st); postord(p->dr); elibnod(p); }
}
Recursivitatea ca metod de programare
Recursivitatea presupune o repetare. Ea const n apelarea unei funcii de ctre ea nsi.
Funcia se numete recursiv dac n momentul executrii sale funcia se apeleaz pe ea
nsi, sau indirect, printr-o succesivitate de apeluri ale altor funcii.
Funcie este nemijlocit recursiv dac ea se apeleaz din corpul aceleiai funcii. De
exemplu:
int a()
{.....a().....}
Funcia este indirect recursiv dac se efectueaz apel recursiv prin intermediul unei
succesiviti de apeluri ale altor funcii. Toate funciile componente ale acestei succesiviti de
apeluri se socot recursive. De exemplu,
a(){.....b().....}
b(){.....c().....}
c(){.....a().....} .
Funciile a,b,c snt recursive, deoarece la apelul unei din funcii are loc apelul altor
funcii inclusiv i pe ea nsi.
Execuia algoritmului recursiv presupune crearea unui numr (finit) de copii ale
algoritmului, care corespund diferitelor valori ale unei variabile. n construirea algoritmului
recursiv este inclus o condiie de terminare a apelrii recursive de o expresie; care prin apelri
succesive valoarea ei crete pn la o valoare ce satisface condiia de finalizare a recursivitii. La
executarea programului cu funcii recursive se creeaz copii ale acestora, fiecare din ele
corespunznd unei valori a expresiei de recursie. Att timp ct expresia recursiei se calculeaz
pn cnd crete pn la o valoare ce satisface condiia de finalizare a recursivitii, se spune c
are loc recursia nainte. Cnd expresia atinge valoarea soluiei recursiei, se execut copiile create,
astfel nct se obine soluia problemei. n acest caz are loc recursia napoi. Executarea
programelor cu funcii recursive necesit mult memorie i mult timp de calcul, cu o
complexitate mai mare dect cele nerecursive.
Recursivitatea ca metod de programare este mai eficient, codul programelor cu funcii
recursive este mai compact i mai uor de neles.
n limbajul C++ funciile pot s se autoapeleze. Exemplul clasic de funcie recursiv este
calcularea factorialului numrului N! = 1*2*3*...*N.
Vom numi aceast funcie factorial().
long factorial(int n) {return((n==1)?1: n*factorial(n-1) ); }
Apelul funciei recursive creeaz noi copii ale variabilelor locale i ale parametrilor pentru clasa
de memorie auto i register, valorile lor din apelurile precedente se pstreaz. Pentru fiecare
moment snt accesibile numai valorile apelului curent. Variabilele declarate cu clasa de memorie
static nu necesit crearea noilor copii. Valorile lor snt accesibile n orice moment de executare a
programului. n corpul funciei recursive este necesar de indicat condiia de ieire din procesul

22
recursiv, n caz contrar sistemul de calcul poate intra n impas. De exemplu, funcia de tiprire
unui numr (ca un ir de caractere): poate fi apelat de ea nsi, adic s fie recursiv
void print_cifre(int n)
{ int i;
if (n<0)
{ putchar(-); n=-n; }
if ((i=n/10)!=0) print_cifre(i);
putchar(n%10+0); }
Programul de mai jos calculeaz funcia Akkerman cu utilizarea funciei recursive ackr
i funciei auxiliare smacc:
// calculul recursiv al funciei kkerman
# include <stdio.h>
int smacc( int n,int x ) // funcie auxiliar
int ackr( int n, int x, int y) // funcie recursiv
void main () // funcia n care se apeleaz funcia
{ int x,y,n,t;
int ackr(int, int, int);
scanf("%d %d %d",&n,&x,&y);
t=ackr(n,x,y);
printf("%d",t); }
int smacc( int n,int x ) // funcie auxiliar
{ switch (n )
{ case 0: return(x+1);
case 1: return (x);
case 2: return (0);
case 3: return (1);
default: return (2); }
}
int ackr( int n, int x, int y) // funcie recursiv
{ int z;
int smacc( int,int);
if(n==0 || y==0) z=smacc(n,x);
else { z=ackr(n,x,y-1); // apeluri recursive ackr(...)
z=ackr(n-1,z,x); }
return z; }
Rezultatul ndeplinirii programului:
146 // datele iniiale
10 // rezultatul obinut
Fiierele input/output ale limbajul C++. Deschiderea i nchiderea fiierelor. Citirea i
scrierea n fiiere.
Limbajul C++ include n sine funciile standard input/output ale limbajului C de
prelucrare a fiierelor la nivelul jos, inferior i superior.
Funciile de prelucrare a fiierelor de nivel inferior pot fi utilizate prin includerea
fiierelor io.h, fcntl.h i stat.h.
Pentru deschiderea unui fiier se utilizeaz funcia open care are urmtoarea form
sintactic:

23
df = open();
unde df este variabil de tip int (descriptorul de fiier).
Funcia open are urmtorii parametri: se indic calea de acces la fiier i modalitatea de
accesare a componentelor fiierului. Modalitatea de accesare a componentelor se indic prin una
din urmtoarele constante:
O_RDONLY fiierul se deschide numai pentru citirea
componentelor lui
O_WRONLY fiierul se deschide numai pentru
nregistrarea componentelor lui
O_RDWR fiierul se deschide pentru citirea i
nregistrarea componentelor lui
O_APPEND fiierul se deschide pentru adugarea
componentelor noi la sfritul lui
O_BINARY fiierul se prelucreaz binar
O_TEXT fiierul se prelucreaz textual
Pentru a crea un fiier, se utilizeaz funcia creat cu urmtorii parametri: calea de acces la
fiierul creat i modalitatea de utilizare a fiierului. Al doilea parametru se indic de una din
urmtoarele constante:
S_IREAD fiierul va fi creat numai pentru citire
S_IWRITE fiierul va fi creat numai pentru nregistrare
S_IEXE fiierul va fi creat numai pentru executare
Citirea dintr-un fiier se efectueaz prin funcia read indicndu-se urmtorii parametri:
read(df, buf, lung)
unde df este descriptor de fiier; buf pointer spre zona de memorie n care se va pstra
nregistrarea citit din fiier; lung lungimea n octei a nregistrrii citite.
nregistrarea n fiier se efectueaz prin funcia write. Aceast funcie are aceiai
parametri ca i funcia read.
Poziionarea ntr-un fiier se efectueaz prin funcia fseek(df, deplasare, origine). Aceast
funcie are urmtorii parametri: df descriptorul fiierului, deplasarea indic numrul de octei
pentru a deplasa capul de citire sau scriere al discului, origine are urmtoarele valori pentru
efectuarea deplasrii: 0 fa de nceputul fiierului, 1- fa de poziia curent a capului de citire
sau nregistrare, 2 fa de sfritul fiierului.
nchiderea fiierului se efectueaz de funcia close (df).
Exemplu de utilizare ale acestor funcii:
char nfis[]=fisier1.dat;
int df; char *p;
df=open(nfis,O_RDONLY);
read(df,p,80);
close(df);
Prototipurile funciilor de prelucrare a fiierelor de nivel superior pot fi utilizate prin
includerea fiierului stdio.h.
Fiierele input/output standard se efectueaz prin intermediul funciilor scanf i printf,
gets, getc, getch i puts, putc, respective.
Funciile getc(), getch() citesc cte un caracter din fiierul standard input .

24
Funciile scanf i fscanf, printf i fprintf permit citirea, respectiv, afiarea uneia sau a mai
multor valori la intrarea standard sau dintr-un fiier, respectiv, ieirea standard sau nregistrare
ntr-un fiier. Prototipurile acestor funcii se afl n biblioteca stdio.h.
Principiul de utilizare al funciei printf const n asocierea unei liste, care conine indicaii
de formatare, dat sub forma unui ir de caractere, o list de variabile. Ambele funcii utilizeaz
specificaiile de scriere sau citire plasate ntr-o constant de tip ir de caractere, urmat de o list
de argumente.
Funcia de afiare printf utilizeaz ca argumente nume de variabile, iar funcia de citire
scanf utilizeaz drept argumente adrese de variabile. De exemplu,
#include<stdio.h>
void main()
{printf("intreg:%6i \n real: %9.3f ",316,144.82) ;
int z;
printf("Introdu valoarea z:");
scanf("%d",&z);
printf("%6d",z);
}
Rezultatul ndeplinirii programului:
intreg: 316
real: 144.820 Introdu valoarea z:500
Valoarea z: 500
Lista este parcurs de la stnga la dreapta. Fiecare semn este asociat cu caracterul care l urmeaz
i este interpretat drept caracter de control. Caracterele de control utilizate snt:
\n avans la nceput de linie nou;
\r poziionare la nceputul liniei curente;
\t tabulator;
\a emite un semnal sonor .
Fiecare semn % este interpretat ca nceputul descrierii caracteristicilor de tiprire a unei valori.
Cele mau utilizate semne snt urmtoarele:
Semnul Descrierea
%d, un ntreg zecimal este ateptat la intrare; argumentul
%i corespunztor trebuie s fie un pointer la ntreg;
%o un ntreg octal este ateptat la intrare; argumentul
corespunztor trebuie s fie un pointer la ntreg;
%x un ntreg hexazecimal este ateptat la
intrare;argumentul corespunztor trebuie s fie un
pointer la ntreg;
%h un ntreg short este ateptat la intrare; argumentul
trebuie s fie un pointer la un ntreg short;
%u un ntreg fr semn zecimal este ateptat la intrare;
argumentul s fie pointer la ntreg;
%f un numr n virgul flotant este ateptat; argumentul
corespunztor trebuie s fie un pointer la un cmp
float. Caracterul de conversie e este *f. Formatul
prezentat la intrare pentru un float este alctuit dintr-
un semn opional;

25
%e un numr n virgul flotant este ateptat; argumentul
corespunztor trebuie s fie un pointer la un cmp
double. Caracterul de conversie e este *e. Formatul
prezentat la intrare pentru un double este alctuit dintr-
un semn opional, un ir de numere care pot s conin
i un punct zecimal i un cmp de exponent care este
format din E sau e, urmat de un ntreg cu semn;
%c un singur caracter este ateptat la intrare; argumentul
corespunztor trebuie s fie un pointer la caracter. n
acest caz, ignorarea caracterelor albe este suprimat;
pentru a citi urmtorul caracter, altul dect caracterele
albe se va utiliza %1s;
%s un ir de caractere este ateptat; argumentul
corespunztor trebuie s fie un pointer al unui tablou de
caractere, destul de mare pentru a ncpea irul i un
terminator \0, care va fi adugat.
Caracterele de conversie d, u, i ,o, i x pot fi precedate de litera l, pentru a indica un
pointer la long, mai degrab dect la int, care apare n lista de argumente. Similar, litera l naintea
lui e sau f indic un pointer la double n lista de argumente. De exemplu:
int i;
float x;
char nume[50];
scanf (%d%f%s,&i,&x,nume) ;
cu linia de intrare
25 244.32E-1 Mircea
va asigna lui i valoarea 25, lui x valoarea 244.32E-1, iar lui nume valoarea Mircea. Cele trei
cmpuri de la intrare pot fi separate de oricte spaii, taburi i caractere de linie nou. Apelarea
int i;
float x;
char nume[50];
scanf (%2d%4.2f%2s,&i,&x,nume) ;
cu linia de intrare
25 244.32E-1 Mircea
va asigna 25 lui i, 44.32 lui x, iar nume va obine valoarea Mi.
Cele mai utilizate secvene asociate valorilor de tip ntreg snt %ssNX sau %ssNU, unde s
este semnul + dac se dorete afiarea explicit a semnului, - arat c se va face o aliniere la
stnga. N este un numr care arat pe cte poziii se va face afiarea. De exemplu,
#include<stdio.h>
void main()
{ printf("% -+5i",3); }
programul indicat va afia valoarea +3 prin aliniere la stnga n conformitate cu specificaiile
date, astfel semnul - cere alinierea la stnga, n cmpul afectat valorii, semnul + cere afiarea
explicit a semnului, cifra 5 arat c afiarea se va face pe 5 poziii, simbolul i arat c va fi
afiat o valoare de tip ntreg.

26
Valorile de tip real pot fi tiprite utiliznd secvene asociate de forma %ssNMf sau
%sSN.tte, n care simbolul M semnific precizia cu care vor fi reprezentate numerele (numrul de
cifre dup punctul zecimal).
Toate caracterele care nu aparin secvenelor de control snt afiate i snt tratate ca iruri
de caractere.
De exemplu,
#include<stdio.h>
void main ()
{ char * p="abracadabra";
char ch=B;
printf("%s %c ", p, ch); }
programul afieaz irul de caractere adresat prin intermediul pointerului p i valoarea variabilei
ch.
Funcia scanf se utilizeaz la iniializarea unor variabile. Funciile scanf i printf snt
utilizate mpreun. Prin funcia printf se afieaz un mesaj care adesea este un comentariu legat
de valoarea care urmeaz s fie introdus. De exemplu, n programul de mai jos am afiat
mesajul numr real, dup care urmeaz apelul funciei scanf care ateapt introducerea unei
valori de tip real sau ntreg:
#include<stdio.h>
void main()
{ float a;
int i;
printf ("Introdu un numr real: ");//utilizatorul va introduce, //la
scanf("%f", &a); //tastatura, un numr urmat de Enter.
printf("\n Introdu un numr intreg: "); //la fel se procedeaz //n cazul variabilei i
scanf ("%i,", &i); // afiarea textului "numr intreg"
printf("\n Numr ntreg: %6i \n Numr real: %9.3f", i, a);
} // va fi urmat de introducerea, la tastatur, a numrului //dorit.
Rezultatul ndeplinirii programului:
Introdu un numr real: 3.14
Introdu un numr intreg: 20
Numr ntreg: 20
Numr real: 3.140
Funciile de scriere i citire anterioare pot fi folosite i n cazul fiierelor. Biblioteca
stdio.h, specific limbajului C, conine definiia unui tip de date FILE. Accesul la un fiier se
face printr-un pointer de tip FILE. Etapele care trebuie s fie parcurse snt definirea unui pointer
de tip FILE i asocierea unui fiier fizic. Pointerul va primi drept valoare adresa unei variabile de
tip FILE, obinut prin intermediul funciei fopen(). Aceast funcie are dou argumente: un ir
de caractere care conine numele fiierului fizic recunoscut de sistemul de operare i un alt ir de
caractere care conine indicaii relativ la modul de utilizare al fiierului. Ultimul parametru poate
conine caracterul
R pentru fiiere deschise pentru citire,
W pentru fiiere deschise pentru creare sau scriere,
T pentru fiiere de tip text sau
B pentru fiiere binare

27
n exemplul de mai jos am creat un fiier prin intermediul unui pointer de tipul FILE i o
iniializare prin funcia fopen(). Pointerul p conine o valoare de tip FILE fumizat de funcia
fopen(), care deschide pentru nregistrare fiierul disk.dat. Am scris n acest fiier dou valori n
acelai mod cum am fcut afiarea la ieirea standard.
#include<stdio .h>
void main()
{ FILE *p;
p = fopen("disk.dat","wt");
fprintf(p,"%6i\n%9.3f", 29, 2.71);
fclose (p) ;
}
Rezultatul ndeplinirii programului:
s-a format fiierul disc.dat (pentru nregistrare) cu urmtorul coninut:
29
2.710

28
Sarcina pentru lucrrile de laborator:
1.
a. Scriei un program care ar numra biii semnificativi, de la dreapta spre stnga, pentru un
numr introdus de la tastatur.
b. Scriei un program care compar dou stive de numere trergi.

2.
a. Scriei un program care efectueaz nmulirea cifrelor unui numr dat.
b. Scriei un program care calculeaz numrul de elemente dintr-o list simplu lnuit care
snt mai mici ca valoarea medie aritmetic a tuturor elementelor acestei liste.
3.
a. Scriei un program care determin un numr obinuit din inversul cifrelor numrului dat.
b. Scriei un program care convertete ntregii fr semn dintr-o list dublu lnuit n
reprezentare binar.
4.
a.Scriei un program care convertete un ntreg ntr-un numr hexazecimal.
b. Scriei un program care permite crearea unui arbore binar i traversarea lui n inordine,
preordine, postordine
5.
a. Scriei un program care calculeaz cel mai mare divizor comun al elementelor dintr-o
consecutivitate.
b. Scriei un program care determin numrul de ordine a numrului minimal dintr-o list
dublu lnuit.

6.
a. Scriei un program care calculeaz suma cifrelor pentru fiecare numr din consecutivitatea
de 100 de numere aleatoare.
b. Scriei un program care determin numrul maximal i cel minimal ntr-o list circular de
100 de numere aleatoare. S se determine consecutivitatea de elemente ce se afl ntre
numerele maximal i cel minimal determinate.

7.
a. Scriei un program care inverseaz un ir de caractere s.
b. Scriei un program care inverseaz cele n elemente ale unei liste simplu lnuit care ncep
de pe poziia p, lsndu-le pe celelalte locul lor.

8.
a. Scriei un program care calculeaz cel mai mare divizor comun dintr-un ir de numere
date.
b. Scriei un program care atribuie unei liste simplu lnuite elementele altei liste n ordine
invers.

9.

29
a. Scriei un program care determin cte numere din consecutivitatea de 100 de numere
aleatoare snt mai mari ca vecinii si.
b. Scriei un program care decide dac o valoare x aparine unei liste dublu lnuite v.
Elementele lui v trebuie s fie n ordine cresctoare. Se tiprete numrul elementului din
list (un numr ntre 0 i n-1), dac x apare n v, i 1, dac nu apare.
10.
a.Scriei un program care convertete un ntreg ntr-un numr binar.
b.Scriei un program care va tipri n ordine invers subconsecutivitatea de numere dintre
valoarea minim i maxim ale unei liste simplu lnuit.

11.
a. Scriei un program care convertete numrul ntreg n n baza zecimal ntr-un ir de
caractere.
b. Scriei un program care inverseaz fiecare element de tip ir de caractere dintr-o list
simplu lnuit.
12.
a. Scriei un program care convertete literele mari n litere mici al unui ir de caractere.
b. S se scrie un program care din lista L1 ce conine numere ntregi s se extrag n lista L2
elementele cu numere impare din lista L1.
13.
a.Scriei un program care convertete un ntreg ntr-un numr octal.
b. Scriei un program care rotete fiecare element al listei dublu lnuite la dreapta cu b
poziii.
14.
a. Scriei un program de convertire a unui numr ntreg ntr-un ir de caractere.
b. Scriei un program care creeaz o list circular a cror valori ale elementelor snt cuprinse
ntre 1 i 100. S se determine frecvena cu care a fost generat fiecare element al listei create.
15.
a. Scriei un program care din 100 de numere aleatoare se determin numrul maximal i cel
minimal. S se determine diferena dintre numrul maximal i cel minimal determinat.
b. Scriei un program care determin cte numere ale unei cozi de 100 de numere aleatoare
snt mai mari ca vecinii si.

30