Sunteți pe pagina 1din 39

Capitolul 7

Relaţia pointeri – tablouri - funcţii

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 90
Cuprins
• Pointeri şi operaţii cu pointeri
• Calificatorul const aplicat variabilelor de tip
pointer
• Pointeri şi tablouri
• Utilizarea variabilelor tablou ca parametri ai
funcţiilor
• Pointeri la funcţii
• Funcţii care returnează pointeri
• Alocarea dinamică a memoriei
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 90
Pointeri şi operaţii cu pointeri

• Tip pointer --- tip de date

• Valoare pointer = o adresă de memorie


(număr întreg pozitiv) a unei zone de
o anumită dimensiune

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 90
char * p; /*variabilă pointer ce poate memora adresa unei variabile de tip
caracter*/
char c, d; /*variabile de tip caracter*/
c = 'Q'; /*atribuire de valoare de tip caracter*/
p = &c; /*în p se memorează adresa de început a zonei de memorie
alocată variabilei c*/
adresa… conţinutul de la adresa…

d = *p ; /*în acest caz, lui d i se atribuie valoarea lui c prin intermediul


adresei memorate în p;*/
caracterul 'Q', care se află la adresa memorată de p

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 91
Adunare/scădere de constante la o valoare pointer

Exemplu: int *p, *q, i=4;


p = &i;
q = p + 1;

Rezultatul expresiei p+1 este adresa valorii de tip întreg ce se află în memorie
imediat după cea indicată de p. Deoarece p este un pointer „la int”, pentru
efectuarea calculelor compilatorul utilizează în rolul constantei 1 valoarea
1*sizeof(int).

Observaţii:
p+1 → pointer la următorul element de acelaşi tip (adresa elementului
situat în memorie imediat după cel indicat de p)
*(p+1) → întregul (valoarea lui) aflat în memorie imediat după cel de la
adresa p
p+2 → se poate aduna orice valoare constantă, nu doar valoarea 1!

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 92
Incrementarea/decrementarea valorilor pointer

int *p, a, b=7;


p=&b; /* p memorează adresa variabilei b */
a= * (++p); /* 1) se incrementează p;
2) se atribuie lui a valoarea întreagă către care arată noua
valoare a lui p */
a= * (p++); /* 1) se atribuie lui a valoarea întreagă către care arată p;
2) se incrementează p */

Observaţie: * şi ++ au aceeaşi prioritate, dar se asociază de la dreapta la stânga.


expresiile a= * (++p) şi a= * ++p sunt echivalente.
Parantezele pot fi omise.

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 92
Pointer_brev_15_16_cap7.c

#include <stdio.h>
int main()
{ int m=12, k=400, *p;
char b='t', a='V', *q;
p=&k;
q=&a;
printf("Adresa pt. q: %p\tValoarea lui q: %p\n\t\t\tValoarea de la adresa q:%c\n",&q,q,*q);
printf("---------------------------------------------------\n");
printf("Adresa pt. a: %p\tValoarea lui a: %c\n",&a,a); Desen pe tabla…
printf("Adresa pt. b: %p\tValoarea lui b: %c\n",&b,b);
printf("---------------------------------------------------\n");
printf("Adresa pt. p: %p\tValoarea lui p: %p\n\t\t\tValoarea de la adresa p:%d\n",&p,p,*p);
printf("---------------------------------------------------\n");
printf("Adresa pt. k: %p\tValoarea lui k: %d\n",&k,k);
printf("Adresa pt. m: %p\tValoarea lui m: %d\n",&m,m);
printf("---------------------------------------------------\n");
p=p+1; /*sau p++; */
q=q+1; /*sau q++; */
printf("Adresa pt. q: %p\tValoarea lui q: %p\n\t\t\tValoarea de la adresa q:%c\n",&q,q,*q);
printf("Adresa pt. p: %p\tValoarea lui p: %p\n\t\t\tValoarea de la adresa p:%d\n",&p,p,*p);
return 0;
}
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 92-1
Pointer NULL

