Sunteți pe pagina 1din 29

Tablouri bidimensionale

Sunt tablouri la care elementele sunt asezate pe linii si coloane.

1
2
3
5
9
0
13 13 13

A=

Declararea matricilor :
Tip_elem nume_mat[nr_max_linii][nr_max_col];
Tip_elem reprezinta tipul elementelor matricei
Nume_mat reprezinta identificatorul variabilei de tip matrice
Exemplu : int a[25][50];
Dimensiunea zonei de memorie ocupata de elemente : sizeof(tip_elem)*nr_max_linii*nr_max_col
Practic, elementele matricei se identifica prin indicele liniei pe care se afla (i) iar indicele coloanei pe care
se afla (j).
a[i][j]
Si in cazul matricelor vorbim de un numar efectiv de linii notat de obicei cu n si numar efectiv de
coloane notate de obicei cu m. Numarul efectiv de elemente este egal cu produsul dintre numarul efectiv
de linii si numarul efectiv de coloane.
Conditii :

0 i<n ; 0 j<m

Citirea
Pentru a atinge atat linia cat si coloana vom folosi doua structure repetitive for :
..
cout<<=n;cin>>n;
cout<<m=;cin>>m;
for(i=0;i<n;i++)
for(j<0;j<m;j++)

{ cout<<a[<<i+1<<j+1<<]=;
cin>>a[i][j];
}

Afisarea
for(i=0;i<n;i++)
{ for(j=0;j<m;j++)
cout<<a[i][j]<< ;
cout<<endl;
}

Prelucrarea elementelor matricei


for(i=0;i<n;i++)
for(j=0;j<m;j++)
<prelucreaza a[i][j]>
Aplicatie : Se citesc de la tastatura doua numere natural m si n apoi elementele intregi ale unei
matrici cu n linii si m coloane. Sa se calculeze, sumaelementele positive din matrice.
#include<iostream.h>
void main()
{ int a[20][50],n,m,I,j,S=0;
cout<<n=;cin>>n;
cout<<m=;cin>>m;
cor(i=0;i<n;i++)
cor(j=0;j<m;j++)
cout<<a[<<i+1<<j+1<<]=;
cin>>a[i][j];
}
for(i=0;i<n;i++)
{ for(j=0;j<m;j++)
if(a[i][j]>0)
S+=a[i][j];
cout<<S=<<S<<endl;
}
Aplicatie : Se citesc de la tastatura elementele natural ale unuei matrici cu n linii si m coloane.
Sa se determine elementele positive, negative si nule din matrice.

#include<iostream.h>
#include<conio.h>
void main()
{ clrscr();
int a[20][50],n,m,I,j,nrp=0,nro=0,nrn=0;
cout<<n=;cin>>n;
cout<<m=;cin>>m;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(a[i][j]>0)
nr=nrp+1;
else
if(a[i][j]==0)
nro++;
else
if(a[i][j]<0)
nrn=nrn+1;
cout<<nrn=<<nrn<<endl;
cout<<nrp=<<nrp<<endl;
cout<<nro=<<nro<<endl;
}

Interschimbarea a doua linii/coloane specificate intr-o matrice

)(

1 2 3
7 8 9
4 5 6
4 5 6

7 8 9
1 2 3
10 11 12
10 11 12

a[i][j] devine a[l1][j]


a[l2-1][j]
a[l3-1][j]
Algoritm de interschimbare intre linii :
..
cout<<l1=;cin>>l1;
cout<<l2=;cin>>l2;
for(j=0;j<m;j++)
{ aux=a[l1-1][j];
a[l1-1][j]=a[l2-1][j];

a[l2-1][j]=aux;
}
Algoritm de interschimbare intre coloane :
..
cout<<c1=;cin>>c1;
cout<<c2=;cin>>c2;
for(j=0;i<n;i++)
{ aux=a[i][c1-1];
a[i][c1-1]=a[i][c2-1]
a[i][c2-1]=aux;
}
Stergerea unei linii sau a unei coloane dintr-o matrice
Stergerea unei linii :

cout<<l=;cin>>l;
for(i=l-1;i<n-1;i++)
for(j=0;j<m;j++)
a[i][j]=a[i+1][j];
n=n-1;
//afisare a[i][j]
Stergerea unei coloane :

cout<<c=;cin>>c;
for(i=0;i<n;i++)
for(j=c-1;j<n-1;j++)
a[i][j]=a[i][j+1];
m=m-1;
//afisare a[i][j]
Aplicatie: Se da o matrice a cu m linii si n coloane cu elemente numere intregi. Se cere :
a) Determinati media aritmetica a elementelor matricii.
b) Stabiliti de cate ori apare o valoare data x ca element al matricii.
c) Determinati numarul de elemente palindrom.
#include<iostream.h>
void main()
{ int a[20][50], i, j, m, n, ogl, ma=0, S=0, nr=0, nrp=0, nro=0, uc, y, x;
float ma;
cout<<n=;cin>>n;

cout<<m=;cin>>m;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
cout<<a[<<i+1<<j+1<<]=;
cin>>a[i][j];
}
nr=m*n;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
S=S+a[i][j];
ma=(float)S/nr;
cout<<ma=<<ma<<endl;
cout<<x=;cin>>x;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
if(a[i][j]==x)
nro=nro+1;
cout<<nro=<<nro<<endl;
for(i=0;i<n;i++)
for(j=0;j<m;j++)
y=a[i][j];
ogl=0;
while(y!=0)
{uc=y%10;
y=y/10;
ogl=ogl*10+uc;
}
if(ogl==a[i][j])
nrp=nrp+1;
}
cout<<nrp=<<nrp<<endl;
}

