Lezione XIX                         frames   noframes

 

Il tipo di dato Struttura

 

 

Le strutture del linguaggio C, (equivalenti al tipo record del Pascal, sono un tipo di dato derivato, ossia sono costruite utilizzando oggetti di altri tipi), sono collezioni di variabili a cui si fa riferimento con un unico nome.

Le variabili che costituiscono la struttura sono dette elementi della struttura. In generale gli elementi di una struttura sono legati da una relazione di tipo logico.

 

Consideriamo la seguente definizione di struttura:

 

struct  indirizzario {

                               char  nome[35];

                               char  indirizzo[61];

                               };

 

La parola chiave  struct  introduce la definizione di struttura, mentre l’identificatore indirizzario e’ la etichetta della struttura (structure tag) e rappresenta assieme alla parola chiave struct il nuovo tipo di dati che e’ stato creato: struct indirizzario

Notare che ogni definizione di struttura deve terminare con un punto e virgola.

Con la dichiarazione, su illustrata non viene creata una variabile ma, si descrive solamente un tipo di dato; se volessimo creare una variabile di nome indiriz di tipo indirizzario ci vuole una istruzione come la seguente:

struct  indirizzario indiriz;

 

E’ possibile dichiarare la/le variabile/i di tipo struttura direttamente nella definizione come mostrato di seguito:

 

struct  indirizzario {

                               char  nome[35];

                               char  indirizzo[61];

                               } indiriz, indiriz2, indiriz3 ;

 

In questo esempio abbiamo dichiarato tre variabili di tipo 
struct indirizzario, dove indirizzario e’ una struttura formata da due elementi (membri o campi) nome ed indirizzo che sono degli array di caratteri (stringhe).

 

Il formato generale della definizione di una struttura e’ il seguente:

 

struct  nome_tipo_struttura {

                                       tipo  nome_variabile_1;

                                       tipo  nome_variabile_2;

                                              

                                       tipo  nome_variabile_n;

                                       } variabili_struttura ;

 

 

In tale definizione si puo’ omettere sia nome_tipo_struttura  che  variabili_struttura ma non tutti e due.

Osservazione : con nome_variabile_i indichiamo il membro i-esimo della struttura ;

 

Nota:  in questa definizione di struttura non avviene che il compilatore riservi dello spazio di memoria per allocare i campi della struttura stessa, ma viene definita la forma della struttura ossia il suo modello.

 

Solitamente le dichiarazioni di modelli di struttura li posizioniamo all’inizio del codice sorgente; dopo aver definito l’identificatore (tag) ed il modello della struttura, si possono dichiarare ed utilizzare oggetti di tale tipo come vere e proprie variabili struct.

 

Per accedere ai singoli elementi (campi) della struttura si utilizza l’operatore punto ‘ . ’ ;

 

Esempio:

 

#include<stdio.h>

#include<string.h>

 

struct  indirizzario {

                               char  nome[35];

                               char  via[45];

                               char  citta[31] ;

                               char  cap[6] ;

                               char  gender ;

                               } ;

 

main ( )

{

 struct  indirizzario indiriz;

 

 strcpy (indiriz.cap, “00195”);

 strcpy (indiriz.nome, “mimmo”);

 indiriz.gender = ‘m’;

}

 

Al campo cap viene assegnata la stringa 00195 mentre al campo nome si assegna la stringa mimmo.

Al campo gender si assegna il carattere m.

 

 

Si puo’ usare anche  typedef   per definire un tipo di struttura, in modo da evitare l’uso delle structure tag:

 

esempio

typedef  struct {

                    float  reale;

                    float  immaginario;

                        } Complesso;

 

creera’ il tipo di struttura Complesso, senza la necessita’ di un’istruzione typedef separata.

 

Volendo dichiarare delle variabili di tipo Complesso scriveremo:

Complesso x1,x2, array_x[31]; /*def. di variabili Complesso*/

 

 

 

 

E’ permessa la nidificazione di strutture:

 

 

 

struct veicolo{

                       char nome[31];

                       struct {

                                  int  giorno;

                                  int  mese;

                                  int  anno;   

                                 } data_immatricolazione;

                    Complesso numero_codice;

                      };

 

Puntatori a strutture

 

Definendo una variabile di tipo struttura, si riserva una quantita’ di memoria bastante a contenere i campi della struttura (tale memoria ha dimensione pari a sizeof(struct nome_struttura)); tale allocazione avviene in modo statico.