•Are valoarea 0 (zero) - nu indică adresa nici unui obiect !!!


•Folosit în instrucţiuni iterative (vom vedea!)

char *p;
p = 0;
sau p= NULL; /*NULL este o constantă predefinită descrisă, de exemplu, in
stddef.h*/
Observaţie: indiferent de tipul variabilei pointer, valoarea atribuită în acest mod
este întotdeauna 0 (zero).

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 93
Pointer void *

•Pointer universal (către orice) – doar adresa, fără dimensiune


asociată
•Permite scrierea unor funcţii cu grad maxim de generalitate
•Poate fi particularizat prin conversie explicită de tip
Desen pe tabla…
void *p; /* pointer universal */
int *q, m=5, n; /* pointer la int, urmat de 2 variabile de tip int */
(int*)p = &m; /* (int*)p este o valoare de tip pointer la int */
n = *((int*)p); /* acum *((int*)p) este chiar valoarea de tip int a cărei adresă
a fost memorată în p */

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 93
Scăderea a doi pointeri de acelaşi tip
•Două variabile de acelaşi tip pointer - adresează obiecte de
acelaşi tip
•Rezultatul operaţiei de scădere - valoare întreagă =
numărul de obiecte situate între cele două adrese
•Prelucrări asupra variabilelor de tip tablou (vom vedea!)
•Tipul predefinit ptrdiff_t descris în fişierul stddef.h
#include <stddef.h>
ptrdiff_t d, i; /* 2 variabile ce pot memora diferenţa a 2 pointeri */
int *p1,*p2, m, n; /* 2 variabile de tip pointer „la int” şi 2 variabile de tip int */
float *p, *q, x, y; /* 2 variabile de tip pointer „la float” şi 2 variabile de tip float */
p1=&m;
p2=&n;
d=p2-p1; /*corect: p1 şi p2 sunt de acelaşi tip */
p=&x;
q=&y;
i = q – p; /*corect: p şi q sunt de acelaşi tip */
i = p2 – q; /*greşit: p2 şi q nu sunt de acelaşi tip; se va genera eroare în
faza de compilare */
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 94
Atribuirea de valori pointer

•Variabile şi valori pointer de acelaşi tip

•Oricărui tip de pointer i se poate atribui valoarea NULL sau


pointer void*;

•Pointerilor void* li se pot atribui valori pointer de orice tip

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 94
#include <stdio.h>
#include <stdlib.h> Pointeri_1.c eventual…
int main(void)
{ int *p, *q, a=1, b=2, t[3]={10,20,30};
float x=23.5, *adr;
adr=&x;
p=&a;
q=&x; /*eroare la compilare: q este pointer la int iar x este de tip float*/
p=&t[0]; /* p= 0022FF50 */
printf("Valoarea lui t[1] este: %d, identic cu %d\n", t[1], *(p+1));
q=&t[2]; /* q= 0022FF58 */
printf("Între adresele de memorie %p si %p există %d numere întregi\n", p, q,
q-p); /* pe ecran apare valoarea 2 */
q=q-2; /* q==p */
a=adr-p; /*eroare la compilare: cei 2 pointeri nu sunt de acelaşi tip*/
return 0; 0022FF48 adr
} 0022FF4C 23.5 x
0022FF50 10 t[0]
Ca urmare a lansării în execuţie a exemplului de program anterior, pe ecran apare 0022FF54 20 t[1]
următorul text: 0022FF58 30 t[2]
0022FF5C
Valoarea lui t[1] este: 20, identic cu 20 0022FF60 2 b
Între adresele de memorie 0022FF50 şi 0022FF58 există 2 numere întregi 0022FF64 1 a
0022FF68 q
0022FF6C p
Dev C++ 5 - dimensiunea în octeţi pentru câteva tipuri reprezentative este:
char=1, int=4, short int=2, long int=4, pointer=4, float=4, double=8.

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 95
Compararea valorilor pointer

