Upload
others
View
7
Download
0
Embed Size (px)
Citation preview
Programarea calculatoarelor
Universitatea “Constatin Brâncuşi” din Târgu-Jiu Facultatea de Inginerie
Departamentul de Automatică, Energie şi Mediu
Lect.dr. Adrian Runceanu
Curs 19
Pointeri
13.01.2013 Programarea calculatoarelor 2
Conţinutul cursului
1. Conceptul de pointer 2. Operatori specifici pointerilor 3. Aritmetica pointerilor 4. Probleme rezolvate 5. Probleme propuse spre rezolvare
13.01.2013 Programarea calculatoarelor 3
1. Conceptul de pointer
• Un pointer este o variabilă care are ca valoare adresa unui obiect cu care operează limbajul C/C++ (variabilă, constantă, funcţie).
• Folosirea pointerilor este determinată de două motive şi anume:
1. este singura modalitate de a efectua anumite calcule
2. folosirea pointerilor duce la generarea unui cod sursă de program mai eficient şi mai compact
13.01.2013 Programarea calculatoarelor 4
1. Conceptul de pointer
Astfel putem enumera situaţiile când limbajul C/C++ foloseşte pointerii, şi anume:
• atunci când se transmite unei funcţii o matrice
sau un şir de caractere • sau când se transmite parametri prin referinţă,
adică atunci când vrem să modificăm variabilele respective
13.01.2013 Programarea calculatoarelor 5
1. Conceptul de pointer Declararea unei variabile de tip pointer se face astfel:
Unde:
• tip reprezintă oricare dintre tipurile limbajului C/C++ şi
indică tipul variabilei a cărei adresă este memorată de
variabila pointer.
• nume_pointer reprezintă numele ales de utilizator
pentru a identifica pointerul respectiv
• operatorul ‘*’ este obligatoriu la declarare 13.01.2013 Programarea calculatoarelor 6
tip *nume_pointer;
1. Conceptul de pointer
Observaţie:
• Pot exista şi pointeri fără tip, care se declară astfel:
• Aceştia se utilizează pentru ca în program să primească valoarea oricărui tip de dată.
13.01.2013 Programarea calculatoarelor 7
Exemple: char *pc; // pointer de tip caracter int *pi; // pointer de tip întreg
float *pf; // pointer de tip real
void *nume_pointer;
1. Conceptul de pointer
Un pointer este un grup de octeti (adesea doi sau
patru) care poate contine o adresa.
Astfel daca c este un char si p un pointer care trimite
catre el, atunci am putea reprezenta situatia astfel:
13.01.2013 Programarea calculatoarelor 8
Adresa de memorie a lui c
Valoarea lui c p
c
Conţinutul cursului
1. Conceptul de pointer 2. Operatori specifici pointerilor 3. Aritmetica pointerilor 4. Probleme rezolvate 5. Probleme propuse spre rezolvare
13.01.2013 Programarea calculatoarelor 9
2. Operatori specifici pointerilor
Operatorii folosiţi pentru lucrul cu pointerii sunt operatorii unari:
1. Operatorul ‘ & ‘ ( operator de adresă ) – se aplică unei variabile furnizând adresa acelei variabile.
13.01.2013 Programarea calculatoarelor 10
2. Operatori specifici pointerilor Exemplu: Următorul program arată cum se poate folosi
operatorul de adresă pentru a afişa adresele unor variabile
de tipuri diferite. #include<iostream.h>
int main(void)
{
int indice=1;
float salariu_dolari=20000.0;
long salariu_lei=30000000L;
cout<<"\nAdresa variabilei indice este "<<&indice;
cout<<"\nAdresa variabilei salariu_dolari este "<<salariu_dolari;
cout<<"\nAdresa variabilei salariu_lei este "<<&salariu_lei;
} 13.01.2013 Programarea calculatoarelor 11
2. Operatori specifici pointerilor
13.01.2013 Programarea calculatoarelor 12
2. Operatori specifici pointerilor Iniţializarea pointerilor se poate face cu o valoare de
adresă de memorie, prin folosirea operatorului de adresă
‘&’:
Exemplu: Următorul program declară o variabilă de tip
pointer şi atribuie adresa unei variabile de tip întreg şi apoi
afişează valoarea variabilei pointer împreună cu adresa
variabilei de tip întreg.
13.01.2013 Programarea calculatoarelor 13
nume_pointer = &variabila;
2. Operatori specifici pointerilor #include<iostream.h>
int main(void)
{
int indice = 1;
int *p_indice;
p_indice = &indice;
cout<<"Valoarea lui p_indice "<<p_indice<<"\nValoarea lui indice "<<indice<<"\nAdresa lui indice este \n"<<&indice;
}
13.01.2013 Programarea calculatoarelor 14
2. Operatori specifici pointerilor
13.01.2013 Programarea calculatoarelor 15
2. Operatori specifici pointerilor 2. Operatorul ‘ * ‘ ( operator de redirectare ) - se aplică pointerilor şi furnizează obiectul referit de acel pointer.
Exemplu:
Următorul program atribuie pointerului adresa unei variabile de tip întreg, afişează adresa sa împreună cu valoarea memorată la adresa pe care o are pointerul, apoi modifică valoarea variabilei prin intermediul pointerului şi o afişează.
13.01.2013 Programarea calculatoarelor 16
2. Operatori specifici pointerilor
13.01.2013 Programarea calculatoarelor 17
Conţinutul cursului
1. Conceptul de pointer 2. Operatori specifici pointerilor 3. Aritmetica pointerilor 4. Probleme rezolvate 5. Probleme propuse spre rezolvare
13.01.2013 Programarea calculatoarelor 18
3. Aritmetica pointerilor
3.1. Pointeri si tablouri
• În limbajul C++ există o stânsă legătură între pointeri şi tablouri, astfel încât orice problemă care se poate rezolva cu tablouri, poate fi rezolvată şi cu pointeri.
• Putem spune că un pointer care reţine adresa unui tablou, reţine de fapt adresa primului element al tabloului.
13.01.2013 Programarea calculatoarelor 19
3. Aritmetica pointerilor
Exemplu:
int a[20], *p; p:
p=&a[0]; a:
a[0] a[1] … a[19]
13.01.2013 Programarea calculatoarelor 20
3. Aritmetica pointerilor Dacă p este un pointer către un element al unui tablou
oarecare, atunci p+1 este un pointer către elementul
următor al taboului, p+i se referă la elementul al i-lea,
iar p-i la elementul al i-lea înainte de p.
13.01.2013 Programarea calculatoarelor 21
p p+i p+1
a[0] a[1] a[2] … … a[19]
3. Aritmetica pointerilor Observaţie:
• În expresia p+i ne apare faptul că exemplificăm pe un tablou cu elemente de tip întreg. De unde putem concluziona că:
• Dacă p este un pointer către un obiect ( tip_obiect *p ), atunci p+i va fi un pointer către al i-lea obiect aflat după obiectul referit de p.
• Numele unei variabile de tip tablou este de fapt adresa primului element ( adică adresa elementului 0 al tabloului ).
• Deci: 13.01.2013 Programarea calculatoarelor 22
p = &a[0]; p = a;
3. Aritmetica pointerilor Dacă p şi q sunt doi pointeri către elemente ale aceluiaşi
tablou ( adică p = &a[i] şi q = &a[j] ), atunci putem efectua
următoarele operaţii:
13.01.2013 Programarea calculatoarelor 23
1) Comparaţii: p == q // adică se compară i cu j
p != q p < q p <= q p > q p >= q 2) p – q // adică numărul de elemente ale tabloului, care se
află între elementul referit de p şi elementul referit de q
3. Aritmetica pointerilor Exemplu: Următorul program afişează cu ajutorul unor tablouri de
tipuri diferite, diferenţa între doi pointeri.
13.01.2013 Programarea calculatoarelor 24
3. Aritmetica pointerilor 3.2. Echivalenţe de scriere
Deci, putem scrie:
13.01.2013 Programarea calculatoarelor 25
a[i] *(i +a) *(a+i) i[a]
p = &a[0] p = a
p + 1 &a[1]
*(p + 1) a[1]
p + i &a[i]
a + 1 &a[1]
*(a + 1) a[1]
a + i &a[i]
*(a + i) a[i]
!
3. Aritmetica pointerilor
• Din echivalenţele de mai sus, putem desprinde o regulă a compilatorului C++, şi anume:
• Orice expresie de forma a[i] este transformată imediat într-o expresie *(a+i), adică o expresie în care apare un pointer ( adică a ) şi un deplasament ( adică i ).
13.01.2013 Programarea calculatoarelor 26
3. Aritmetica pointerilor Exemplu:
Următorul program prezintă ultima regulă obţinută
mai sus şi anume a[i] i[a].
13.01.2013 Programarea calculatoarelor 27
3. Aritmetica pointerilor Observaţie:
• Succesiunea operatorilor ‘&*‘ aplicată unui pointer cu
deplasament are ca efect (evaluarea se face de la
dreapta la stanga):
– la primul pas, selectarea conţinutului (valorii) de la respectiva
adresă
– iar la al doilea pas, selectarea adresei respectivului conţinut
• Deci aplicând această succesiune de operatori de obţine
tot obiectul.
• Nu acelaşi lucru de poate spune despre succesiunea
‘*&‘.
13.01.2013 Programarea calculatoarelor 28
3. Aritmetica pointerilor Exemplu: Următorul program arată echivalenţa dintre un
tablou si un pointer care îl referă.
13.01.2013 Programarea calculatoarelor 29
3. Aritmetica pointerilor 3.3. Expresii compacte cu pointeri
• Cu ajutorul pointerilor se pot scrie expresii compacte în care pointerii apar împreună cu operatorii de incrementare ( ++ ) şi decrementare ( -- ).
• Astfel pot apărea următoarele situaţii:
13.01.2013 Programarea calculatoarelor 30
EXPRESIA OPERATIA CE SE MODIFICĂ
*p++ postincrementare pointerul
*p-- postdecrementare pointerul
*++p preincrementare pointerul
*--p predecrementare pointerul
++*p preincrementare obiectul
--*p predecrementare obiectul
(*p)++ postincrementare obiectul
(*p)-- postdecrementare obiectul
3. Aritmetica pointerilor • Expresiile din prima grupă modifică pointerul şi nu
obiectul la care se referă acesta.
• Acest tip de expresii îmbunătăţesc viteza de execuţie a unui program şi se recomandă utilizarea acestora în ciclurile repetitive.
• Expresiile din a doua grupă modifică obiectul referit, astfel încât operatorii ++ şi -- sunt aplicaţi de către compilator asupra obiectului şi nu asupra pointerului.
• Deci, nu putem utiliza în aceste expresii un pointer la o structură, uniune sau o funcţie.
13.01.2013 Programarea calculatoarelor 31
3. Aritmetica pointerilor Exemplu: Următorul program prezintă modul în care
acţionează operatorii ++ şi -- asupra expresiilor compacte
cu pointeri.
13.01.2013 Programarea calculatoarelor 32
Conţinutul cursului
1. Conceptul de pointer 2. Operatori specifici pointerilor 3. Aritmetica pointerilor 4. Probleme rezolvate 5. Probleme propuse spre rezolvare
13.01.2013 Programarea calculatoarelor 33
4. Probleme rezolvate
Transformarea unui număr dintr-o bază oarecare b în baza 10.
• Functia strtol este folosita pentru a face conversia unui număr dintr-o bază b (2<=b<=36) în baza 10.
• Numărul inițial, întrucât poate conține și litere, este reprezentat ca un șir de caractere.
• Pentru verificarea corectitudinii este setat un pointer la primul caracter din șir care a generat eroarea de conversie.
• Dacă pointerul este NULL, nu a apărut nici o eroare. 13.01.2013 Programarea calculatoarelor 34
#include<iostream.h> #include<stdlib.h> int main(void) { int baza; char numar[30], *p; long int nr; cout<<"\n Introduceti baza: "; cin>>baza; cout<<"\n Introduceti numarul in baza: "<<baza<<" = "; cin>>numar; nr=strtol(numar,&p,baza); if(p)cout<<"Eroare la caracterul "<<*p; else cout<<"Numarul este: "<<nr; } 13.01.2013 Programarea calculatoarelor 35
4. Probleme rezolvate
Să se facă un program de determinare a unei date calendaristice știind o dată de pornire și un număr de zile trecute.
Pentru a se ține cont de numărul diferit de zile ale lunilor anului, se va defini un tablou de constante și se va lua în calcul separat cazul când anul este bisect, luna februarie având 29 de zile.
13.01.2013 Programarea calculatoarelor 36
4. Probleme rezolvate #include<iostream.h>
const int t[13] ={ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
void calcul (int z, int an, int nr_zile, int *zi, int *luna, int *a)
{
for(int i=1;i<=12;i++)
if ( (i==2) && (an%4==0) )
if( nr_zile>29 ) nr_zile=nr_zile-29;
else break;
else
if( nr_zile>t[i]) nr_zile=nr_zile-t[i];
else break;
*a=an; 13.01.2013 Programarea calculatoarelor 37
4. Probleme rezolvate do{ if( (an%4==0) && (i==2) ) { z-=29-nr_zile; nr_zile=0; i++; if(zi<=0) { i--; z+=29; break; } } else{ if(i>12) { (*a)++; i++; } z-=t[i]-nr_zile; nr_zile=0; i++; if(z<=0) { i--; z+=t[i]; break; } } }while(z>0); *luna=i; *zi=z; }
13.01.2013 Programarea calculatoarelor 38
4. Probleme rezolvate
int main()
{
int nr_zile, zi, an, z, luna, a, i;
cout<<"\nIntroduceti data (an luna zi) : ";
cin>>an;
cin>>luna;
cin>>z;
for (a=0,i=2;i<luna;i++)
a+=t[i]+(an%4==0 && i==2);
13.01.2013 Programarea calculatoarelor 39
4. Probleme rezolvate
if(luna<1 || luna>12 || z>t[luna])
{
cout<<"Data gresita";
return;
}
z+=a;
cout<<"Introduceti numarul de zile trecute: "; cin>>nr_zile;
calcul(z, an, nr_zile, &zi, &luna, &a);
cout<<"Anul: "<<a<<"\tLuna:"<<luna<<"\tZiua: "<<zi;
} 13.01.2013 Programarea calculatoarelor 40
4. Probleme rezolvate
Se dau n numere reale ce reprezintă rădăcinile unui polinom.
Să se determine coeficienții acestui polinom.
Soluție:
Fie a1, a2, …, an rădăcinile reale ale polinomului P:
P = (x-a1)* (x-a2)*...* (x-an)
13.01.2013 Programarea calculatoarelor 41
4. Probleme rezolvate Fie polinomul P de forma:
P = bn*xn + bn-1*xn-1 + . . .+ b1*x + b0 Coeficienții b0, b1, . . ., bn se pot calcula fie cu ajutorul relațiilor lui Viete, fie calculând produsul tuturor termenilor ce formează descompunerea. Astfel, dacă:
Q = cm *xm +cm-1 * xm-1 + . . . + c1 *x+ c0
si R=Q*(x-am+1) unde
R = dm+1*xm+1 +dm*xm +... + d1* x + d0 vom avea relațiile: dm+1 = cm dk = ck-1 - ck * am+1, 1 <= k <= m d0 = -c0 * am+1
13.01.2013 Programarea calculatoarelor 42
4. Probleme rezolvate #include<iostream.h>
#include<stdio.h>
#include<stdlib.h>
int cit_date(float **rad)
{
int n, i;
cout<<"n = ";
cin>>n;
*rad = malloc((n+1) * sizeof(float));
for (i=1; i <=n ; i++){
cout<<"Radacina ["<<i<<"] = ";
cin>>&((*rad)[i]);
}
return n;
} 13.01.2013 Programarea calculatoarelor 43
4. Probleme rezolvate float* polinom(float *a, int n){
float *b;
int m, k;
b = malloc((n+1) * sizeof(float));
b[1]=1;
b[0]= - a[n];
for( m = 2; m <= n; m++){
b[m] = b[m-1];
for(k=m-1; k>0; k--)
b[k]=b[k-1] - b[k] * a[m];
b[0] = -b[0] * a[m];
}
return b;
} 13.01.2013 Programarea calculatoarelor 44
4. Probleme rezolvate
void afis_polinom(float *coef, int grad)
{
int i;
cout<<"P= ";
for(i=grad; i>0 ; i++)
if(coef[i] != 0) cout<<coef[i]<<" *X^"<<i<<"+";
if(coef[0] != 0 || grad == 0)
cout<<coef[0];
cout<<"\n";
} 13.01.2013 Programarea calculatoarelor 45
4. Probleme rezolvate
int main(void)
{
float *a, *b;
int n;
n = cit_date(&a);
b = polinom(a, n);
afis_polinom(b, n);
}
13.01.2013 Programarea calculatoarelor 46
Conţinutul cursului
1. Conceptul de pointer 2. Operatori specifici pointerilor 3. Aritmetica pointerilor 4. Probleme rezolvate 5. Probleme propuse spre rezolvare
13.01.2013 Programarea calculatoarelor 47
5. Probleme propuse spre rezolvare
1. Se dau şi mulţimile A = {a1, a2, . . . , am} şi B = {b1, b2, . . . , bn} memorate ca vectori.
Să se scrie câte un program care calculează:
a)
b)
c)
Cei doi vectori se consideră sortaţi crescător.
13.01.2013 Programarea calculatoarelor 48
BAC
BAC
BAC
5.Probleme propuse spre rezolvare
2. Să se determine toate numerele întregi de trei
cifre cu proprietatea că
3. Scrieţi un program de ordonare descrescătoare a unui tablou de numere unidimensional (vector) folosind ca instrument de lucru pointeri.
13.01.2013 Programarea calculatoarelor 49
abc .333 cbaabc
Structura biletelor de examen
13.01.2013 Programarea calculatoarelor 50
Structura biletelor de examen
13.01.2013 Programarea calculatoarelor 51
Subiect I - Grile cu alegere multiplă. Identificați litera care corespunde răspunsului corect. Subiect II - Algoritm în pseudocod Specializarea INGINERIE ENERGETICA: Subiect III – Enunțul unei probleme având un exemplu specificat. Specializarea INGINERIA SISTEMELOR: Subiect III – Enunțul unei probleme cu vectori sau matrici, având un exemplu specificat. Subiect IV – Enunțul unei probleme cu funcții, având un exemplu specificat.
Structura biletelor de examen
13.01.2013 Programarea calculatoarelor 52
Subiectul III – Enunțul unei probleme cu vectori sau matrici, având un exemplu specificat.
Problema 1
13.01.2013 Programarea calculatoarelor 53
Intersectia a doua multimi Sa se scrie un program care sa calculeze intersectia a doua multimi de cate n, respectiv m numere intregi memorate cu ajutorul vectorilor. Exemplu:
Date de intrare: n=5, a={1, 2, 5, 7, 12} si m=4, b={2, 4, 8, 12}
Date de iesire: k = 2 d = {2, 12}
Problema 1
13.01.2013 Programarea calculatoarelor 54
#include<iostream.h> int main(void) { int a[100], b[100], c[100], n, m, i, j, k, ok; cout<<"Dati cardinalul multimii A - n = "; cin>>n; cout<<"Dati elementele multimii A \n"; for(i = 1; i <= n; i++){ cout<<"a["<<i<<"] = "; cin>>a[i]; }
Problema 1
13.01.2013 Programarea calculatoarelor 55
cout<<"Dati cardinalul multimii B - m = "; cin>>m; cout<<"Dati elementele multimii B \n"; for(i = 1; i <= m; i++) { cout<<"b["<<i<<"] = "; cin>>b[i]; }
Problema 1
13.01.2013 Programarea calculatoarelor 56
k=0; for(j = 1; j <= m; j++) { ok = 0; // variabila care verifica daca un element apartine sau un multimii A
for(i = 1; i <=n ;i++) if(b[j] == a[i]) // daca elementul din multimea B apartine si multimii A atunci il adaugam in multimea intersectie - C
ok = 1; if(ok == 1) { k++; c[k] = b[j]; } }
Problema 1
13.01.2013 Programarea calculatoarelor 57
cout<<"\nElementele multimii intersectie sunt : \n"; for(i = 1; i <= k; i++) { cout.width(9); cout<<c[i]; } }
Problema 2
13.01.2013 Programarea calculatoarelor 58
Se dă un şir de n numere naturale. Să se afişeze pe două randuri, pe primul rand cele pare şi pe al doilea cele impare.
Exemplu:
Date de intrare: Pentru n = 10 si elementele 4 3 2 5 6 8 9 0 1 5
Date de iesire: 4 2 6 8 0 3 5 9 1 5
Problema 2
13.01.2013 Programarea calculatoarelor 59
#include<iostream.h> int main(void) { int a[100], par[100], impar[100], n, i,j,k; cout<<"Dati valoarea lui n = "; cin>>n; cout<<"Dati elementele\n"; for(i = 1; i <= n; i++){ cout<<"a["<<i<<"] = "; cin>>a[i]; }
Problema 2
13.01.2013 Programarea calculatoarelor 60
j=k=0; for(i = 1; i <=n; i++) if(a[i]%2==0) { j++; par[j]=a[i]; } else { k++; impar[k]=a[i]; }
Problema 2
13.01.2013 Programarea calculatoarelor 61
cout<<"\nElementele pare sunt : "; for(i = 1; i <= j; i++) { cout.width(9); cout<<par[i]; } cout<<"\nElementele impare sunt : "; for(i = 1; i <= k; i++) { cout.width(9); cout<<impar[i]; } }
Problema 2
13.01.2013 Programarea calculatoarelor 62
Întrebări?
13.01.2013 Programarea calculatoarelor 63