Documente Academic
Documente Profesional
Documente Cultură
Pentru a atribui variabilei p de tip pointer valoarea adresei variabilei x se foloseşte operatorul de adresă &:
p = &x;
Aplicaţie propusă 1. Funcția f de mai jos returnează lungimea unui șir de caractere, furnizat funcției prin
argumentul de tip pointer către char: s. Scrieți un program complet în care să integrați funcția.
/* f: returneaza lungimea sirului s */
int f(char *s) {
int n;
for (n = 0; *s !=‘\0’; s++)
n++;
return n;
}
Aplicaţie propusă 2. Funcția f de mai jos returnează lungimea unui șir de caractere, furnizat funcției prin
argumentul de tip pointer către char: s. Scrieți un program complet în care să integrați funcția.
/* f: returneaza lungimea sirului s */
int f(char *s)
{
char *p = s;/* initializare cu adresa sirului*/
Aplicaţie rezolvată 1. Se citesc N numere întregi şi se memorează în şirul t1. Se construiește apoi şirul t2 cu
elementele lui t1 în ordine inversă.
#include <stdio.h>
#define N 5
/* construieste t2 */
for (i = 0; i < N; i++)
t2[i] = t1[N – 1 - i];
return 0;
}
Aplicaţie rezolvată 2. Folosind patru variante - pe bază de pointeri - pentru o funcției de afișare a elementelor
unui tablou unidimensional de numere reale, să se afișeze un tablou ale cărui elemente se citesc.
#include <stdio.h>
main()
{
float a[10];
int i, n;
Aplicaţie rezolvată 3. Folosind o funcție pentru afișarea elementelor unui tablou unidimensional (vector, șir)
de numere reale, se afișeze:
- toate elementele șirului,
- elementele șirului începând cu o anumită poziție din șir până la final și
- un număr precizat din elementele șirului începând de la o poziție precizată.
#include <stdio.h>
main()
{
float a[10];
int i, n, l;
Aplicaţie propusă 4. Folosind codul de mai jos citiţi şi afişaţi elemente unei matrici de numere reale cu N linii
şi M coloane.
/* citire matrice */
printf("Introduceti elementele matricii: \n");
for(i = 0; i < N; i++)
for(j = 0; j < M; j++){
printf("element[%d][%d] = ", i, j);
scanf("%f", &a[i][j]);
}
/* afisare matrice */
for(i = 0; i < N; i++) {
for(j = 0; j < M; j++)
printf("%8.2f", a[i][j]);
printf("\n");
}
Aplicaţie rezolvată 4. Folosind codul de mai jos să se calculeze suma elementelor de sub diagonala
principală a unei matrici pătrate cu n (n ≤ 20) linii şi coloane.
/* suma elementelor de sub diagonala principală a unei matrici pătrate */
#include <stdio.h>
main(void)
{
int a[20][20];
int suma, i, j, n;
/* afisare matrice */
for ( i = 0; i < n; i++ ) {
for ( j = 0; j < n; j++ )
printf("%5d", a[i][j]);
printf("\n");
}
Aplicaţie rezolvată 5. Scrieți un program care calculează suma și diferența a două matrici de numere reale.
#include <stdio.h>
int n, m;
int main()
{
4
float a[10][10], b[10][10], suma[10][10], diferenta[10][10];
printf("dimensiuni matrici:\n");
printf("numar linii = "); scanf("%d", &n);
printf("numar coloane = "); scanf("%d", &m);
/* Citirea matricilor */
printf("\nelemente matrice a \n\n");
citire(a);
printf("\nelementele matrice b \n\n");
citire(b);
/* Tiparirea matricilor */
printf("\nMatricea a este :\n");
tiparire(a);
printf("\nMatricea b este :\n");
tiparire(b);
return 0;
}
5
}
}
TABLOURI DE POINTERI
Putem memora în fiecare element al lui b adresa unui tablou unidimensional, nu doar a unei variabile int ca în
aplicația de mai jos:
Aplicație rezolvată 6. Scrieți un program care memorează adresele a trei vectori într-un vector de pointeri.
Afișarea celor trei vectori se face în trei moduri diferite:
/* tablou de pointeri la tablouri */
#include <stdio.h>
main()
{
int *b[10], i, j;
int x[3] = {1, 2, 3}, y[3] = {4, 5, 6}, z[3] = {7, 8, 9};
b[0] = x;
b[1] = y;
b[2] = z;
Aplicaţie rezolvată 7. Scrieți un program care folosind funcția zi(z), care returnează un pointer la un şir de
caractere ce conține numele celei de a z-a zi din săptămână, citește un număr natural între 1 și 7 și afișează ziua
corespunzătoare din săptămână. Programul să aibă prevăzută posibilitatea ca în cazul furnizării unui număr în
afara intervalului 1..7, să afișeze un mesaj: “eroare zi!”.
#include <stdio.h>
main()
{
int nr;
6
printf("introduceti numarul unei zile din saptamana(1..7): "); scanf("%d", &nr);
printf("\nziua %d din saptamana este : %s\n", nr, zi(nr) );
}
char *zi(int z)
{
static char *s[] = {"eroare zi din saptamana!", "luni", "marti", "miercuri", "joi",
"vineri", "sambata", "duminica"};
Aplicație propusă 5. Funcția luna(l) furnizată mai jos folosește un tablou de pointeri la char (char *p[])
pentru a memora lunile anului. Folosind funcția luna(l), care returnează un pointer la un şir de caractere ce
conține numele celei de a n-a luni, construiți un program care citind un număr natural între 1 și 12 afișează luna
corespunzătoare din an. Programul are prevăzută și posibilitatea ca în cazul furnizării unui număr în afara
intervalului 1..12 să afișeze un mesaj: “eroare luna!”.
char *luna(int l)
{
static char *p[] = {“eroare luna!”, “ian”, “feb”, “mar”, “apr”,
“mai”, “iun”, “iul”, “aug”, “sep”, “oct”, “nov”, “dec” };
Aplicație propusă 6. Funcția luna(l) furnizată mai jos folosește o matrice care pe fiecare linie memorează un
șir de caractere corespunzând unei luni a anului. Folosind funcția luna(l) de mai jos, care returnează un
pointer la un şir de caractere ce conține numele celei de a n-a luni, construiți un program care citind un număr
natural între 1 și 12 afișează luna corespunzătoare din an. Programul are prevăzută și posibilitatea ca în cazul
furnizării unui număr în afara intervalului 1..12 să afișeze un mesaj: “eroare luna!”.
Observație: Dacă în aplicația anterioară am folosit un vector de pointeri pentru a memora mesajul de eroare și
numele celor 12 luni (vezi figura de mai sus), de data aceasta folosim un tablou bidimensional (matrice).
Dezavantajul acestei variante în raport cu cea
anterioară care în loc de matrice folosea un vector de
pointeri este dat de pierderea spațiului de memorie,
care este același (17 octeți) chiar dacă numele oricărei
luni este redus la 3 caractere (3 octeți) (vezi figura din
dreapta).
char *luna(int l)
{
static char a[][17] = {"eroare luna!", "ian", "feb", "mar", "apr", "mai", "iun", "iul",
"aug", "sep", "oct", "nov", "dec" };
Aplicație rezolvată 8. Folosind pe rând câte una din variantele de funcție strcpy de mai jos scrieți un program
care citește un șir de caractere, îl atribuie altui șir pe care apoi îl afișează.
VARIANTA 1
#include <stdio.h>
main()
{
char s1[10], s2[10], c;
int i;
7
i = 0;
while ((c = getchar()) != '\n')
s1[i++] = c;
s1[i]='\0';
VARIANTA 2
/* strcpy: copiaza t in s; versiunea cu pointeri 1 */
void strcpy(char *s, char *t)
{
while ((*s = *t) != '\0'){
s++;
t++;
}
}
VARIANTA 3
/* strcpy: copiaza t in s; versiunea cu pointeri 2 */
void strcpy(char *s, char *t)
{
while ((*s++ = *t++) != '\0')
;
}
VARIANTA 4
/* strcpy: copiaza t in s; versiunea cu pointeri 3 */
void strcpy(char *s, char *t)
{
while (*s++ = *t++)
;
}
Aplicație rezolvată 9. Folosind pe rând câte una din variantele de funcție strcmp de mai jos scrieți un program
care citește două șiruri de caractere pe are le compară.
VARIANTA 1
#include <stdio.h>
int main()
{
char s1[10], s2[10], c;
int i;
8
printf("introduceti primul sir: ");
i = 0;
while ((c = getchar()) != '\n')
s1[i++] = c;
s1[i]='\0';
i = strcmp(s1,s2);
if ( i == 0 )
printf("\nsirurile sunt egale\n");
else if ( i < 0 )
printf("\nprimul sir \"%s\" < al 2-lea sir \"%s\"\n", s1, s2);
else
printf("\nprimul sir \"%s\" > al 2-lea sir \"%s\"\n", s1, s2);
return 0;
}
VARIANTA 2
/* strcmp: compara sirurile de caractere s si t; versiunea cu pointeri */
int strcmp (char *s, char *t)
{
for ( ; *s == *t; s++, t++)
if (*s == ‘\0’)
return 0;
return *s – *t;
}
POINTERI LA POINTERI
Un pointer la pointer este tot un pointer ce conține adresa unei alte variabile de tip pointer care, la rândul ei,
conține adresa unei variabile obișnuite.
9
Aplicație rezolvată 10. Scrieți un program care afișează - folosind pointeri la pointeri - elementele unui tablou
de șiruri de caractere memorat pe baza unui tablou de pointeri la char (char *p[]).
Observație: Pointerul p este constant, el nu poate fi incrementat (p++) pentru afișarea celor opt șiruri de
caractere, dar putem defini un pointer la pointerul p, prin char **pp = p; care poate fi incrementat.
#include <stdio.h>
int main()
{
char *p[] = {"eroare zi", "duminica", "luni", "marti", "miercuri", "joi", "vineri",
"sambata"};
char **pp = p;
int i;
printf("\n");
return 0;
}
ALOCAREA DINAMICĂ
Multe aplicaţii pot fi optimizate dacă memoria necesară stocării datelor lor este alocată dinamic în timpul
execuţiei programului. Alocarea dinamică de memorie înseamnă alocarea de zone de memorie şi eliberarea lor
în timpul execuţiei programelor. Funcţiile de gestionare a memoriei au prototipurile în fişierele alloc.h şi
stdlib.h.
Funcţia alocă în heap un bloc de dimensiune size; Funcţia eliberează un bloc alocat anterior cu malloc;
dacă operaţia reuşeşte returnează un pointer la adresa de început a blocului este transmisă ca
blocul alocat, altfel returnează NULL. argument, la apelul funcţiei.
void* calloc(size_t nmemb, size_t size); void* realloc(void *ptr, size_t size);
nmemb: numărul de elemente care trebuie alocate ptr: adresa veche a blocului
size: dimensiunea elementelor care trebuie alocate size: noua dimensiune a blocului, dacă este 0, iar
ptr indică spre un bloc de memorie existent, blocul
Funcţia alocă în heap un bloc de dimensiune
de memorie spre care indica ptr este eliberat și
nmemb*size; dacă operaţia reuşeşte returnează un
funcția întoarce pointerul NULL.
pointer la blocul alocat, altfel returnează NULL.
Blocul alocat este inițializat cu zero. Funcția redimensionează și realocă blocul de
memorie heap de la adresa indicată de ptr, bloc care
a fost alocat anterior în heap cu un apel de malloc ,
calloc sau realloc. Funcția întoarce noua adresă
de realocare a blocului în heap sau NULL.
Aplicație rezolvată 11. Scrieți un program care creează o copie alocată dinamic în heap a unui șir de caractere
alocat static. Către copia șirului va indica un pointer alocat static.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
10
int main()
{
char s1[20] = "Un sir de caractere", *s2;
strcpy(s2, s1);
printf("Copia lui alocata dinamic in HEAP = \"%s\" \n", s2);
return 0;
}
Aplicație rezolvată 12. Scrieți un program pentru alocarea dinamică în heap a unui tablou unidimensional (șir,
vector) v de n numere reale simplă precizie folosind funcția malloc.
/* alocarea dinamică a unui tablou (șir sau vector) de n numere reale */
#include <stdio.h>
#include <stdlib.h>
main(void)
{
int n, i;
float *v;
/* citire tablou */
printf("\ncitire tablou\n");
for (i = 0; i < n; i++){
printf("element[%d] = ", i + 1);
scanf("%f", &v[i]);
}
/* afisare tablou */
printf("\nafisare tablou\n");
for (i = 0; i < n; i++)
printf("%5.2f ", v[i]);
int main(){
int n, i, *a;
return 0;
}
Aplicație rezolvată 14. Scrieți un program pentru alocarea dinamică în heap a unui tablou bidimensional
(matrici).
int main ()
{
int **a, i, j, nl, nc;
return 0;
}
12
Aplicație rezolvată 15. Scrieți un program care citește un număr necunoscut de valori întregi într-un vector
extensibil alocat dinamic în heap.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n = INCREMENT, i = 0, j;
float x, *v; /* v = adresa vector
*/
return 0;
}
Argumentele de tip pointer permit unei funcții să acceseze și să modifice obiecte din funcția care a apelat-o. De
exemplu, să considerăm funcția getint care realizează conversia datelor de intrare independentă de format,
prin împărțirea unui flux de caractere în valori întregi, câte un întreg la fiecare apel. Funcția getint trebuie să
returneze valoarea pe care a găsit-o și să semnaleze de asemenea sfârșitul de fișier când nu mai există date de
intrare. Aceste valori trebuie trimise înapoi pe căi separate, deoarece indiferent ce valoare este folosită pentru
EOF, aceasta ar putea fi și valoarea unui întreg din fișierul de intrare.
O soluție este ca funcția getint să returneze indicatorul de sfârșit de fișier ca valoarea a sa, folosind în același
timp un argument de tip pointer pentru a trimite întregul rezultat după conversie înapoi în funcția apelantă.
Acesta este procedeul pe care îl folosește și funcția scanf. Următorul ciclu completează un tablou cu întregi
prin apeluri la funcția getint:
int n, array[SIZE], getint(int *);
for (n = 0; n < SIZE && getint(&array[n]) != EOF; n++)
;
Fiecare apel setează variabila array[n] la valoarea următorului întreg întâlnit în fișierul de intrare și îl
incrementează pe n. Observați că este esențială transmiterea adresei variabilei array [n] funcției getint.
Altfel nu există nici o cale ca getint să comunice întregul rezultat după conversie apelantei sale.
Funcția getint returnează EOF pentru sfârșit de fișier, zero dacă următoarea dată de intrare nu este un număr şi
o valoare pozitivă dacă data de intrare conține un număr valid.
#include <ctype.h>
int getch(void);
void ungetch(int);
13
if (!isdigit(c) && c != EOF && c != '+' && c != '-') {
ungetch(c); /* it is not a number */
return 0;
}
sign = (c == '-') ? -1 : 1;
if (c == '+' || c == '-')
c = getch();
for (*pn = 0; isdigit(c); c = getch())
*pn = 10 * *pn + (c - '0');
*pn *= sign;
if (c != EOF)
ungetch(c);
return c;
}
În interiorul funcției getint, *pn este folosit ca o variabilă de tip int obișnuită. Am folosit de asemenea
funcțiile getch şi ungetch (prezentate în Cursul 6 la Aplicația cu programul calculator care folosește stiva și
notația poloneză inversă) astfel încât acel caracter suplimentar care trebuie citit să poată fi reintrodus în fișierul
de intrare.
Aplicaţie rezolvată 16*. Scrieţi un program C care foloseşte funcţia getint pentru a citi și a afișa un șir de
valori întregi până la introducerea unor caractere care nu pot fi numere întregi.
#include<stdio.h>
#include <ctype.h>
int main()
{
#define SIZE 100
int n, array[SIZE], getint(int *), i, k;
return 0;
}
int getch(void);
void ungetch(int);
sign = (c == '-') ? -1 : 1;
if (c == '+' || c == '-')
c = getch();
*pn *= sign;
14
if (c != EOF)
ungetch(c);
return c;
}
Aplicaţie propusă 7. Folosind codul de mai jos scrieţi un program complet pentru conversia datei din zi a lunii
în zi a anului şi invers, prin intermediul celor două funcţii:
zi_a_anului – converteşte ziua şi luna în ziua din an
luna_zi – converteşte ziua din an în lună şi zi.
static char tabzi[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
REZOLVĂRI
Aplicaţie propusă 1. Funcția f returnează lungimea unui șir de caractere, furnizat funcției prin argumentul de
tip pointer către char: s. Scrieți un program complet în care să integrați funcția.
/* afiseaza lungimea unui sir dat */
#include <stdio.h>
int f(char *s);
main()
{
char s[10] ="Curs PCLP", *p;
15
printf("lungimea sirului \"%s\" = %d\n", s, f(s));
printf("lungimea sirului \"Curs PCLP\" = %d\n", f("Curs PCLP"));
p = s;
printf("lungimea sirului \"%s\" = %d\n", s, f(p));
}
Aplicaţie propusă 2. Funcția f returnează lungimea unui șir de caractere, furnizat funcției prin argumentul de
tip pointer către char: s. Scrieți un program complet în care să integrați funcția.
/* afiseaza lungimea unui sir dat */
#include <stdio.h>
int f(char *s);
main()
{
char s[10] ="Curs PCLP", *p;
main(void)
{
int x, *p;
x = 3;
p = &x;
printf("*p = %d\n", *p);/* valoarea obiectului indicat de p:valoarea lui x.Afişeaza 3 */
*p = 5; /* modifică valoarea obiectului indicat de p, adică valoarea lui x. */
printf(" x = %d", x); /* afișează 5 */
}
#define N 3
#define M 2
main(void)
16
{
float a[N][M];
int i, j;
/* citire matrice */
printf("Introduceti elementele matricii: \n");
for(i = 0; i < N; i++)
for(j = 0; j < M; j++){
printf("element[%d][%d] = ", i, j);
scanf("%f", &a[i][j]);
}
/* afisare matrice */
for(i = 0; i < N; i++) {
for(j = 0; j < M; j++)
printf("%8.2f", a[i][j]);
printf("\n");
}
}
Aplicaţie propusă 5. Folosind funcția luna(l), care returnează un pointer la un şir de caractere ce conține
numele celei de a n-a luni, construiți un program care citind un număr natural între 1 și 12 afișează luna
corespunzătoare din an. Programul are prevăzută și posibilitatea ca în cazul furnizării unui număr în afara
intervalului 1..12 să afișeze un mesaj: “eroare luna!”.
#include <stdio.h>
main()
{
int nr;
char *luna(int l)
{
static char *p[] = {"eroare luna!", "ian", "feb", "mar", "apr", "mai", "iun", "iul",
"aug", "sep", "oct", "nov", "dec"};
Aplicaţie propusă 6. Folosind funcția luna(l), construiți un program care citind un număr natural între 1 și 12
afișează luna corespunzătoare din an. Programul are prevăzută și posibilitatea ca în cazul furnizării unui număr
în afara intervalului 1..12 să afișeze un mesaj: “eroare luna!”. Dacă în aplicația anterioară am folosit un
vector de pointeri pentru a memora mesajul de eroare și numele celor 12 luni, de data aceasta folosim un tablou
bidimensional (matrice).
#include <stdio.h>
main()
{
int nr;
char *luna(int l)
{
static char a[][17] = {"eroare luna!", "ian", "feb", "mar", "apr", "mai", "iun", "iul",
"aug", "sep", "oct", "nov", "dec" };
17
return (l < 1 || l > 12) ? a[0] : a[l];
}
Aplicaţie propusă 7. Folosind codul dat scrieţi un program complet pentru conversia datei din zi a lunii în zi a
anului şi invers, prin intermediul celor două funcţii:
zi_a_anului – converteşte ziua şi luna în ziua din an
luna_zi –
converteşte ziua din
an în lună şi zi.
#include <stdio.h>
int main()
{
int an, luna, zi, a, b, *l = &a, *z = &b;
*pluna = i;
*pzi = zi_an;
}
18