Caracteristici:
 se efectuează în aceleaşi condiţii ca scăderea (valorile pointer trebuie să fie de
acelaşi tip);
 permite utilizarea tuturor celor 6 operatori de comparaţie:
< <= > >= == !=
 utilizează regula: p>q este „adevărat” (valoare 1) atunci când se poate calcula
diferenţa p-q şi valoarea rezultată este strict pozitivă (>0);
 orice valoare pointer poate fi comparată cu valoarea 0 (NULL).

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 95
Calificatorul const aplicat variabilelor de tip pointer
const int m=5;
m++; /*eroare la compilare: valoarea lui m nu poate fi modificata */

Declararea: (Permite protejarea unor informatii)


 unor constante de tip pointer
 unor variabile de tip pointer ce conţin adresa unei valori constante

const int m=5, *p=&m; /* m - constantă; p – pointer ce poate memora adresa


unei constante de tip int */
const int *const q=&m; /* q – constantă de tip pointer ce poate memora adresa
unei constante de tip int */
int a; /* a – variabilă de tip int */
int *const s=&a; /* s – constantă de tip pointer ce poate memora adresa
unei valori de tip int */
/*Exemple de utilizare corectă a elementelor declarate*/
a=m;
p++;
p=q;
*s=m;
/*Exemple de utilizare incorectă a elementelor declarate*/
m=3; /*valoarea unei constante nu poate fi modificată*/
m++; /*idem*/
*p=7; /*entitatea (*p) este chiar constanta m, care nu poate fi modificata*/
s=&a; /*modificarea unei constante de tip pointer nu este permisă*/
q++; /*idem*/
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 96
Pointeri şi tablouri unidimensionale

adr t
short t[3]; t[0]
short *adr; t[1]
adr = &t[0];
adr+2
t[2]

Particularitate:

în limbajul C, numele unui tablou, ne-urmat de indice, este interpretat ca


fiind adresa primului element al tabloului

t ≡ &t[0] => *(t+n) ≡ t[n]

Indicele
--- deplasare faţă de adresa de început
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 96
Particularitate:

în limbajul C, numele unui tablou este un pointer constant


(valoare constantă)

int a[4], *adr;


adr = a;
a[1] = *(adr+3); /* echivalent cu a[1] = a[3]; */
a = adr; /* GREŞIT - a este nume de tablou, nu poate fi modificat!!! */
adr++; /* CORECT - în adr se memorează acum &a[1] */
adr+=2; /* CORECT - echivalent cu adr=&a[3];

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 97
Utilizarea variabilelor tablou unidimensional ca
parametri ai funcţiilor
Nume tablou ≡ pointer constant --- adresa I element al tabloului
Particularitate:
Folosirea unui tablou unidimensional ca parametru al unei funcţii
se va face întotdeauna, implicit, prin referinţă (adresă) şi nu prin
valoare, indiferent de forma în care este scris parametrul formal la
definirea funcţiei.

la definirea funcţiei, se poate omite menţionarea dimensiunii


tabloului;

la apelarea funcţiei, se scrie ca parametru actual doar


numele tabloului

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 97
Exemple

Cateva variante corecte de scriere a unei


funcţii care:

calculează suma elementelor unui tablou


unidimensional cu valori de tip real

folosind ca parametri:
tabloul
si numărul său de elemente
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 98
/*scrierea „clasică” a parametrilor şi accesarea elementelor tabloului prin index
(poziţie)*/ se poate omite specificarea dimensiunii maxime; se
poate scrie şi float x[100] !!!
float suma (float x[ ], int nr)
{ int i; specifică numărul efectiv de elemente din tablou
float s = 0.0;
for(i = 0; i < nr; i++)
s += x[i];
return s;
}
/*exemplificarea modului de apelare a funcţiei*/
int main (void)
{ int i, n;
float a[100], rez;
/*...aici pot fi scrise instrucţiunile pentru citirea de la tastatură a numărului de
elemente din tablou şi a valorilor ce fac parte din acesta
...............
*/
rez = suma (a, n); /* apelarea funcţiei suma() */
numele tabloului (care este şi pointer la primul element)
*/ ...aici pot să apară alte instrucţiuni ce aparţin funcţiei main()*/
} TABL73.c

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 98
/* scrierea explicită a parametrului tablou ca pointer şi accesarea elementelor prin
pointer (adresă) */
parametru de tip pointer la element de tipul celor din tablou
float suma (float *x, int nr)
{ float *final = x + nr; /* adresa finală a tabloului în memorie*/
float s = 0.0, *p;
for(p = x; p < final; ++p)
s += *p; /* echivalent cu: s=s+ *p; */
return s; se putea scrie p<x+nr şi se renunţa la declararea şi
} utilizarea variabilei final, dar timpul de execuţie este mai
bun aşa !