Matricea patratica
Matricea la care numarul de linii este egal cu numarul de coloane se numeste matrice
patratica.
n=m
Ex declarare: int c[25][25];

Citirea si afisarea matricelor patratice ramane identical cu a unei matrici obisnuite, cu singura
deosebire ca I si j merg pana la n.

a 00 a01 a 02
a 10 a11 a 12
a 20 a21 a 22

Prelucrare in raport cu diagonal principala :


a) Elemente pe diagonal principala : i=j
for(i=0;i<n;i++)
for(i=0;i<n;i++)
for(j=0;j<m;j++)
sau
<prelucreaza a[i][j]>
if(i==j)
<prelucreaza a[i][j]>
b) Elemente aflate sub diagonala principala : i>j
c) Elemente aflate deasupra diagonalei principale : i<j
Aplicatie : Scrieti un program care citeste de la tastatura un numar natural n si construieste o
matrice cu n linii si m coloane ale carei elemente vor primi valori dupa cum urmeaza :
- Elemente aflate pe diagonal
- Elemente de pe prima linie cu exceptia celui de pe diagonal secundara , n.
- Elemente de pe a doua linie cu exceptia celui de pe diagonal secundara, n-1.
#include<iostream.h>
void main()
{ int a[25][25], I,j,n,c;
cout<<n=;cin>>n;
c=n;
for(i=0;i<n;i++)
{ for(j=0;j<n;j++)
if(i+j!=n-1)
a[i][j]=c;
else
a[i][j]=0;
c=c-1;
}
for(i=0;i<n;i++)
for(j=0;j<n;j++)
cout<<a[i][j]<< ;
cout<<endl;
}
}

Implementarea sirurilor de caractere in C++


Putem define un sir de caractere ca o succesiune de caractere cuprinse intre doua
ghilimele si poate sa contina orice caractere, litere mari si mici, cifre, caractere speciale,
delimitatori.
Mai putem define sirul de caractere ca fiind o structura de date formata dintr-o multime
ordonata de caractere in care fiecare character se identifica prin pozitia sa in cadrul multimii.
In C++ implementarea sirurilor de caractere se face sub forma unu tablou unidimensional
ale carui elemente sunt de tip character, fiecare character fiind reprezentat prin codul sau ASCI.
Caracterele sirului vor ocupa pozitii consecutive in vector, incepand cu pozitia 0.
Declararea:
char_nume_sir[dim_max];
Dim_max reprezinta numarul maxim de caractere din sir plus unu.
Exemplu declarare : char s[30]=test;
Dimensiunea efectiva a unui sir de caractere este data de numarul de caractere din sir.
Ceea ce deosebeste un vector de caractere adica un sir de un vector obisnuit este faptul ca in
cazul vectorului de caractere compilatorul C++ memoreaza la sfarsitul sirului de caractere un
character special NULL simbolizat prin constanta \0.

Citirea/Scrierea sirurilor de caractere folosind functii specific C


Citire : gets(sir)
Afisare : puts(sir)
Se gasesc in header-ul stdio.h.
Aplicatie : Se citeste de la tastatura un sir de caractere de maxim 70 de caractere.
a) Sa se afiseze sirul
b) Sa se afiseze caracterele din sir
c) Sa se afiseze numarul literelor mari din sir
#include<iostream.h>
#include<stdio.h>
void main()
{ char s[71];
int nr=0,I;

gets(s);
puts(s);
i=0;
while(s[i]!=\0)
{ cout<<s[i]<<endl;
i++;
}
i=0;
while(s[i]!=\0)
{
if(s[i]>A&&s[i]<=Z)
nr++;
i++;
}
cout<<nr=<<nr<<endl;
}

