Laborator 8
Tema: Pointeri si alocarea dinamica a memoriei
Definitie: un pointer este o variabila care are ca valoare o adresa de memorie.
Cum accesam adresele sau valorile de la anumite adrese? Se folosesc operatorii:
- operatorul * furnizeaza valoarea din zona de memorie a carei adresa este
continuta in variabila de tip pointer
- operatorul & atribuie unei variabile de tip pointer adresa altei variabile
Declarare: tip*nume;
nume este pointer care pointeaza spre o zona de memorie ce contine o data de
tipul tip; daca un pointer se utilizeaza cu mai multe tipuri de date se utilizeaza
formatul: void*nume;
Legatura dintre pointeri si tablouri:
- numele unui tablou este un pointer constant deoarece el are ca valoare adresa
primului sau element
Program care demonstrează afirmaţia anterioară:
#include<stdio.h>
#include<conio.h>
void main()
{ int *p,v[40],i,n;
printf("\nIntroduceti n:");
scanf("%d",&n);
printf("\nIntroduceti elementele vectorului:");
for(i=0;i<n;i++)
{printf("v[%d]=",i+1);
scanf("%d",&v[i]);}
p=v;
printf("pointerul este:%d",*p);
getch();
}
- un sir de valori poate fi prelucrata printr-un vector clasic sau pointer.
- O tablou de valori poate fi prelucrat printr-o matrice clasica sau un vector de
pointeri
Operatii cu pointeri:
1. Incrementarea si decrementarea:
tip*p;
p++; sau p--;
se mareste sau se micsoreaza adresa continuta de p cu un nr. de octeti necesari pt. a
pastra in memorie o data de tipul tip.
2. Adunarea si scaderea unui intreg dintr-un pointer
tip*p;
int n;
p+n mareste valoarea lui p cu n*t, unde t este nr. de octeti necesari pt. a memora o data de
tipul tip.
p-n micsoreaza valoarea lui p cu n*t, unde t este nr. de octeti necesari pt. a memora o data
de tipul tip.
Observatie f. importanta!
tip x[20];
x+n reprezinta adresa elementului x[n];
*(x+n) reprezinta valoarea elementului x[n];
3. Compararea a doi pointeri care pointeaza spre elementele aceluiasi tablou.
float v[20]; p pointeaza spre elem. v[i], q pointeaza spre elem. v[j].
p<q are sens si este adevarata daca i<j
p!=q are sens si este adevarata daca i j.
Obs: p= =NULL adevarata inseamna ca p nu contine nici o adresa.
4. Diferenta a doi pointeri
float v[20]; p pointeaza spre elem. v[i], q pointeaza spre elem. v[i+k].
q-p are valoarea egala cu k.
Alocarea dinamica a memoriei
Functiile care permit ac. sunt:
a. Functia malloc
- este definita in fisierul standard alloc.h care trebuie inclus in programul sursa
- permite alocarea unui bloc de memorie a carui dimensiune se specifica in octeti
- prototipul functiei: void*malloc(unsigned n);
n reprezinta nr. de octeti ai zonei care se aloca
- returneaza un pointer spre inceputul zonei alocate care trebuie sa permita
memorarea oricarui tip de data in ac. zona, deci este de tipul void* sau pointerul
NULL daca n este prea mare
b. Functia calloc
- este definita in fisierul standard stdlib.h care trebuie inclus in programul sursa
- permite alocarea unei zone de memorie
- returneaza un pointer spre inceputul zonei rezervate sau pointerul NULL in cazul
in care numarul de octeti este prea mare
- elem din zona de memorie alocata prin calloc au valoarea zero
- prototipul functiei: void*calloc(unsigned nrelemente, unsigned dimelem);
dimelem – dimens in octeti a unui elem de data
nrelem – nr elem pentru care se aloca memorie
c. Functia free
- elibereaza o zona de memorie care in prealabil a fost alocata prin malloc sau
calloc
- antet: void free(void*p); unde p este pointerul returnat de malloc sau calloc la
alocare.
1. Se considera un sir cu n numere naturale. Sa se ordoneze sirul crescator dupa ultima
cifra a elementelor sale. Folositi pointer (cu alocare dinamica a memoriei), functii de
citire, afisare si ordonare.
Ultima cifra a unui nr. natural se obtine ca rest al impartirii numarului la 10.
#include<stdio.h>
#include<conio.h>
#include<alloc.h> //sau #include<stdlib.h>
unsigned *v,n;
void citire()
{int i;
printf("\nIntroduceti nr de elemente ");
scanf("%d",&n);
v=(unsigned*)malloc(n*sizeof(unsigned));//sau v=(unsigned*)calloc(n,sizeof(unsigned));
printf("\nIntroduceti elementele\n");
for(i=0;i<n;i++)
{printf("v[%d]=",i+1);
scanf("%u",v+i);}
}
void ordonare()
{int i,cod;
unsigned aux;
do
{cod=1;
for(i=0;i<n-1;i++)
if(*(v+i)%10>*(v+i+1)%10)
{aux=*(v+i);
*(v+i)=*(v+i+1);
*(v+i+1)=aux;
cod=0;}
}
while(cod==0);
}
void afisare()
{ int i;
for(i=0;i<n;i++) printf("%4u",*(v+i));
}
void main()
{citire();
printf("\nSirul introdus este:\n ");
afisare();
ordonare();
printf("\nSirul ordonat crescator dupa ultima cifra este:\n ");
afisare();
free(v);
getch();
}
Alta varianta
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
void citire(unsigned*v,unsigned n)
{int i;
printf("\nIntroduceti elementele\n");
for(i=0;i<n;i++)
{printf("v[%d]=",i+1);
scanf("%u",v+i);}
}
void ordonare(unsigned*v,unsigned n)
{int i,cod;
unsigned aux;
do
{cod=1;
for(i=0;i<n-1;i++)
if(*(v+i)%10>*(v+i+1)%10)
{aux=*(v+i);
*(v+i)=*(v+i+1);
*(v+i+1)=aux;
cod=0;}
}
while(cod==0);
}
void afisare(unsigned*v,unsigned n)
{ int i;
for(i=0;i<n;i++) printf("%4u",*(v+i));
}
void main()
{ unsigned*x,m;
printf("\nIntroduceti nr de elemente ");
scanf("%d",&m);
x=(unsigned*)malloc(m*sizeof(unsigned));
citire(x,m);
printf("\nSirul introdus este:\n ");
afisare(x,m);
ordonare(x,m);
printf("\nSirul ordonat crescator dupa ultima cifra este:\n ");
afisare(x,m);
free(x);
getch();
}
2. Program care citeste de la tastatura elementele intregi ale unei matrici patratice de
ordinul n, afiseaza matricea, calculeaza si afiseaza suma elem. de pe diag. principala.
Folositi vector de pointeri, alocare dinamica a memoriei, functii de citire, afisare si de
calcul a sumei.
#include<stdio.h>
#include<conio.h>
#include<alloc.h>
int *a[20],n;
void citire()
{int i,j;
printf("\Introduceti n: ");
scanf("%d",&n);
for(i=0;i<n;i++)
a[i]=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{printf("a[%d][%d]=",i,j);
scanf("%d",a[i]+j);}
}
void afisare()
{ int i,j;
for(i=0;i<n;i++)
{for(j=0;j<n;j++)
printf("%d\t",*(a[i]+j));
printf("\n");}
}
long suma()
{long s=0;
int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++)if(i==j)
s=s+*(a[i]+j);
return s;
}
void main()
{int i;
citire();
printf("\nMatricea este:\n");
afisare();
printf("\nSuma elem de pe diag princ este %ld",suma());
for(i=0;i<n;i++)
free(a[i]);
getch();
}
[Link] cu functii de citire, ordonare alfabetica si afisare a unui sir de litere
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<alloc.h>
char*a;
void citire()
{a=(char*)malloc(50*sizeof(char));
printf("\nDati sirul:");
gets(a);}
void ordonare()
{int i,cod;
char aux;
do{cod=1;
for(i=0;i<strlen(a)-1;i++)
if(*(a+i)>*(a+i+1))
{aux=*(a+i);
*(a+i)=*(a+i+1);
*(a+i+1)=aux;
cod=0;}}
while(cod==0);
}
void afisare()
{printf("%s",a);
printf("\n");
}
void main()
{
citire();
afisare();
ordonare();
printf("\nSirul ordonat este\n");
afisare();
free(a);
getch();
}
Tema:
Refaceti problemele de prelucrare a elementelor unui tablou pe care le-am rezolvat
seminariile anterioare cu ajutorul pointerilor si cu alocare dinamica a memoriei. Ex:
1. Se citeste un sir de numere intregi de dimensiune n si un numar intreg b.
a) Sa se calculeze media elementelor strict pozitive.
b) Sa se determine nr. elementelor negative.
c) Sa se caute daca exista elementul 0 in vector.
d) Sa se determine numarul de aparitii a lui b in sirul dat.
2. Se consideră un şir de dimensiune n.
a) Sa se inverseze elem sirului.
b) Sa se adauge in sirul cu elem inversate, pe pozitia k<n elementul a carui valoare
este data de suma elem sirului
c) Sa se ordoneze crescator elem noului sir.
[Link] două matrici pătratice de ordinul n. Să se determine suma şi produsul celor două
matrici.
4.Să se afişeze numărul elementelor pozitive, numărul elementelor nule şi numărul
elementelor negative dintr-o matrice dată cu n linii şi m coloane.