Sei sulla pagina 1di 8

Array Dinamici

C: Strutture Nella maggior parte dei casi pratici, il numero di elementi di un array puo’
essere determinato solo durante l’esecuzione del programma.
Es: Supponiamo di voler scrivere un programma che grafica
automaticamente le coppie (X,Y) . Il primo numero che potrebbe essere
• Memory Leakage dato in input è il numero di punti.
• Arrays di Puntatori Usando gli array statici per conservare le coppie (X,Y) avremmo
• Strutture bisogno di decidere a priori un numero massimo di elementi e ciò
• Stringhe implicherebbe dei grossi limiti all’applicabilità del nostro programma.

La funzione malloc() ci consente di decidere la dimensione


dell’array durante l’esecuzione del programma (in run-time). Gli
array le cui locazioni di memoria sono allocate in run-time sono
detti pertanto dinamici.

E. Vardaci Corso di Informatica A.A. 2010-2011 1/31 E. Vardaci Corso di Informatica A.A. 2010-2011 2/31

int main()
{ Esempio (I)
int *p, dim,i;
printf(“\n Numero di elementi dell’array: ”);
scanf(“%d”, &dim);
void *MyMalloc(size_t nbytes)
p = (int *) malloc( dim * sizeof(int)); // alloca
{
if(p == NULL){ //verifica
void *p = 0;
printf ("Error: Memoria non disponibile \n");
exit(1); p = malloc(nbytes);
} if(p == NULL){ //verifica
for(i = 0;i < dim; i++){ printf("Error: Not enough memory \n");
printf(“\n Inserire il valore dell’elemento %d ”, i); exit(1);
scanf(“%d”, &p[i]); }
printf(“L’indirizzo di p[%d] e’:%x\n il suo valore e’ return p;
*p = %d\n", i, p+i, p[i]); }
} . . . . .
free(p); //libera la memoria allocata
return 0;
} E. Vardaci Corso di Informatica A.A. 2010-2011 3/31 E. Vardaci Corso di Informatica A.A. 2010-2011 4/31
Array Statici vs. Array Dinamici Esempio (II)
Dal punto di vista dell’immagazzinamento di un insieme di dati
. . . .
int main()
double a[10]; {
e’ equivalente a const int dim = 10;
int i, a[dim], *b;
double *a; b = (int *)MyMalloc(dim*sizeof(int));
printf(“\n Indirizzo di a : %x", &a);
a = (double *) malloc(10 * sizeof(double))
printf(“\n Indirizzo di a[0]: %x", &a[0]);
printf(“\n Dimensione di a : %d bytes", sizeof(a));
In entrambi i casi abbiamo definito un vettore di 10 elementi printf(“\n Indirizzo di b : %x", &b);
che possiamo individuare singolarmente tramite la notazione printf(“\n Indirizzo di b[0]: %x", &b[0]);
a[0] ecc. o b[0] ecc. printf(“\n Dimensione di b : %d bytes", sizeof(b));
Esiste però una differenza… verificabile con il free(b);//libera la memoria allocata
return 0;
seguente esempio
}
E. Vardaci Corso di Informatica A.A. 2010-2011 5/31 E. Vardaci Corso di Informatica A.A. 2010-2011 6/31

Esempio (III) Memory Leakage (I)


Se si “perde” il valore di un puntatore di una zona di memoria allocata, quella
L’output del programma precedente potrebbe essere del tipo: memoria non e’ piu’ utilizzabile dal processo e non e’ piu’ “liberabile”: rimane
quindi proprieta’ del processo fino alla sua terminazione.
Indirizzo di a : 5FB9
int main()
Indirizzo di a[0]: 5FB9 {
const int dim=10;
Dimensione di a : 40 byte
int *b;
Indirizzo di b : 9AC2 b =(int *)MyMalloc(dim*sizeof(int)); //allochiamo
printf(“\n Indirizzo di b : %x", &b);
Indirizzo di b[0]: 2C84
printf(“\n Indirizzo di b[0]: %x", &b[0]);
Dimensione di b : 4 byte b = (int *)MyMalloc(2*dim*sizeof(int)); //allochiamo ancora

L’indirizzo di a e a[0] coincidono mentre l’indirizzo di b e


printf(“\n Indirizzo di b : %x", &b);

b[0] sono diversi così come sono diverse le dimensioni di a e


printf(“\n Indirizzo di b[0]: %x", &b[0]);

b. Come mai ?
free(b);//libera la memoria allocata
return 0;
}
E. Vardaci Corso di Informatica A.A. 2010-2011 7/31 E. Vardaci Corso di Informatica A.A. 2010-2011 8/31
Memory Leakage (II) Array di Puntatori
Una matrice bidimensionale può essere rappresentata come un vettore a due indici, o
come un vettore di puntatori
int main() int main(){
{ const int dim = 3 ;
const int dim=10; int i,j;
int *b; double a[dim][dim]= { {1.,0.,0.},{0.,1.,0.},{0.,0.,1.} };
b =(int *)MyMalloc(dim*sizeof(int)); //allochiamo double *b[dim];/* a è una matrice quadrata di double
printf(“\n Indirizzo di b : %x", &b); b è un array di puntatori */ Un vettore di double
printf(“\n Indirizzo di b[0]: %x", &b[0]); per ciascun
for(i=0;i<dim;i++) { puntatore
free(b); b[i]=(double *)calloc(dim ,sizeof(double));
b = (int *)MyMalloc(2*dim*sizeof(int)); //allochiamo ancora }//ora b è una matrice quadrata inizializzata a zero
printf(“\n Indirizzo di b : %x", &b); for(i=0;i<dim;i++){
printf(“\n Indirizzo di b[0]: %x", &b[0]); for(j=0;j<dim;j++) {
free(b);//libera la memoria allocata b[i][j]=a[i][j] ; }
return 0; }
} return 0;
E. Vardaci Corso di Informatica A.A. 2010-2011 9/31 E. Vardaci
} Corso di Informatica A.A. 2010-2011 10/31

Puntatori a Puntatori Matrici come argomento di funzioni


Un array di puntatori è…un puntatore a puntatori !
int main(){
I puntatori a puntatori sono spesso l’unico mezzo pratico di passare
const int dim = 3 ;
matrici come argomenti di funzioni. Ciò accade perché il
compilatore ha bisogno che nel prototipo e nella definizione della
int i,j;
funzione venga specificata ogni dimensione di un array successiva
double a[dim][dim]= { {1.,0.,0.},{0.,1.,0.},{0.,0.,1.} };
alla prima. Ad esempio volendo costruire una funzione per calcolare
double **b; // b è un puntatore ad un puntatore ad un double
la trasposta si avrebbe:
b=(double **)calloc(dim,sizeof(double *)) Vettore di puntatori,
for(i=0;i<dim;i++) { uno per riga void trasponi3{double a[][3],double at[][3]) {

b[i]=(double *)calloc(dim ,sizeof(double)); const int dim = 3 ;

}//ora b è una matrice quadrata inizializzata a zero int i,j;


..e se volessi
for(i=0;i<dim;i++){ for(i=0;i<dim;i++){
calcolare la trasposta
for(j=0;j<dim;j++) { for(j=0;j<dim;j++) { di una matrice 4X4
b[i][j]=a[i][j] ; } at[i][j]=a[j][i]} ??
} }

return 0; }
E. Vardaci
} Corso di Informatica A.A. 2010-2011 11/31 E. Vardaci Corso di Informatica A.A. 2010-2011 12/31
Esempio Esempio II
void trasponi (double **a,double **at,int dim)
{
void trasponi4{double a[][4],double at[][4]) {
/* a e at sono matrici >*dinamiche*< allocate altrove */
const int dim = 4 ;
int i,j;
int i,j;
for(i=0;i<dim;i++){
for(i=0;i<dim;i++){
for(j=0;j<dim;j++) {
for(j=0;j<dim;j++) {
at[i][j]=a[j][i]
at[i][j]=a[j][i]}
}
}
}
}
}
…oppure, per poter calcolare la trasposta di QUALSIASI matrice…

E. Vardaci Corso di Informatica A.A. 2010-2011 13/31 E. Vardaci Corso di Informatica A.A. 2010-2011 14/31

Es: distanza tra due punti


. . . . continua
#include <stdio.h>
#include <math.h>
struct point { definizione
double x; della struttura.
printf(“\n Enter x and y of point 2: ”);
double y;
scanf(“%lf %lf”, &pt2.x, &pt2.y);
};
dist = (pt1.x - pt2.x) * (pt1.x - pt2.x);
int main()
dist = dist + (pt1.y - pt2.y) * (pt1.y - pt2.y);
{
dichiarazioni di dist = (dist > 0 ) ? sqrt(dist): 0.;
int i = -1, n;
float dist; variabili di tipo printf(“Distance = %lf”, dist);
struct point pt1, pt2; point. }

printf(“\n Enter x and y of point 1: ”);


scanf(“%lf %lf”, &pt1.x, &pt1.y);
. . .

E. Vardaci Corso di Informatica A.A. 2010-2011 15/31 E. Vardaci Corso di Informatica A.A. 2010-2011 16/31
struct: tipo di dato user-defined(I) struct: tipo di dato user-defined(II)
Oltre ai tipi di dati semplici, quali int, char,float…, in C e’
possibile creare nuovi tipi aggregando tipi di dati eterogenei Per accedere ai singoli campi della struttura si usa la
sotto un unico nome. Questo nuovo tipo di dato va sotto il nome notazione:
di struttura e si definisce con la parola chiave struct:
identificativo.var_1 = …;
struct [nome-struttura] { nome della identificativo.var_2 = …;
struttura (tag) .
tipo1 var1;
tipo2 var2; .
membri o .
.
campi della
. identificativo.var_n = …;
struttura
tipoN varN;
} [identificativo]; Da non
dimenticare
E. Vardaci Corso di Informatica A.A. 2010-2011 17/31 E. Vardaci Corso di Informatica A.A. 2010-2011 18/31

Definizione vs. Dichiarazione Array di strutture


#include<stdio.h>
struct Circle {
Nella definizione di una variabile (struttura) viene informato il float raggio;
compilatore sulla composizione della stessa. Noto il tipo di variabile float area;
(struttura) e’ possibile valutarne la sua dimensione in termini di bit. };
La dichiarazione riguarda l’ esecuzione del programma: la float CircleArea(float Radius);
dichiarazione e’ trasformata in istruzioni che allocano fisicamente la
memoria necessaria alla vita della variabile (struttura). Una zona di int main()
memoria viene quindi riservata alla variabile quando questa e’ {
dichiarata: la variabile (struttura) esiste dal momento in cui viene int i = -1, n;
dichiarata. struct Circle circle[100];
printf(“\n Enter 0 to QUIT.”);
. . . .

E. Vardaci Corso di Informatica A.A. 2010-2011 19/31 E. Vardaci Corso di Informatica A.A. 2010-2011 20/31
Puntatori & Strutture (I)
do{
i++; #include <stdio.h>
printf(“\n Radius ? “); struct point {
scanf(“%f”, &circle[i].raggio); double x;
circle[i].area = CircleArea(circle[i].raggio); double y;
} while(circle[i].raggio != 0) };
int main()
n = i;
{
for(i = 0; i < n; i++){
struct point A1, A2, *pA;
printf(“\n Radius =%f, Area = %f”, A1.x = 10.3;
circle[i].raggio, A1.y = 10.6;
circle[i].area); A2.x = 8.3;
} A2.y = 3.6;
} pA = &A1;
printf(“\n(x,y) = (%lf, %lf)”, (*pA).x,(*pA).y);
}

E. Vardaci Corso di Informatica A.A. 2010-2011 21/31 E. Vardaci Corso di Informatica A.A. 2010-2011 22/31

Puntatori & Strutture (II) Puntatori & Strutture (III)


#include <stdio.h>
#include <stdio.h>
struct point {
struct point {
double x;
double x;
double y;
double y;
};
};
int main()
int main()
{
{
struct point A1, A2, *pA;
struct point A1, A2, *pA; operatore pA = &A1;
A1.x = 10.3; “freccia” pA->x = 10.3;
A1.y = 10.6;
pA->y = 10.6;
A2.x = 8.3;
pA = &A2;
A2.y = 3.6;
pA->x = 8.3;
pA = &A1;
pA->y = 3.6;
printf(“\n(x,y) = (%lf, %lf)”, pA->x, pA->y);
printf(“\n(x,y) = (%lf, %lf)”, pA->x, pA->y);
}
}
E. Vardaci Corso di Informatica A.A. 2010-2011 23/31 E. Vardaci Corso di Informatica A.A. 2010-2011 24/31
Puntatori & Strutture (IV) Puntatori & Strutture (V)
#include <stdio.h>
int main()
struct point {
{
Annidiamo due strutture: double x;
struct rect R, *pR;
double y;
definiamo la struttura pR = &R;
};
“point” e la struttura R.pt1.x = 10.3;
struct rect {
“rect”. R.pt1.y = 10.3;
struct point pt1;
struct point pt2;
pR->pt2.x = 20.3;
int FillColor;
pR->pt2.y = 30.5;
};
main()
. . .
{
. . . . . .

E. Vardaci Corso di Informatica A.A. 2010-2011 25/31 E. Vardaci Corso di Informatica A.A. 2010-2011 26/31

Puntatori & Strutture (VI) Puntatori & Strutture (VII)


#include <stdio.h> #include <stdio.h>
struct point { struct point { int main()
double x; double x; {
Una struttura può contare double y;
double y; struct rect R, *pR;
tra i suoi campi puntatori struct point *next;
struct point *next; struct point pt1, pt2;
a qualsiasi tipo di dato. };
};
Sono perciò ammessi struct rect { struct rect { pR = &R;
anche puntatori a struct point *ListPt; struct point *ListPt; pR->ListPt = &pt1;
struttura, persino int FillColor; int FillColor; pR->ListPt->next = &pt2;
puntatori a struttura }; }; pt2.next = NULL;
identificata dal medesimo int main() int main() . . .
tag. { { }
. . . . . . . . . . . .

E. Vardaci Corso di Informatica A.A. 2010-2011 27/31 E. Vardaci Corso di Informatica A.A. 2010-2011 28/31
Stringhe Manipolazione di stringhe
In C una stringa è semplicemente un array di variabili di tipo char terminata La libreria standard del C fornisce una serie di utili funzioni per la
nella rappresentazione interna dal carattere speciale ‘\0’. manipolazione di stringhe, definite nell’header string.h
L’array contiene quindi un elemento in più rispetto al numero di caratteri.
char *strcopy(s, ct) copia ct in s, compreso
#include<stdio.h>
lo ‘\0’ e ritorna s
char *strncopy(s, ct, n) idem ma per i primi n
main(){
caratteri di ct
char *s1, s2[]=“Hello world!”, *s3;
char *strcat(s, ct) concatena ct al termine
s1=s2; /*ATTENZIONE questa istruzione copia i puntatori
di s e ritorna s
non i caratteri ! Usare invece strcopy ! */
char *strncat(s, ct, n) idem ma per i primi n
s3=”Hello again!”;
caratteri di ct
printf(“%s\n%s\n%s\n”,s1,s2,s3);
int strcmp(cs, ct) confronta cs e ct; il
*(s1+1)=‘a’;
risultato è <0 se cs<ct, 0
printf(“%s\n%s\n%s\n”,s1,s2,s3); se cs==ct, >0 se cs>ct
} size_t strlen(cs) ritorna la lunghezza di cs

E. Vardaci Corso di Informatica A.A. 2010-2011 29/31 E. Vardaci Corso di Informatica A.A. 2010-2011 30/31

Esempio
#include<stdio.h>
#include<string.h>
main(){
char *s1, s2[]=“Hello”, *s3;
s1 = “ world !”;
s3 = “ again!”;
s3 = strcat(s2,s3);
s1 = strcat(s2,s1);
printf(“%s\n%s\n”,s1,s3);
if(strcmp(s1,s3)>0)
printf(“%s precede %s\n”,s1,s3);
else
printf(“%s precede %s\n”,s3,s1);
}

E. Vardaci Corso di Informatica A.A. 2010-2011 31/31