Citirea/Scrierea cu functii specifice C++


Daca dorim sa citim un singur cuvand atunci putem folosi functia cin>>sir. In schimb functia cin
nu poate citi spatiile albe.
Daca citim Afara ploua vom obitne doar cuvantul Afara. Pentru a elemina acest dezavantaj
vom folosi functia cin.get() care are doua forme ce difera prin numarul de parametrii.
a) cin.get(sir,nr,ch)
sir = sirul de caractere
nr = de tip numeric
ch = de tip character si este optional
Efectul fuctiei va fi urmatorul : se vor citi de la tastatura mai multe caractere, inclusiv caracterele
albe care vor fi scrise in variabila sir pana cand se produce unul din evenimentele :
-

au fost citite nr-1 caractere


a fost intalnit caracterul ch

Exemplu : {char s[30]


cint.get(s,30);
cout<<s<<endl; // Afara ploua
Exemplu : {char s[30]=Dau mancare la gaini;
cin.get(s,30,g);
cout<<s<<endl;//Dau mancare la

}
b) cin.get() este utilizata dupa o functie cin.get cu parametrii pentru a descarca din fluxul
de date ultimul caracter citit care ar impiedica efectuarea unei a doua operatie de citire de
la tastatura.
{ char s1[30], s2[30];
cin.get(s1,30);
cin.get();
cin.get(s2,30);
cin.get();
cout<<s1<< <<s2<<endl;
}
Determinarea lungimii effective a unui sir de caractere
C++ ne pune la dispozitie o functie predefinita pentru a determina lungimea efectiva a unui
sir de caractere.
strlen(sir) se gaseste in string.h
Aplicatie : Se citeste de la tastatura un sir s cu maxim 70 de caractere. Sa se determine
lungimea efectiva a sirului.
#include<iostream.h>
#include<string.h>
void main()
{ char s[71];
int n;
cin.get(s, 70);
n=strlen(s);
cout<<n<<endl;
}

Tipul pointer
Sirurile de caractere pot fi manipulate cu ajutorul unei variabile de tip pointer catre tipul char.
Un pointer este o variabila care retine adresa unei alte variabile.
Compilatorul C++ vede numele unui tablou ca o constanta simbolica de tip adresa, deci ca pe un
pointer constant, si numele sirului de caractere va fi interpretat ca o constanta de tip pointer.
.
{char *p, *q;
p=ana are mere;

cout<<p<<endl;
q=p++;
cout<<q<<endl;
}
p si q se numesc pointer catre char. Un pointer este identificat prin faptul ca are in fata in zona de
declaratii simbolul *.

Concadenarea a doua siruri de caractere


Se adauga la sfarsitul sirului destinatie continutul sirului sursa.
Functiile care permit aceasta operatie sunt urmatoarele :
a) strcat(sir_destinatie, sir_sursa)
Functia va intoarce un pointer catre sirul destinatie. In sirul destinatie este adaugat la sfarsit sirul
sursa inclusive caracterul NULL.
b) Strncat(sir_destinatie, sir_sursa, n)
In sirul destinatie se adauga primele n caractere din sirul sursa. Functia adauga la sfarsit
caracterul NULL.
Exemplu:

{ char sir1[256], sir2[256];


cout<<primul sir;
cint.get(sir1, 256);
cin.get();
cout<<al doilea sir;
cin.get(sir2,256);
strcat(sir1,sir2)
cout<<sir1<<endl;
strcat(sir2,sir1)
cout<<sir2<<endl;
}

Functii pentru copierea unui sir de caractere in alt sir de caractere


Cu ajutorul acestor functii este simulate operatia de atribuire intre doua siruri de caractere.
a) Strlcpy(sir_destinatie, sir_sursa);
Sunt copiate prin sirul sursa in sirul destinatie toate caracterele inclusive caracterul NULL.
Functia furnizeaza ca rezultat un pointer care indica adresa sirului destinatie.
b) Strncpy(sir_destinatie, sir_sursa, n)
Functia copie primele caractere din sirul sursa in sirul destinatie inclusive caracterul NULL.
Functia returneaza un pointer care retine adresa sirului destinatie.
c) Stpcpy(sir_destinatie, sir_sursa)