Definendo un puntatore ad una struttura, si avra’ un puntatore capace di puntare ad oggetti del tipo della struttura; la memoria per tali oggetti dovra’ essere allocata esplicitamente dal programmatore, mediante le funzioni per l’allocazione dinamica.

 

Esempio

 

typedef struct {

                  char  nome[38];

                  char  indiriz[51];

                  char  telefon[20];

                 }Ind;

 

Un puntatore ad una struttura viene dichiarato ponendo un asterisco prima del nome di una variabile struttura  -  esempio : definiamo un puntatore ad Ind chiamato punt_ind:

 

 

Ind *punt_ind;

 

avendo  struct  data{

                     int  giorno;

                     int  mese;

                     int  anno;

                               } ;

 

con la seguente istruzione allocheremo un oggetto di tipo Ind:

punt_ind = malloc(sizeof(Ind))

 

definiamo adesso un puntatore di tipo data avente nome punt_data:

struct  data *punt_data;

 

con la seguente istruzione allocheremo un oggetto di tipo struct data:

punt_data = malloc (sizeof(struct data));

 

a questo punto tenendo presente le istruzioni precedenti, possiamo accedere ai campi delle strutture, ( per manipolare tali campi) su definite, in questo modo:

strcpy((*punt_ind.nome), “fabiano”); oppure in modo piu’ consueto e piu’ semplice nel seguente modo:

strcpy(punt_ind->nome, “fabiano”)

e

(*punt_data.mese) = 12;  oppure

punt_data->mese = 12;

 

 

Passaggio di strutture alle funzioni

 

Le strutture possono essere passate alle funzioni, fornendo i singoli membri, la struttura intera oppure un puntatore alla struttura.

Il passaggio delle struct alle funzioni avviene sempre per valore, ossia la struct passata

alla funzione viene copiata in un’altra struct locale alla funzione ed eventuali modifiche alla struttura, eseguite all’interno della funzione, non si riflettono sulla struttura usata al momento della chiamata.

Tale copia viene persa al momento in cui si esce dalla funzione.

Puo’ essere anche simulato il passaggio per indirizzo, con l’uso dei puntatori.

 

Quando un argomento di una funzione e’ una struttura, deve essere che il tipo del parametro attuale e quello del parametro formale coincidano; consideriamo allo scopo il seguente programma dove viene dichiarata una struttura globale, di cui poi vengono attivate le variabili  e gli argomenti necessari:

 

#include<stdio.h>

 

/*definizione del tipo struttura*/

struct  tipo_strutt{ int a; int b; char car;};

 

main (void)

{

 char blocca;

struct  tipo_strutt  par_attuale;

par_attuale.a = 150;

funz1(par_attuale);

 

scanf(“%c”,&blocca);

}

 

funz1( struct  tipo_strutt par_formale)

{

printf ("%d",par_formale.a);

}

 

Questo programma stampa sul video il numero 150.

Con questo programma e’ assicurato che il tipo dei parametri formali e attuali, usati al momento della chiamata coincidano effettivamente.

 

 

Array di strutture

 

Un array di strutture e’ un tipo di dato, in cui ogni elemento dell’array e’ una struttura.

Per creare un array di strutture si deve definire prima la struttura e poi dichiarare un array di variabili di quel tipo.

 

Esempio

 

Se volessimo creare 100 strutture in cui ogni struttura rappresenta una scheda di un utente telefonico, scriveremo una struttura come la seguente:

 

struct tab1
{

char nome[38];
char codice[5];
char telefon[20];
char fax[20];
char cap[6];
char citta[20];
char indiriz[45];
char note[51];
} utente[100];

 

l’array utente contiene 100 strutture di tipo tab1.

 

Per accedere all’elemento 12 dell’array e stamparvi la citta’ scriveremo: printf(“%s”,utente[11].citta);

il campo codice della struttura tab1 serve per discriminare due utenti aventi lo stesso valore del campo nome, in modo da rendere univoca la eventuale ricerca dell’utente desiderato.

 

Esempio 

 

Consideriamo come esempio di utilizzo degli array di strutture;  un programma, che gestisce i voli di un aeroporto; il programma assolve a 6 compiti :  

1) stampa l'elenco dei voli 

2) stampa un volo dall'elenco

3) aggiunge un nuovo volo all'elenco

4) sopprime un volo

5) aggiorna il numero di posti

6) aggiorna l'orario di partenza. 

Ognuno di tali compiti viene assolto da una funzione.