/*Apelarea funcţiei se va scrie la fel ca în exemplul prezentat anterior */

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 99
Observaţie: deoarece x, de tip „pointer la float”, este un parametru trimis prin
valoare, o eventuală modificare a sa în interiorul funcţiei nu se va reflecta în
exteriorul acesteia, ceea ce permite scrierea unei variante simplificate:

float suma (float *x, int nr)


{ float *final = x + nr;
float s = 0.0; /* s-a renunţat la variabila locală float *p */
nu se scrie nimic!
for ( ; x < final; ++x)
s += *x;
return s;
}

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 99
Particularitate:

Folosirea tablourilor unidimensionale ca parametri ai


funcţiilor exclusiv prin referinţă (adresă), indiferent
de forma de scriere…

…Consecinţă…

…Orice modificare a valorilor elementelor tabloului


făcută pe durata execuţiei funcţiei se păstrează şi
după încheierea acesteia!!!

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 100
Exemplu:
Un program C care interschimbă valorile de tip întreg din două tablouri
unidimensionale citite de la tastatură, putând afişa pe ecran, de exemplu,
următorul text:
Introduceţi informaţii despre tabloul A
Tastaţi nr. de elemente: 3
Tastaţi valorile elementelor:
A[0]=1
A[1]=2
A[2]=3
Introduceţi informaţii despre tabloul B
Tastaţi nr. de elemente: 3
Tastaţi valorile elementelor:
B[0]=4
B[1]=5
B[2]=6
Valorile iniţiale sunt:
A[0]=1 A[1]=2 A[2]=3
B[0]=4 B[1]=5 B[2]=6
După interschimbare, valorile sunt:
A[0]=4 A[1]=5 A[2]=6
B[0]=1 B[1]=2 B[2]=3
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 100
TABL73M.c
/* Programul principal */ Tablou_7_3.c
#include <stdlib.h> /*pentru exit() */
#include <stdio.h>
void CiteşteTablouDeLaTastatură (int t[ ], int * nr, char nume);
void Afişează (int t[ ], int nr, char nume);
void Interschimbă (int x[ ], int y[ ],int nr);

int main (void)