Copie continutul sirului sursa in sirul destinatie inclusive caracterul NULL, numai ca de aceasta
dada este furnizat un pointer care indica sfarstiul sirului destinatie.
Aplicatie : Se citesc doua siruri cu maxim 30 de caractere. Realizati copierea lui s1 in s2; s2 in
s1.
#include<iostream.h>
#include<string.h>
void main()
{ char s1[31], s2[31];
cout<<primul sir;
cin.get(s1,31);
cin.get();
cout<<al doilea sir;
strcpy(s2,s1);
cout<<s2<<endl;
strcpy(s1,s2);
cout<<s1<<endl;
}
Compararea a doua siruri de caractere
Compararea se realizeaza in functie de codurile ASCI ale caracterelor aflate pe pozitii identice.
(comparare lexico-grafica)
a) Strcmp(s1, s2) intoarce 0 daca s1=s2
Intoarce un rezultat pozitiv daca s1>s2
Intoarce un rezultat negative daca s1<s2
b) Stricmp(s1,s2) lucreaza la fel ca functia anterioara fara sa faca diferenta intre litere mari
si mici
c) Strncmp(s1,s2,n) compara primele n caractere din sirurile s1 si s2 returnand un rezultat
la fel ca strcmp.
d) Strncmpi(s1,s2,n) compara primele n caractere din cele doua siruri fara sa tina cont de
diferenta dintre literele mari si cele mici.
**C++ ne pune la dispozitie o functie predefinita care inverseaza sirul de caractere :
Strrev(sir) functia furnizeaza un pointer care indica adresa sirului inversat

Transformarea literelor mari in litere mici si invers


1) Folosind codul ASCI

Lit_mica=(char)((int) lit_mare + 32)


Lit_mare=(char)((int)lit_mica 32)
2) Din #ctype.h pot fi folosite functiile :
Tolower(ch)
Toupper(ch)
3) Din #string.h putem folosi functiile :
Strlwr(sir) transforma toate literele mari in litere mici. Daca literele erau mici le lasa asa.
Strlupr(sir) transforma literele mici in litere mari. Daca erau deja mari, le lasa asa.

Cautarea unui caracter intr-un sir


Pentru a cauta un caracter ch intr-un sir putem folosi functia :
strchr(sir, ch) - functia returneaza un pointer catre prima aparitie a caracterului in sir.
strrchr(sir, ch) functia returneaza un pointer catre ultima aparitie a caracterului in sirul
respectiv

Functii pentru conversii


Conversia unui sir de caractere in numar

atoi(sir) converteste intr-un intreg


atol(sir) converteste intr-un intreg lung
atof(sir) converteste intr-un real scurt (float)
strtol(sir, &p, b) converteste sirul de caractere intr-o valoare numerica intreaga de tip
long.Functiei I se furnizeaza baza de numeratie prin intermediul parametrului b. Functia
furnizeaza prin intermediul parametrului p, pozitia primului character ce nu poate fi
convertit.

Conversia unui numar in sir de caractere :

itoa(n,sir,b) valoarea intreaga de tip long n exprimata in baza de numeratie b este


convertita in sirul de caractere sir.
Ultoa(n,sir,b) converteste valoarea intreaga fara semn n exprimata in baza de numeratie
n, in sirul sir.
Ecvt(n,m,&p,&s) converteste numarul real exprimat in dubla precizie n, in sirul de
caractere. (m precizeaza numarul de caractere ale sirului)

Functia furnizeaza prin intermediul parametrului p, pozitia punctului zecimal iar prin s , semnul.
Fcvt(n,m,&p,&s) functioneaza la fel ca precedent cu deosebirea ca parametrul exprima
numarul de caractere ale partii zecimale.

Inregistrari
Inregistrarea este o structura de date formata dintr-un ansamblu de date neomogene intre care
exista o legatura de continut. Elementele structurii se numesc campuri si pot fi identificate prin nume.
Putem afirma ca inregistararea este o structura de date neomogena, in plus inregistrarea este o structura de
date liniara, adica campurile sunt asezate in locatii succesive de memorie ca si in cazul tabloului de
caractere.
Declarare:
Se foloseste cuvantul rezervat struct si exista 3 variante de declarare:
Var 1:
struct nume_struct
{tip1 camp11,camp12.......camp1n;
.......................................................
tip n campn1,campn2,.......campnn;
};
nume_struct

nume_var;

Ex: struct elev


{char nume[30], pren[30];
float media;
int nrmat;
};
elev e1,e2;
Var 2:
struct nume_struct
{<descriere_campuri>;
}nume_var;

Ex: struct elev

{char nume[30],pren[30];
float media;
int nrmat;
}e1,e2;
Var 3:
struct
{<descriere_campuri>;
}nume_var;
Ex: struct
{char nume[30],pren[30];
float media;
int nrmat;
}e1,e2;
Tipul struct este un tip de data anonim definit de utilizator. Putem asigna un nume tipului de data
astfel definit folosind cuvantul rezervat typedef si sintaxa typedef<tip>nume_tip;