L'elenco viene memorizzato su un file in memoria secondaria.

 

/*programma per la gestione dei voli*/

 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define NMAX_VOLI 14
#define NCOD 6
#define NDEST 25
#define file_dati_voli "dativoli12.dat"

typedef char Tipo_codice_volo[NCOD];
typedef char Tipo_destinazione[NDEST];
typedef struct { int ora;
int minuti;
}Nuovo_or;

typedef struct {Tipo_codice_volo codice;
Nuovo_or orario;
int posti_liberi;
Tipo_destinazione dest;
}Rec_volo;

typedef struct {Rec_volo elenco_voli;
}Tabel[NMAX_VOLI];


/*prototipi delle funzioni che useremo*/
void carica_tabella(FILE *f,Tabel tab);
void salva_tabella(FILE *f,Tabel tab);
int indice(Tipo_codice_volo,Tabel tab );
void aggiungi_volo(FILE *f,Tabel tab );
void elimina_volo(FILE *f,Tipo_codice_volo,Tabel tab );
void stampa_tabella(FILE *f,Tabel tab);
void stampa_volo(FILE *f, Tipo_codice_volo, Tabel tab);
void aggiorna_posti(FILE *f, Tipo_codice_volo , int,Tabel tab );
void aggiorna_orario(FILE *f,Tipo_codice_volo , Nuovo_or,Tabel tab);
int menu(int); void iniz(Tabel tab);
void conferma_salvataggio();

int main(void)
{
FILE *fp;
Tabel tab ;
char car;
int k,i;
char ch;
char scelta;
Nuovo_or nuovo_orario;
Tipo_codice_volo volo;
Rec_volo nuovo_volo;
while(1)
{
scelta=menu(0);
{
switch(scelta)
{
case 'S': {stampa_tabella(fp,tab);break; }
case 'V':{carica_tabella(fp,tab);printf("\nstampa del volo: inserite il codice del volo : ");
scanf("\n%s",volo);
stampa_volo(fp,volo,tab);break;}

case 'A': {aggiungi_volo(fp,tab);break;}
case 'E': {printf("\neliminazione del volo: inserite il codice del volo: ");
scanf("\n%s",volo);
elimina_volo(fp,volo,tab);
break;}

case 'L': {carica_tabella(fp,tab);break; }
case 'P': { printf("aggiorna numero posti prenotati: inserite codice del volo : ");
scanf("\n%s",volo);
i=indice(volo,tab);
if(i!=-1)
{
printf("\ni posti liberi nel volo di codice %s : %d \n",volo, tab[i].elenco_voli.posti_liberi);
printf("\nnumero di posti prenotati (negativo se si liberano) ");
scanf("\n%d",&k);
aggiorna_posti(fp,volo,k,tab);
}
break;}

case 'O': {printf("\naggiornamento orario di partenza: inserite codice del volo: ");
scanf("%s",volo);
i=indice(volo,tab);
if(i!=-1)
{
printf("\nnuovo orario: ");
scanf("\n%d%c%d",&nuovo_orario.ora,&ch,&nuovo_orario.minuti);
aggiorna_orario(fp,volo,nuovo_orario,tab);
}
break; }
case 'U': exit(0);
}
}
}
scanf("\n%c", &car);
return (0);
}

int menu(int s)
{
printf("\n************************************************");
printf("\noperazioni possibili :\n");
printf("\nS : stampa l'elenco dei voli");
printf("\nV : stampa un volo dall'elenco");
printf("\nA : aggiunge un nuovo volo all/'elenco");
printf("\nE : sopprime un volo");
printf("\nP : aggiorna il numero di posti");
printf("\nO : aggiorna l'orario di partenza");
printf("\nU : uscita dal programma");
printf("\n\nimmettere operazione da compiere: ");
s=toupper(getchar());
while((s!='S')&&(s!='V')&&(s!='A')&&(s!='E')&&(s!='P')

&&(s!='O')&&(s!='R')&&(s!='F')&&(s!='U'))
s=toupper(getchar());
printf("\n%c\n",s);
return(s);
}


void iniz(Tabel tab)
/*inizializzazione*/
{
register int t,i;
for(t=0;t<NMAX_VOLI;t++) strcpy(tab[t].elenco_voli.codice,"");
for(t=0;t<NMAX_VOLI;t++) tab[t].elenco_voli.orario.ora='\0';
for(t=0;t<NMAX_VOLI;t++) tab[t].elenco_voli.orario.minuti='\0';
for(t=0;t<NMAX_VOLI;t++) tab[t].elenco_voli.posti_liberi='\0';
for(t=0;t<NMAX_VOLI;t++) strcpy(tab[t].elenco_voli.dest,"");

}