{int i, na, nb, a[10], b[10];
printf("Introduceţi informaţii despre tabloul A\n");
CiteşteTablouDeLaTastatură (a, &na, 'A');
printf("Introduceţi informaţii despre tabloul B\n");
CiteşteTablouDeLaTastatură (b, &nb, 'B');
printf("\nValorile iniţiale sunt:\n");
Afişează(a, na, 'A');
Afişează(b, nb, 'B');
if (na!=nb) {printf("Număr de elemente diferit. Nu se va face interschimbarea!”);
exit(1);
}
Interschimbă(a, b, na);
printf("\nDupă interschimbare, valorile sunt:\n");
Afişează(a, na, 'A');
Afişează(b, nb, 'B');
return 0;
}

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 101
/* Functie pentru citirea de la tastatură a:
- numărului de elemente ce fac parte dintr-un tablou unidimensional cu
elemente de tip întreg;
- tuturor valorilor ce fac parte din tablou;
Valorile citite pot fi folosite, după încheierea execuţiei funcţiei, de către funcţia
apelantă.*/
void CiteşteTablouDeLaTastatură (int t[ ], int * nr, char nume)
{int i;
(int *t, int * nr, char nume)
printf("Tastaţi nr. de elemente:");
scanf("%d", nr); /* NU se scrie &nr, nu ar fi corect în acest caz! */
printf("Tastaţi valorile elementelor:\n");
for(i = 0; i < *nr; i++)
{printf("%c[%d]=", nume, i);
scanf("%d", &t[i]); scanf("%d", (t+i));
} sau scanf("%d", t++);
}

Exemplu LIVE, cu GRESEALA: Tablou_7_3_dem_greseala.c

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 101
/* Funcţie pentru afişarea pe ecran a valorilor tabloului */

void Afişează (int t[ ], int nr, char nume) void Afişează (int *t, int nr, char nume)
{int i; {int i;
for(i = 0; i < nr; i++) for(i = 0; i < nr; i++)
printf("%c[%d]=%d ", nume, i,t[i]); printf("%c[%d]=%d ", nume, i,*(t+i));
printf("\n"); printf("\n");
} }

/* Funcţie pentru interschimbarea valorilor a două tablouri unidimensionale cu


elemente de tip întreg. Cele două tablouri trebuie să aibă acelaşi număr de
elemente */
void Interschimbă (int x[], int y[],int nr) void Interschimbă (int*x, int*y, int nr)
{int i, aux; {int i, aux;
for(i = 0; i < nr; i++) for(i = 0; i < nr; i++)
{aux =x[i]; { aux = *x;
x[i]=y[i]; *x++ = *y;
y[i]=aux; *y++ =aux;
} }
} }

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 102
Pointeri către tablouri unidimensionale
Reamintire:
char *s ; /* pointer la char – poate adresa o zonă de 1 octet */
float *r; /* pointer la float – poate adresa o zonă de 4 octeţi */

Exemplu:
int a[10]; /* tablou cu 10 elemente de tip int */
int * p_int; /* pointer la int */
int (* p_tab)[10]; /* pointer la tablou cu 10 elemente de tip int */
p_int = a;
p_tab = &a; /* p_int şi p_tab sunt pointeri de tipuri diferite !!! */

int a [10]

a[0] a[1] a[2] ... a[9] ... ...

p_int p_int +1
p_tab p_tab+1

Observaţie: --- declararea variabilelor!!!


int (* q) [10]; /*pointer la tablou cu 10 elemente de tip int */
int * p [10]; /* tablou cu 10 elemente de tip pointer la int */
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 102
Pointeri şi tablouri cu mai multe dimensiuni
a
a[0][0]
a[0] a[0]
a[0][1]

a[1][0]
a[3][2] a[1]
a[1][1]
a+2
a[2][0]
a[2]
a[2][1]

*a == a[0]
=> *a[0] == a[0][0] => **a == a[0][0]
a[0] == &a[0][0]

a+1 == &a[1] (adresa elementului de tip tablou a[1])


a[0] + 1 == &a[0][1] (element al tabloului, de tip întreg, de exemplu)

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 103
Accesarea elementelor tabloului bidimensional:

a[0] == *a == &a[0][0] *a[0] == **a == a[0][0]


a[1] == *(a+1) == &a[1][0] => *a[1] == **(a+1) == a[1][0]
a[2] == *(a+2) == &a[2][0] *a[2] == **(a+2) == a[2][0]

a[i][j] Pentru un tablou definit ca:


*(*(a + i) + j) Tip a[d1][d2]
(*(a + i)) [j] forma de accesare a elementului a[i][j] poate fi
*(a[i] + j) *((Tip *)a+i*d2+j)

Pentru un tablou cu trei dimensiuni definit ca:


Tip a[d1][d2][d3]
forma de accesare a elementului a[i][j][k] poate fi
*((Tip *)a+i*d2*d3+j*d3+k)

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 103
Utilizarea variabilelor tablou multidimensional ca
parametri ai funcţiilor
Similară celei prezentate pentru tablouri unidimensionale.
DAR…
La declararea parametrului se poate omite doar specificarea
primei dimensiuni.
Se pot specifica drept parametri:
 un pointer (adresa primului element din tablou) si
 dimensiunile tabloului
!!! Ultima variantă trebuie folosită cu multă atenţie --- poate genera
dificultăţi utilizatorilor ne-experimentaţi.
Exemplu: Afişarea elementelor unui tablou bidimensional, int x[3][4]

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 104
trebuie să apară; se poate omite doar prima dimensiune
void AfisMatr (int a[ ][4], int m, int n)
{ int i, j; numărul de coloane din tablou
for( i = 0; i < m; i++)
numărul de linii din tablou
{ for( j = 0; j < n; j++)
printf(“%6d”, a[i][j]);
printf(“\n”);
}
}
/*exemplificarea modului de apelare a funcţiei*/
int main (void)
{ int i, j, l, c;
int x[3][4];
/*...aici pot fi scrise instrucţiunile pentru citirea de la tastatură a numărului de
elemente din tablou şi a valorilor ce fac parte din acesta
...............
*/
AfisMatr (x, l, c); /* apelarea funcţiei AfisMat() */
Numele tabloului, urmat de dimensiunile acestuia. Pentru
corectitudinea funcţionării programului, este important ca,
în acest caz, c să aibă valoarea 4.

*/ ...aici pot să apară alte instrucţiuni ce aparţin funcţiei main()*/


} TABL741.c

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 104
Nu poate fi omisă !!!
INCORECT: void matprint (int a[ ][ ], int m, int n)
Două posibile (…) soluţii CORECTE:
/*Prima soluţie*/
void AfisMatr (int (*a)[4], int m, int n) /*detalii live, la curs*/
{ int i, j;
for( i = 0; i < m; i++)
{ for( j = 0; j < n; j++)
printf(“%6d”, *(a[i]+j));
printf(“\n”);
}
}
TABL741_mod17.c
/*A doua soluţie*/
#include<stddef.h> /* necesar pt. folosirea tipului ptrdiff_t */
void matprint (void *a, int m, int n)
{ int *v = (int*)a;
int nr = m * n; /*numărul total de elemente din tablou*/
ptrdiff_t d; /*pentru diferenţa dintre două valori pointer*/
while((d = v – (int*)a) < nr)
printf( (d%n == n-1) ? “%6d\n” : “%6d”, * v ++ );
/*pentru afişarea sub formă de matrice*/
/*nu functioneaza corect in anumite situatii – detalii live, la curs*/
}
Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 105
Particularitate:

Folosirea tablourilor multidimensionale ca


parametri ai funcţiilor se face exclusiv prin referinţă
(adresă), indiferent de forma de scriere…

…Consecinţă…

…Orice modificare a valorilor elementelor tabloului


făcută pe durata execuţiei funcţiei se păstrează şi
după încheierea acesteia!!!

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 105
EXEMPLU

„Fie A şi B două matrice de dimensiune M linii şi N coloane, cu elemente de tip


întreg. Să se scrie câte o funcţie pentru realizarea următoarelor operaţii:
 citirea de la tastatură a valorilor unei matrice;
 afişarea pe ecran a valorilor matricei;
 determinarea valorii minime din cadrul unui tablou unidimensional cu
elemente de tip întreg, folosit ca parametru, şi transmiterea ca rezultat a
primei poziţii din tablou în care apare această valoare.
Folosind cele trei funcţii, să se scrie apoi un program C care, pentru fiecare dintre
cele M linii ale celor două matrice, să interschimbe elementele cu valoare minimă
din liniile corespondente.
Adică, de exemplu, valoarea minimă din linia 3 a matricei A să ia locul valorii
minime ce apărea în linia 3 din matricea B, şi reciproc.
Interschimbarea se face doar în poziţia primei apariţii a valorii minime.”

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 106
Câte linii au matricele? 2
Câte coloane au matricele? 3
Tastaţi valori pentru matricea A:
Dorim ca A[0][0]=3
lansarea în A[0][1]=1
A[0][2]=1
execuţie a A[1][0]=2
programului sa A[1][1]=5
produca, de A[1][2]=6
Tastaţi valori pentru matricea B:
exemplu, B[0][0]=0
afisarea acestor B[0][1]=3
B[0][2]=0
informatii pe B[1][0]=5
ecranul B[1][1]=4
sistemului de B[1][2]=-1
Iniţial, valorile celor 2 matrice sunt:
calcul: Matricea A:
311
256
Matricea B:
030
5 4 -1
După interschimbare, valorile celor 2 matrice sunt:
Matricea A:
301
-1 5 6
Matricea B:
130
542

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 106
TEST2742.c
TABL742.c – modif. …

#include <stdio.h>
/* Functie pentru citirea de la tastatură a valorilor ce fac parte dintr-un tablou
bidimensional cu elemente de tip întreg.
Valorile citite pot fi folosite, după încheierea execuţiei funcţiei, de către funcţia
apelantă.*/
void creare_matrice(int a[][10], int l, int c, char nume)
{ int i,j;
printf ("Tastati valori pentru matricea %c:\n",nume);
for(i=0;i<l;i++)
for(j=0;j<c;j++)
{printf("%c[%d][%d]=",nume,i,j);
scanf ("%d",&(a[i][j]));
}
}

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 107
/* Funcţie pentru afişarea pe ecran a valorilor tabloului */
void afisare_matrice(int a[][10] , int l, int c, char nume)
{ int i,j;
printf("Matricea %c:\n",nume);
for(i=0;i<l;i++)
{ for(j=0;j<c;j++) printf ("%d ",a[i][j]);
printf ("\n");
}
}

/* Funcţie pentru determinarea primei poziţii dintr-un tablou unidimensional cu


elemente de tip întreg în care apare valoarea minimă a acestuia*/
int poz_min(int x[], int n)
{ int min,i,poz;
min=x[0];
poz=0;
for(i=1;i<n;i++)
if (x[i]<min) { min=x[i];
poz=i;
}
return poz;
}

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 107
/* Programul principal */
int main ()
{ int i,j,p1,p2,aux,m,n,a[10][10],b[10][10];
printf("Cate linii au matricele? ");
scanf("%d",&m);
printf("Cate coloane au matricele? ");
scanf("%d",&n);
creare_matrice(a,m,n,'A');
creare_matrice(b,m,n,'B');
printf("Initial, valorile celor 2 matrice sunt:\n");
afisare_matrice(a,m,n,'A');
afisare_matrice(b,m,n,'B');
for(i=0;i<m;i++) /* interschimbarea elementelor cu valoare minimă*/
{ p1=poz_min(a[i],n);
p2=poz_min(b[i],n);
aux=a[i][p1];
a[i][p1]=b[i][p2];
b[i][p2]=aux;
}
printf("Dupa interschimbare, valorile celor 2 matrice sunt:\n");
afisare_matrice(a,m,n,'A');
afisare_matrice(b,m,n,'B');
return 0;
}

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 108
Tabl_7_nov_15.c

2 3 10 15 17
1 5 4 6 12
8 -3 -1 5 7

2 10 0
4 6 12
8 0 0

Daniela Saru - "Programarea calculatoarelor. Note de curs” – Ed. Printech, 2011 / slides rev. 2021 108-1

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