Ex: typedef int intreg;


intreg a,b;
typedef struct
{char nume[30],pren[30];
float media;
int nrmat;
}Telev;
Telev e1,e2;

Accesul la campurile unei inregistrari se realizeaza prin operatorul . si cu sintaxa:


nume_var.nume_camp.

Se numeste . operatorul de selectie a membrului unei structuri si leaga numele structurii de


numele membrului. Este un operator binar de prioritate maxima.
O structura poate fi initializata inca de la declarare:
Telev e1={Popescu,Ion,9.42,105};
Intre 2 variabile de tip struct este permisa atribuirea directa
Ex: e2=e1;

Lungimea zonei de memorie necesara pentru a retine datele unei variabile de tip struct se obtine
prin insumarea dimensiunilor tuturor campurilor variabilelor de tip struct.
Aplicatie :Sa se defineasca o structura de date care sa contina informatii despre o carte: titlu, anul
aparitiei, pret. Sa se citeasca informatiile despre aceasta carte si sa se afiseze titlul, anul si pretul.

#include<iostream.h>
#include<string.h>
void main( )
{ struct carte
{ char titlu[30],autor[30];
int an_ap;
float pret;
};
carte c;
cout<<Date despre carte:<<endl;
cout<< "titlul :" ; cin.get(c.titlu,30) ;
cin.get( );
cout<<nume autor:;cin.get(c.autor,30);
cin.get( );
cout<<anul aparitiei:;cin>>c.an_ap;
cout<<pret:;cin>>c.pret;

cout<<c.titlu<< <<c.autor<< <<c.pret<< endl;


}

Vector de inregistrari
Etapele pentru declararea unui vector de inregistrari sunt urmatoarele :
- Definirea inregistrarii
- Declarare variabia de tip vector de inregistrari
nume_struct

nume_vector[dim_max];

Exemplu declarare :
struct clasa
{ int etaj, nr_loc;
char numar;
};
clasa v[30];
Accesul la un camp pentru elemental I se va face sub forma nume_vector[i].nume_camp
Exemplu :
v[i].etaj
v[i].nr_loc
v[i].numar
Aplicatie : Intr-o clasa sunt maxim 30 de elevi, fiecare elev fiind identificat prin nume si
prenume. Pastram si informatiile referitoare la media elevului.
Se citesc de la tastatura n numere de elevi in clasa apoi se citesc datele despre cei n elevi.
Sa se afiseze elevii descrescator dupa medie.
#include<iostream.h>
#include<string.h>
void main()
{ struct clasa
{ char nume[30], prenume[30];
float media;
};
elev v[30], aux;
int i, n, j;
cout<<Dati nr. De elevi : ;
cin>>n<<i<<:;
for(i=0; i<n; i++)
{ cout<<Numele pentru elevul : ;

cin.get (v[i].nume, 30);


cin.get ();
cout<<media pentru elevul <<i<<:;
cin>>v[i].media;
}
for(i=0; i<n-1; i++)
for(j=i+1; j<n; j++)
if(v[i].media < v[j].media)
{ aux=v[i];
v[i]=v[j];
v[j]=aux;
}
for(i=0; i<n; i++)
cout<<v[i].nume<< <<v[i].prenume<< <<v[i].media<<endl;
}
Inregistrari imbricate
Sa presupunem ca pe langa clasa, media, numele si prenumele unui elev, ca informatii trebuie sa
mai adaugam si data de nastere a acestuia.
**O data calendaristica se compune din 3 elemente : zi, luna, an.
Vom putea define datele unui elev folosind doua structuri, astfel :
struct data
{ int zi, luna, an;
};
struct elev
{ char nume[20], prenume[20];
data datan;
float medie;
int clasa;
};
**Membrul datan, reprezentand data nasterii elevului, este de tip structurat si se foloseste in
interiorul altei structure. Spunem despre tipul data ca este imbricate in tipul elev.
Se pot realize mai multe nivele de imbricari. Modul de adresare in cazul structurilor imbricate,
pentru exemplul precedent :
articol.nume
articol.prenume
articol.datan.zi
articol.datan.luna
articol.data.an
articol.medie
articol.clasa

Inregistrari cu structura variabila