/*funzione di caricamento file da memoria secondaria*/


void carica_tabella(FILE *f,Tabel tab)
{
int i;
iniz(tab);
if((f=fopen(file_dati_voli,"rb"))==NULL)
{fprintf(stderr,"\nImpossibile aprire il file");
return;
}
for(i=0;i<NMAX_VOLI;i++)
{
if(fread(&tab[i],sizeof(Rec_volo),1,f)!=1);
{
if(feof(f))
{ fclose(f);
fprintf(stderr,"Errore di lettura del file\n");
break;
}
}
}
fclose(f);
}


void salva_tabella(FILE *f,Tabel tab)
{
/*FILE *f;*/

int h;
if((f=fopen(file_dati_voli,"wb"))=='\0')
{
fprintf(stderr,"impossibile aprire il file\n");
return;
}
else
for(h=0;h<NMAX_VOLI;h++)
if(fwrite(&tab[h],sizeof(Rec_volo),1,f)!=1)
fprintf(stderr,"errore di scrittura\n");
fclose(f);
}

/*funzione di ricerca*/
int indice(Tipo_codice_volo volo,Tabel tab)
{
/*restituisce l'indice della tabella che ha codice uguale a volo; se
l'elemento non e' presente nella tabella la funzione restituisce -1*/
int h=NMAX_VOLI-1;
/*indice per la scansione della tabella*/
int trovato=0;

while((h>=0)&&(!trovato))
{
if(!strcmp(tab[h].elenco_voli.codice,volo))
trovato=1;
/*volo e'stato trovato*/
else h=h-1;
/*preparazione alla ricerca del prossimo elemento*/
}

/*N.B. se volo non e' stato trovato, allora h=-1, altrimenti h contiene l'indice dell'elemento dell'array tab[h].elenco_voli, in cui c'e' volo*/
if(h==-1){printf("\nvolo non trovato\n");}
return(h);
/*trasmissione del risultato all'unita' chiamante*/
}

/*aggiunge un volo nella tabella: */

void aggiungi_volo(FILE *f,Tabel tab)
{
char space;
char buffer[NDEST];
int p,i;
char cod[NCOD];
char dati;
iniz(tab);
carica_tabella(f,tab);
for(i=0;i<NMAX_VOLI;i++)
{
if(!strcmp(tab[i].elenco_voli.codice,""))
break;
}
if(i>=NMAX_VOLI)
{printf("\nTabella piena\n"); return;}
else
{
p=i;
printf("\naggiunta volo ...%d ",p+1 );
printf("\ninserite il codice volo: ");
scanf("%s",tab[p].elenco_voli.codice);
printf("Orario di partenza (ore minuti es. 20 15) :");
scanf("%d%c%d",&tab[p].elenco_voli.orario.ora,&space,&tab[p].elenco_voli.orario.minuti);
printf("\ninserite il n. di posti liberi: ");
scanf("%d",&tab[p].elenco_voli.posti_liberi);
printf("\ndestinazione: ");
scanf("%s",tab[p].elenco_voli.dest);
printf("\nI dati inseriti sono corretti (s/n)\n");
scanf("\n%c",&dati);
dati=toupper(dati);
if(dati=='S')
salva_tabella(f,tab);
}
}
/*fine aggiungi_volo*/



void elimina_volo(FILE *f,Tipo_codice_volo volo,Tabel tab)
{
int i,k;
char car;
/*usato per il controllo dell'eliminazione vale s od n*/
iniz(tab);
carica_tabella(f,tab);
i=indice(volo,tab);
if(i==-1)
{printf("\ncodice volo non in elenco\n");
return;}
else
{
printf("\nstai eliminando il volo di codice %s s/n ", volo);
scanf("\n%c",&car);
car=toupper(car);
}
if(car=='S')
{
printf("\n%c\n",car);
strcpy(tab[i].elenco_voli.codice,"");
tab[i].elenco_voli.orario.ora='\0';
tab[i].elenco_voli.orario.minuti='\0';
tab[i].elenco_voli.posti_liberi='\0';
strcpy(tab[i].elenco_voli.dest,"");
salva_tabella(f,tab);
}
}
/*fine funzione elimina_volo*/