Limbajul C++ pune la dispozitia utilizatorilor inca un tip cu care utlizatorul poate sa-si
defineasca structura de date pe care doreste sa o foloseasca, acesta este tipul union.
union elev
{ char nume[20], prenume[20];
float medie;
int clasa;
}articol;
Dupa cu se poate observa nu este nici o diferenta in declararea structurii cu tipul
struct sau union.
**Tipul union memoreaza la un moment dat doar atatia octeti cati sunt necesari pentru
memorarea campului celui mai lung.
Daca adaugam programului afisarea operatorului sizeof(a), rezultatul afisarii va fi 20; adica
dimensiunea in octeti a celui mai lung membru.
Tipul union se foloseste in situatia in care dorim sa cream articole cu structura variabila.

Subprograme
Un program in C++ contine cel putin un subprogram, adica functia radacina main. In
cazul probremelor complexe se practica impartirea respective problem in subprobleme mai
simple.
Pentru fiecare subprobleme mai simple.
Pentru fiecare subproblema se construieste un subprogram care implementeaza doar
subproblema respective (tehnica top-down).
Definim subprogramul ca o secventa de instructiuni ce rezolva o anumita sarcina care poate fi
descrisa, separate de blocul radacina si lansata in executie din cadrul unui bloc ori de cate ori este
nevoie. Intr-o structura modular in care fiecare modul este descries printr-un subprogram,
subprogramele se clasifica astfel :
- Modul apellant : este modulul care pentru rezolvarea propriei sarcini apeleaza alte
module, fiecare dintre ele rezolvand o anumita subproblema.
- Modul apelat : este un modul apelat de un alt modul pentru a-I rezolva o subproblema.

Structura functiilor si apelul lor


O functie se compune din antet si corpul functiei.
Antetul unei functii cuprinde tipul de data returnat de functie, numele functiei si lista
parametrilor.
Corpul functiei este format din una sau mai multe instructiuni cuprinse intre {}
Forma generala :
Tip nume(param1, param2,) {instructiuni}
- Tip : reprezinta tipul de data si desemneaza tipul datei returnate de functie.
- Nume: este un identificator prin intermeriul caruia se apeleaza functia
- Parametrii : permit transmiterea argumentelor catre functie
- Instructiuni : reprezinta corpul functiei cuprins intre {}
Declararea si definirea :
A declara o functie inseamna a o anunta, adica a face cunoscut programului ca aceasta exista si
caracteristicile ei : tipul, numele si lista parametrilor.
Declararea unei functii se face cu ajutorul antetului :
tip nume (param1, param2) {instructiuni}
Definitia unei functii tine loc si de declarare daca aceasta este plasata inaintea functiei radacina
main().

Structura unui program :


Un program poate sa contina oricate functii. Pentru a fi apelata, functia trebuie sa fie cel putin
declarata. Exista doua modalitati de plasare a functiilor :
a) Inaintea functiei radacina main ()
#include <iostream.h>
int f()
{ int a=3;
return a;
}
void main()
cout<<f();
}
b) Dupa functia principal main ()
Apelul unei functii :
O functie poate fi apelata din functia radacina main(), o alta functie, sau chiar functia insasi. O
functie poate returna o valoare sau nu. Din acest punct de vedere functiile se clasifica in :
1) Functii care returneaza o valoare
Definire : tip nume (parametru 1, parametru 2, ) {instructiuni}
O functie care returneaza o valoare trebuie sa contina linia de cod : return expresie ;
Rezultatul final returnat de functie poate fi utilizat intr-o expresie sau afisat.
Variabila = nume(par1, par2, );
Afisare : cout << nume(par1, par2);
2) Functii care nu returneaza o valoare
In loc de tip vom avea void : void nume(par1, par2, ) {instructiuni}
Apelul : nume(par1, par2);
Antetul unei functii poate sa nu contina parametrii. In acest caz, atat la declarare cat si la definire
si apel, numele functiei va fi urmat de paranteze rotunde, dar fara sa contina parametrii.
Parantezele sunt obligatorii pentru a aanunta compliatorul ca este o functie si nu o variabila.
Modul de functionare al unui subprogram care contine functii :
In momentul apelarii unei functii se intampla urmatoarele :

Se aloca spatiu pe segmental de stiva pentru memorarea parametrilor functiei. Se


salveaza adresa instructiunii urmatoare apelului pentru ca la revenirea din functie
programul sa continuie cu urmatoarele instructiuni.
Se aloca spatiu pe segmental de stiva unde se memoreaza variabilele locale. Se executa in
secventa instructiunile functiei apelate. Se elibereaza segmental de stiva alocat functiei.
Se revine in punctual unde a fost apelata functia. Se continua cu instructiunile urmatoare.