void stampa_tabella(FILE *f,Tabel tab)
{
int h;
int cont_voli=0;
char car;
iniz(tab);
carica_tabella(f,tab);
printf("\nstampa dati sui voli");
printf("\n..................................................\n");
for(h=0; h<NMAX_VOLI;h++)
{
if(strcmp(tab[h].elenco_voli.codice,""))
{
printf("\nCodice volo: %s",tab[h].elenco_voli.codice);
printf(" Orario di partenza: %2d %2d ",tab[h].elenco_voli.orario.ora,tab[h].elenco_voli.orario.minuti);
printf("\nPosti liberi: %3d",tab[h].elenco_voli.posti_liberi);
printf(" Destinazione: %s ",tab[h].elenco_voli.dest);
cont_voli++;
if((cont_voli%5)==0)
{
printf("\nPremere un carattere per la videata successiva\n");
scanf("\n%c",&car);
}

}
/*end if*/
}
}
/*fine stampa_tabella*/

/*cerca il volo di codice cod e lo stampa su video*/

void stampa_volo(FILE *f,Tipo_codice_volo cod,Tabel tab)
{
int i;
iniz(tab);
/*caricamento della tabella da disco */
carica_tabella(f,tab);
i=indice(cod,tab);
if(i==-1)
/* se il volo non e' nella tabella*/
{printf("\n%s",cod," :Codice volo non trovato");return;}
else
{
printf("\n__________________________________________________\n");
printf("\nCodice volo: %s",tab[i].elenco_voli.codice);
printf(" Orario di partenza: %2d % 2d",tab[i].elenco_voli.orario.ora, tab[i].elenco_voli.orario.minuti);
printf("\nPosti liberi: %3d",tab[i].elenco_voli.posti_liberi);
printf(" Destinazione: %s ",tab[i].elenco_voli.dest);
printf("\n__________________________________________________\n");
}

}
/*fine stampa_volo*/


void aggiorna_posti(FILE *f, Tipo_codice_volo volo, int k,Tabel tab)
{
int i;
char car;
carica_tabella(f,tab);
i=indice(volo,tab);
if(i==-1)
{
printf("\n%s ", volo,": codice volo non trovato");
return;}
else
{
if(tab[i].elenco_voli.posti_liberi<k)
{
printf("\nposti insufficienti sul volo %s", volo);
return;
}
else
{
printf("\nposti liberi nel volo di codice %s sono %d \n",volo, tab[i].elenco_voli.posti_liberi);
tab[i].elenco_voli.posti_liberi= tab[i].elenco_voli.posti_liberi - k;

}

printf("\nsalviamo le modifiche apportate? (s/n)\n");
scanf("\n%c",&car);
car=toupper(car);
if(car=='S')
salva_tabella(f,tab);
}

}
/*fine aggiorna_posti*/

void aggiorna_orario(FILE *f, Tipo_codice_volo volo,Nuovo_or nuovo_orario,Tabel tab)
{
int i;
char car;
carica_tabella(f,tab);
i=indice(volo,tab);
if(i==-1)
{printf("\n%s ", volo," : codice volo non trovato"); return;}
else
{
{
printf("\nIl vecchio orario di partenza era: %2d % 2d",tab[i].elenco_voli.orario.ora, tab[i].elenco_voli.orario.minuti);
tab[i].elenco_voli.orario=nuovo_orario;
}
printf("\nsalviamo le modifiche d'orario al vodo di codice %s (s/n) ",volo);
scanf("\n%c",&car);
car=toupper(car);
if(car=='S')
salva_tabella(f,tab);
}
}
/*fine aggiorna_orario*/



programma gestione voli in formato zip: g_voli.zip
 

Funzioni che ritornano strutture

 

Riprendiamo la definizione su esposta:

 

typedef  struct {

                    float  reale;

                    float  immaginario;

                        } Complesso;

 

 

e definiamo la seguente funzione, la quale prende il puntatore ad una struttura, vi pone nei campi i dati letti da input e la restituisce:

 

Leggi_complesso(Complesso *punt)

{

 printf(“\n inserite un numero complesso (Re+j*Im): ”);

 scanf(“%lf + j *%lf”,&punt->reale,&punt->immaginario);

 printf(“\n ho letto %lf +%lf j”, punt->reale, punt->immaginario);

 

 return(*punt); /* restituzione della struttura puntata da punt */

}

 

nel main avremo una cosa cosi fatta:

 

main()

{

 Complesso x, y, x1,y1;

 x1 = Leggi_complesso(&x) ;

 y1 = Leggi_complesso(&y);

 

 printf(“\n fine\n”);

}

 