Clasificarea subprogramelor
1. Din punct de vedere a celui care a creat subprogramelor :
a) Subprograme predefinite : sqrt(x), strlen(s) etc
b) Subprograme definite de utilizator
2. Din punct de vedere al modului de returnare a rezultatelor :
a) Functia operand : intoarce un singur rezultat prin insasi numele ei.
b) Functia procedural : intoarce un rezultat, mai multe, sau nici unul.
**Singurul mod in care o functie procedural poate intoarce rezultate este transmiterea
parametrilor prin referinta.
Mecanismul de apel al subprogramelor :
#include<iostream.h>
Void sb()
{.
.}
Void main()
{
Sb();
..
}
La lansarea in executie a unui program se executa mai intai instructiunile
programului principal pana la intalnirea apelului unui subprogram. In acest moment se intrerupe
executia programului principal si se cedeaza executia subprogramului.
Se executa instructiunile subprogramului, dupa care se revine in programul principal la
instructiunea imediat urmatoare celei de apel, instructiune numita si adresa de revenire. Se
continua cu urmatoarele instructiuni din main().

Functia operand

Tip_rezultat nume_functie ( lista_parametrilor_formali )


{ <zona declaratii variabile locale>
Instructiuni ;
Return expresie ;
}

Tipul rezultatului trebuie sa coincida cu tipul expresiei sau sa se poata realiza o conversie
implicita intre cele doua tipuri.
Parametrii formali sunt doar niste simboluri care la apel vor fi inlocuiti cu parametrii
efectivi. Pentru fiecare parametru se specifica tipul acestuia iar in lista parametrii vor fi
despartiti prin virgule.
Int alfa( int a, int b, float c)

Apelul unei functii operand se realizeaza intr-o expresie prin numele functiei urmat de
lista parametrilor efectivi.
Cout<<alfa (x,y,z);

**Parametrii efectivi pot avea acelasi nume ca si parametrii formali.


**Lista parametrilor efectivi trebuie sa coincide cu lista parametrilor formali ca numar, ordine si
tip.
Aplicatie : Se citesc de la tastatura l si L reprezentand latimea, lungimea unui dreptunghi. Sa se
creeze un subprogram care calculeaza aria dreptunghiului.
#include<iostream.h>
float aria(float x, float y)
{ float A;
A=x*y;
return A;
}
void main()
{ float l, L;
cout<<l=; cin>>l;
cout<<L=; cin>>L;
cout<<aria(l,L);
}

Functii procedurale
Poate sa intoarca o valoare, mai multe sau nici una. Singurul mod in care o functie
procedural poate intoarce un rezultat este prin intermediul parametrilor transmisi prin referinta.
Aplicatie : Se citeste un vector v cu n elemente numere intregi. Se cere sa se ordoneze sis a se
afiseze vectorul.
Pentru rezolvare vom folosi trei functii procedurale :
a) Pentru citire vector
b) Pentru ordonare vector
c) Pentru afisare vector
Sintaxa : void nume_functie (lista_parametrilor_formali)
{<declarare variabile locale>
Instructiuni;
}
Apelul functiei procedural se realizeaza intotdeauna, direct prin insasi numele
subprogramului, urmat de lista parametrilor, urmat de lista parametrilor efectivi.
Exemplu : afis(x,y);
Rezolvare problema :
#include<iostream.h>
int v[30], n;
void citire()
{ int I;
cout<<n=;cin>>n;
for(i=0;i<n;i++)
{ cout<<v[<<i+1<<]=;
cin>>v[i];
}
}
void sort()
{ int I,j,aux;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(v[i]>v[j])
{aux=v[i];

v[i]=v[j];
v[j]=aux;
}
}
void afis()
{ for (inst) i=0; i<n;i++)
cout<<v[i]<< ;
}
void main()
{ citire();
sort();
afis();
}

Transmiterea parametrilor
Catre subprogram parametrii pot fi transmisi :
1. Prin valoare : este situatia in care parametrii pot participa la calculele din subprogram.
Pot fi modificati in subprogram insa nu ne intereseaza aceasta modificare sa se vada si in
programul principal.
2. Prin referinta : este situatia in care ne intereseaza ca modificarile suferite de parametrii in
subprogram sa fie vazute si in programul appellant. In aceasta situatie in stiva de
memorie se salveaza adresa parametrului respectiv. Un parametru transmis prin referinta
este precedat de simbolul &.
Aplicatie : Se citesc doua valori a si b. Sa se interschimbe valorile celor doua variabile folosind
un subprogram.
#include<iostream.h>
void interschimb (int &a, int&b)
{ int aux;
aux=a;
a=b;
b=aux;
}
void main()
{ int a,b;
cout<<a=; cin>>a;
cout<<b=;cin>>b;

interschimb(a,b);
cout<<a<< <<b<<endl;
}
Aplicatie : Functia f primeste prin intermediul parametrului n un numar natural nenul iar prin
intermediul parametrului n un numar natural nenul iar prin intermediul parametrului a un
tablou unidimensional care are n elemente. Functia retunreaza -1 daca numarul de valori strict
negative din a este strict mai mare decat numarul de valori strict pozitive din tablou , valoarea 0
daca numarul de valori strict negative din a este egal cu numarul de valori strict pozitive din
tablou, si valoarea 1 daca numarul de valori strict positive din a este strict mai mare decat
numarul de valori strict negative din a. Scrieti definitia complete a functii f.
#include<iostream.h>
unsigned f(unsigned n, unsigned a[i])
{ unsigned x=0,p=0;
for(i=0;i<n;i++)
if(a[i]>0)
p++;
else
x++;
if(x==p)
return 0;
if(x>p)
return -1;
if(x<p)
return 1;
}

Liste
Se intalnesc in mai multe situatii curente:
-lista de cumparaturi
-o stiva de carti
-lista de asteptare la medic

Definim lista ca fiind o structura de date logica si liniara in care fiecare element cu exceptia
primului si ultimului are un succesor si un predecesor. Elementele unei liste se numesc noduri.
Implementarea listelor se poate realiza:

a) prin alocare secventiala statica, situatie in care nodurile listei sunt stocate intr-un bloc contiguu
de locatii de memorie cu adrese consecutive. Practic sunt implementate ca tablouri e memorie. Algoritmii
pentru operatiile de prelucrare a listelor in aceasta situatie sunt cei folositi pentru operatiile de prelucrare
a vectorilor si necesita foarte mult timp in operatiile de deplasare a elementelor in vecori(inserare,
stergere elemente.
b) prin alocare inlantuita: in aceasta situatie dispunerea elementelor in memorie poate fi
dispersata.

Alocarea inlantuita se poate realiza:


-static
-dinamic (in care nodurile vor fi pastrate in memorie cu ajutorul pointerilor).

Operatiile pe liste sunt urmatoarele:

-initializarea listei (corespunde situatiei in care lista este vida);


-crearea listei (se adauga repetat noduri in lista pornind de la situatia de lista vida);
-inserarea unui nod (se poate realiza la inceputul, in interiorul sau la sfarsitul listei);

-stergerea unui element (se poate realiza la inceputul, in interiorul sau sfarsitul listei);
-parcurgerea listei (are drept scop vizitarea nodurilor listei pentru a obtine informatia);
-cautarea unui element ce indeplineste o anumita conditie;
-concatenarea a doua liste;
-divizarea unei liste;

Lista simpla inlantuita

Este o lista la care fiecare nod va retine informatia utila sau cheia si adresa nodului
urmator: Pentru a putea gestiona lista vom folosi 2 variabile de tip adresa, variabila prim care
retine adresa primului nod din lista si ultim care retine adresa ultimului element din lista.
Vom defini nodul listei simple inlantuite astfel:
typepedef int adresa;
struct nod
{int inf;
adresa urm;
};
Lista va fi memorata intr-un vector cu elemente de tip lista:
nod lista[100];
Prima si ultima valoare sunt de tip adresa.
Deoarece in cazul alocarii inlantuite nodurile listei nu sunt memorate pe o zona contigua
de memorie vom folosi un vector liber ale carui elemente pot fi doar 0 sau 1.
adresa liber[100];
liber[i] 1 daca la adresa i exista nod memorat;
- 0 daca la adresa i nu exista nod memorat;
Crearea listei simple inlantuite
Exista 2 situatii:

a) In lista nu exista nici un nod :


-se aloca memorie pentru primul nod;
- se citeste informatia utila pentru acest nod;
- se completeaza campul de adresa a acestui nod cu val 0;
-deoarece este primul nod din lista, acesta este si ultimul;
b)

Exista cel putin un nod in lista:


- se aloca spatiu de memorie pentru acest nou nod;
- citim informatia utila in campul de informatii ;
-se completeaza campul de adresa a acestui nod cu val 0;
lista[ultim].urm=adr;
-se muta ultim pe noul nod;

-trebuie sa mutam ultimo pe noul nod


Obs: LSI poate fi create si prin adaugare in fata primului nod, caz in care la fiecare pas
va fi mutat prim.
Parcurgerea LSI
-se pleaca cu o copie de pe primul nod si cat timp nu am ajuns la sfarsitul listei:

vizualizam sau prelucram informatia din nod;

trecem pe nodul urmator;

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