La chiamata della funzione Leggi_complesso(&x) restituisce la struttura x opportunamente “riempita”; la struttura  viene assegnata ad x1 con una copiatura membro a membro.

 

Osservazione

 

Esistono funzioni che ritornano puntatori a strutture; un esempio lo potremmo realizzare considerando una funzione che prende due numeri complessi x e y, ne effettua la somma e pone quest’ultima in una nuova struttura, allocata dinamicamente, della quale restituisce il puntatore.

Il prototipo di una tale funzione potrebbe essere:

 

Complesso * somma (Complesso x, Complesso y)

 

Dove Complesso e’ la struttura definita sopra.

 

Esercizio 1

 

Consideriamo un programma che gestisce un array di 2 strutture bottiglia_vino, dove ogni bottiglia_vino contiene due campi: il campo produttore, il campo quantita che indicano rispettivamente il nome del produttore del vino e la quantita’ di bottiglie vendute.

 

#include<stdio.h>

#include<string.h>

 

struct  bottiglia_vino{

             char  produttore[31];

             int     quantita;

           }bottiglie[2];

 

 

 

main ( )

{

 struct  bottiglia_vino * punt_vino;

 /* punt_vino e’ il puntatore che utilizzeremo per la scansione*/

 strcpy (bottiglie[0].produttore, “Brunello”);

 strcpy (bottiglie[1].produttore, “Barbera”);

 bottiglie[0].quantita = 10000;

 bottiglie[1].quantita = 15000;

 

for (punt_vino=bottiglie; punt_vino < bottiglie + 2; punt_vino++)

printf(“Produttore : %s, Quantita’ : %d; \n”, punt_vino->produttore, punt_vino->quantita);

printf (“\n fine\n”);

 

}

 

notiamo che il membro produttore della struttura  e’ una stringa allocata staticamente e che la scansione viene effettuata attraverso il puntatore punt_vino.

 

Esercizio 2

 

In questo esercizio consideriamo l’esercizio 1 nel caso che il blocco di memoria che contiene le strutture venga allocato dinamicamente, con una fase di input output dei dati.

 

#include<stdio.h>

#include<string.h>

#include<stdlib.h> /* contiene la funzione malloc*/

struct bottiglia_vino{

     char produttore[31];

     int quantita;

     }bottiglie[2];

 

/*prototipi delle funzioni che useremo*/

struct bottiglia_vino *alloca(int *);

void leggi(int, struct bottiglia_vino *);

void stampa(int, struct bottiglia_vino *);

main()

{

struct bottiglia_vino *punt_vino;

int numero_elementi;

/*inizializzazione*/

 

punt_vino=alloca(&numero_elementi);

if(punt_vino==NULL) exit(1);

leggi(numero_elementi, punt_vino);

/*fine inizializzazione*/

 

stampa(numero_elementi,punt_vino);

printf("\n\n Fine\n");

 

 

}

/*definizioni delle funzioni*/

struct bottiglia_vino *alloca(int *numero)

/*la funzione, alloca elementi consecutivi pari a numero che sono di tipo struct bottiglia_vino e restituisce il puntatore all’inizio di tale blocco di memoria*/

 

{

struct bottiglia_vino *punt;

printf("\n quanti elementi ?...");

scanf("%d",numero);

punt=malloc(*numero * sizeof(struct bottiglia_vino));

if(punt==NULL)

 {

 printf("errore di allocazione");

 return NULL;

 }

 return ;

}

 

void leggi(int numero, struct bottiglia_vino *punt_vino)

/*legge ‘numero’ dati di tipo struct bottiglia_vino ponendoli sequenzialmente nel blocco puntato da punt_vino*/

 

{

struct bottiglia_vino *p;

 for(p=punt_vino; p<punt_vino+numero;p++)

 {

 printf("\nProduttore e Quantita' %d:\n",(int)(p-punt_vino));

 scanf("%s",&p->produttore);

 scanf("%d",&p->quantita);

 }

}

 

void stampa(int numero, struct bottiglia_vino *punt_vino)

/* stampa ‘numero’ di dati di tipo struct bottiglia_vino contenuti nel blocco puntato da punt_vino*/

 

{

int k;

for(k=0;k<numero;k++)

printf("Produttore: %sQuantita:%d;\n",

(punt_vino+k)->produttore,(punt_vino+k)->quantita);

 

}

 

 esercizio

 

Test 19