le strutture e le unioni

annuncio pubblicitario
Il linguaggio C
Le strutture
Le unioni
Le liste concatenate
Allocazione dinamica
Creazione e aggiunta di un nuovo elemento alla lista
Inserimento e cancellazione di elementi
La ricerca di un elemento
Fondamenti di Informatica I  a.a. 2008-09
1
Le strutture
Fondamenti di Informatica I  a.a. 2008-09
2
Introduzione
Gli array sono uno strumento adeguato per il
trattamento di insiemi di variabili di uno stesso tipo
Quando i tipi di dati, che devono essere logicamente
aggregati, sono distinti, è necessario usare il tipo
struttura (o record)
L’ulteriore tipo composto unione consente di
interpretare il contenuto delle stesse locazioni di
memoria con modalità diverse (è la realizzazione del
concetto di record a lunghezza variabile)
Fondamenti di Informatica I  a.a. 2008-09
3
Le strutture  1
Esempio: Supponiamo di voler memorizzare, relativamente
a ciascun abitante di un dato comune, nome e cognome,
data di nascita e codice fiscale:
Nome e cognome costituiscono un array di caratteri
La data è composta da tre numeri interi, che descrivono
giorno, mese ed anno
Il codice fiscale è un array di 16 caratteri (15 per il
codice ed uno per il carattere nullo di terminazione)
 Le informazioni non possono essere collezionate in un
unico array di caratteri, perché sono disomogenee
Fondamenti di Informatica I  a.a. 2008-09
4
Le strutture  2
Possibile soluzione: memorizzare le informazioni in variabili
distinte
char name[20], fiscode[16];
short day, month, year;
Le informazioni relative ad
una persona sono sparse
per la memoria
Un’organizzazione più naturale consiste nella definizione di
una variabile che contenga tutti i dati relativi ad una persona:
utilizzando un tipo struttura
Una struttura è simile ad un array, ma è costituita da campi
(piuttosto che da elementi) che sono identificati da nomi
(piuttosto che da indici) e possono contenere informazione di
tipo diverso
Fondamenti di Informatica I  a.a. 2008-09
5
Le strutture  3
Esempio
struct vitalstat
{
char vs_name[20], vs_fiscode[16];
short vs_day, vs_month, vs_year;
};
struct vitalstat vs;
L’allocazione della struttura vs
sulla macchina di riferimento
presuppone che i campi siano
memorizzati consecutivamente,
nell’ordine in cui sono dichiarati,
ma non necessariamente in
maniera contigua
Fondamenti di Informatica I  a.a. 2008-09
Vi sono due dichiarazioni: la
prima contiene lo schema della
struttura vitalstat, la seconda
dichiara una variabile vs di tipo
struct vitalstat
Nota: includere un prefisso nei
nomi dei campi, per distinguerli
da campi di strutture diverse
vs_name[]
vs_fiscode[]
vs_day[]
vs_year[]
vs_month[]
6
Le strutture  4
Il nome vitalstat è un’etichetta (o tag) e struct vitalstat
rappresenta un nuovo tipo di dati definito dall’utente, per il
quale non viene riservata memoria
L’etichetta può essere utilizzata ogni volta che è necessario
creare ulteriori variabili che contengono gli stessi campi
struct vitalstat vsa[1000], *pvs;
pvs  &vsa[10];
La sintassi della dichiarazione di una struttura può assumere
diverse forme:
Dichiarazione dell’etichetta e uso dell’etichetta (insieme alla
parola chiave struct) per definire le variabili
Uso di typedef per definire un particolare tipo struttura
Fondamenti di Informatica I  a.a. 2008-09
7
Le strutture  5
Il tipo VITALSTAT rappresenta l’intera struttura, compresa la
parola chiave struct
typedef
Il nome di tipo è scritto struct
maiuscolo, per distinguerlo dai {
nomi di etichette e variabili
char vs_name[20], vs_fiscode[16];
Un’etichetta o un typedef
consentono di definire una sola
volta lo schema di una struttura,
per dichiarare variabili del tipo
struttura quando necessario
short vs_day, vs_month, vs_year;
}
VITALSTAT;
Le dichiarazioni di struttura sono normalmente raggruppate
in file header, così da poter essere accedute da più file
sorgente
Fondamenti di Informatica I  a.a. 2008-09
8
L’inizializzazione delle strutture
Una struttura può essere inizializzata facendo seguire al nome della
variabile di tipo struttura il simbolo di uguale e la lista dei valori
iniziali racchiusi tra parentesi graffe
Ogni valore iniziale deve essere dello stesso tipo del corrispondente
campo della struttura
VITALSTAT vs  {“Marco Rossi”, “MRCRSS89C23D612K”,
23, 3, 1989 };
Un valore iniziale non può essere incluso in una dichiarazione che
contiene solo un’etichetta o un typedef, poiché tali dichiarazioni
definiscono lo schema della struttura, ma non riservano memoria
typedef struct
{
int a;
float b;
} s  {1, 1.0}; /* non ammesso */
Fondamenti di Informatica I  a.a. 2008-09
9
L’accesso ai campi della struttura
Esistono due modalità diverse di accesso ai campi di una struttura,
dipendenti dalla modalità di accesso alla struttura, diretta o
mediante puntatore
Nel caso di accesso diretto alla struttura, si usano il nome della
struttura ed il nome del campo, separati dall’operatore punto “.”
Nel caso di accesso tramite puntatore alla struttura, si usa l’operatore
freccia destra “>”, formato dalla concatenazione del segno meno e
del simbolo maggiore
vs.vs_day  23;
vs.vs_month  3;
vs.vs_year  1989;
VITALSTAT *pvs;
………
pvs>vs_day  23;
pvs>vs_month  3;
pvs>vs_year  1989;
L’operatore > è una forma abbreviata per accedere all’indirizzo
contenuto nel puntatore e quindi applicare l’operatore punto
pvs>vs_day
Fondamenti di Informatica I  a.a. 2008-09
è equivalente a
(*pvs).vs_day
10
Gli array di strutture
Gli array di strutture vengono dichiarati facendo precedere al
nome dell’array il nome typedef della struttura
include “v_stat.h” /* file header che contiene la dichiarazione
typedef VITALSTAT */
int agecount(vsa, size, low_age, high_age, current_year)
VITALSTAT vsa[];
int size, low_age, high_age, current_year;
{
int age, count0;
VITALSTAT *pvsa, *p_last&vsa[size];
for (; p<p_last; p)
{
agecurrent_year  p>vs_year;
if ((age > low_age) && (age < high_age))
count;
}
return count;
Esempio:
Funzione che
calcola il numero di persone
con età compresa in un
intervallo specificato
Le variabili locali p e p_last
sono state introdotte per
mantenere invariato il valore
del parametro formale vsa
(che altrimenti potrebbe
essere usato direttamente
nel ciclo)
}
Fondamenti di Informatica I  a.a. 2008-09
11
Le strutture innestate  1
Una struttura innestata è una struttura in cui almeno uno dei campi
è, a sua volta, una struttura
Le strutture innestate sono comuni in C perché consentono di creare
gerarchie di dati
typedef struct
{
char vs_name[20], vs_fiscode[16];
struct vs_birth_date
{
short vs_day;
short vs_month;
short vs_year;
};
} VITALSTAT;
Per identificare l’anno di nascita in una struttura
vs dichiarata VITALSTAT, si deve scrivere
typedef struct
{
char day;
char month;
short year;
} DATE;
typedef struct
{
char vs_name[20], vs_fiscode[16];
DATE vs_birth_date;
} VITALSTAT;
vs.vs_birth_date.vs_year
Fondamenti di Informatica I  a.a. 2008-09
12
Le strutture innestate  2
Una struttura innestata viene inizializzata racchiudendo i valori
iniziali fra parentesi graffe
typedef struct
{
DATE d;
char event[20];
} CALENDAR;
CALENDAR holiday  {{25, 12, 2009}, “Natale”};
Non esistono limiti al numero di livelli di nesting delle
strutture, anche se i riferimenti agli elementi diventano
sempre più difficili da leggere perché contengono i nomi di
tutte le strutture intermedie
Fondamenti di Informatica I  a.a. 2008-09
13
Le strutture contenenti
puntatori a sé stesse  1
Le strutture e le unioni non possono contenere istanze di sé
stesse, ma possono contenere puntatori a sé stesse
struct s {
int a, b;
float c;
struct s *pointer_to_s;
};
Il compilatore consente di dichiarare un puntatore ad una
struttura prima che sia stata dichiarata la struttura
Fondamenti di Informatica I  a.a. 2008-09
14
Le strutture contenenti
puntatori a sé stesse  2
Il riferimento in avanti a strutture (e unioni) è uno dei pochi
casi nel linguaggio C in cui un identificatore può essere
utilizzato prima di essere dichiarato
Il riferimento in avanti non è ammesso con la definizione di
tipo (typedef)
typedef struct neg {
int a;
FOO *p; /* errato perché FOO non
* è ancora stato dichiarato
*/
} FOO;
Fondamenti di Informatica I  a.a. 2008-09
15
L’allineamento dei campi
delle strutture  1
Alcune architetture (come i processori Motorola) richiedono
che ogni oggetto di dimensioni superiori ad un char venga
memorizzato in locazioni di memoria con indirizzo pari
I problemi di allineamento non sono normalmente visibili al
programmatore, ma possono creare spazi vuoti all’interno
delle strutture
Allocazione senza restrizioni di allineamento
struct align_examp
{
char mem1;
short mem2;
char mem3;
} s1;
mem1
1000
mem2
1001
mem3
1003
Allocazione con restrizioni di allineamento
mem1
1000
mem3
mem2
spazio vuoto
1001
1002
spazio vuoto
1004
Fondamenti di Informatica I  a.a. 2008-09
16
L’allineamento dei campi
delle strutture  2
Gli spazi vuoti vengono eliminati da una redistribuzione delle
dichiarazioni degli elementi
struct align_examp
{
char mem1, mem3;
short mem2;
} s1;
Poiché le strutture possono essere memorizzate in modi
diversi sui diversi calcolatori, è necessario accedervi con
modalità portabili
L’allineamento naturale (tutti gli oggetti di 2 byte iniziano da
indirizzi pari, gli oggetti di 4 byte a indirizzi divisibili per
quattro, etc.) è il requisito più stringente imposto dai
calcolatori
 Se la struttura è allineata in modo naturale è portabile
Fondamenti di Informatica I  a.a. 2008-09
17
Il passaggio di strutture come
parametri di funzione  1
Esistono due modalità per passare strutture come argomenti
di funzione:
Passaggio della struttura vera e propria, per valore
Passaggio di un puntatore alla struttura, per indirizzo
VITALSTAT vs;
………
func1(vs); /* Passaggio per valore */
………
func2(&vs); /* Passaggio per indirizzo */
Il passaggio per indirizzo è più efficiente perché solo il
puntatore viene copiato nell’area di memoria degli
argomenti, mentre il passaggio per valore richiede la copia
dell’intera struttura
Fondamenti di Informatica I  a.a. 2008-09
18
Il passaggio di strutture come
parametri di funzione  2
Le strutture dovrebbero essere passate per valore solo se…
…la struttura è molto piccola (di dimensione paragonabile al puntatore)
…è necessario garantire che la funzione chiamata non ne alteri il
contenuto originale
In dipendenza della modalità di passaggio prescelta, occorre
dichiarare il parametro all’interno della funzione come
struttura o come puntatore a struttura
func1(vs)
VITALSTAT vs; /* l’argomento è
* una struttura */
func2(pvs)
VITALSTAT *pvs; /* l’argomento è un
* puntatore a
* struttura */
La scelta della modalità di passaggio dei parametri struttura
definisce gli operatori da impiegare all’interno della funzione
chiamata (il punto se la struttura è passata per valore, la
freccia destra se è passata per indirizzo)
Fondamenti di Informatica I  a.a. 2008-09
19
Il passaggio di strutture e di array
come parametri di funzione  1
Le modalità per il passaggio di strutture e di array come
parametri di funzione non sono omogenee

Per passare un array, si specifica il solo nome dell’array senza
indici: il compilatore interpreta il nome come un puntatore al
primo elemento dell’array, che viene passato per indirizzo
Non è possibile passare un array per valore, se non includendolo
in una struttura passata per valore
Per le strutture, il nome viene interpretato come l’intera
struttura
Applicando la stessa sintassi si ottiene una semantica diversa
int ar[100];
struct tag st;
………
funcv(ar); /* viene passato un puntatore al primo elemento di ar[] */
………
funcs(st); /* viene passata l’intera struttura */
Fondamenti di Informatica I  a.a. 2008-09
20
Il passaggio di strutture e di array
come parametri di funzione  2
La stessa inconsistenza si riproduce anche all’interno delle
funzioni
Le due versioni basate su array sono equivalenti:
funcv(ar)
int ar[]; /* ar viene convertito in puntatore ad intero */
funcv(ar);
int *ar; /* ar è un puntatore ad intero */
Le due versioni basate su strutture non lo sono:
funcs1(st)
struct tag st; /* st è una struttura completa */
funcs2(st);
struct tag *st;
Fondamenti di Informatica I  a.a. 2008-09
/* st è un puntatore a struttura */
21
Strutture restituite da funzioni  1
Le funzioni possono restituire strutture o puntatori a
strutture
La dichiarazione del tipo di dato restituito da una funzione
deve essere concorde con il valore effettivamente restituito
Generalmente, è preferibile restituire puntatori a strutture
per motivi di efficienza
Se si restituisce un puntatore a struttura, la struttura deve
avere durata fissa, perché altrimenti non sarebbe più
accessibile al termine della funzione
La restituzione di strutture è particolarmente utile quando si
voglia comunicare all’esterno più di un valore
Fondamenti di Informatica I  a.a. 2008-09
22
Strutture restituite da funzioni  2
include <stdio.h>
include <math.h>
define TOO_LARGE 100 /* dipendente dalla macchina */
define NULL (void *) 0
typedef struct
{
double sine, cosine, tangent;
} TRIG;
TRIG *get_trigvals(radian_val)
double radian_val;
{
static TRIG result;
/* se radian_val è troppo grande, i valori sin, cos, tan non sono significativi */
if (radian_val > TOO_LARGE)
{
printf(“Valore di ingresso troppo grande”);
return NULL;
}
result.sine  sin(radian_val);
result.cosine  cos(radian_val);
result.tangent  tan(radian_val);
return (&result);
}
Fondamenti
di Informatica I  a.a. 2008-09
23
L’assegnamento di strutture
Lo standard ANSI consente di assegnare una struttura ad una
variabile struttura dello stesso tipo
struct {
int a;
float b;
} s1, s2, sf(), *ps;
………
s1  s2;
s2  sf();
ps  &s1;
s2  *ps;
………
Fondamenti di Informatica I  a.a. 2008-09
24
Le unioni
Fondamenti di Informatica I  a.a. 2008-09
25
Le unioni  1
Le unioni consentono agli elementi di sovrapporsi l’uno sull’altro
per condividere la stessa area di memoria
Esempio:
typedef union
{
struct
{
char c1, c2;
} s;
long j;
float x;
} U;
1000
1001
c1
c2
1002
1004
j
x
Il compilatore riserva sempre una quantità di memoria sufficiente
all’elemento più grande e tutti gli elementi iniziano allo stesso
indirizzo
Fondamenti di Informatica I  a.a. 2008-09
26
Esempio sulle unioni  1
I dati viaggiano sulla linea un byte alla volta; le unioni
consentono di raggruppare i byte in modo tale che
possano essere ricostruiti nella loro forma originale
Sia get_byte() una funzione che restituisce un singolo
byte prelevato da un dispositivo di comunicazione
Un valore double a otto byte può essere estratto dal
dispositivo mediante otto chiamate successive alla
funzione get_byte()
Fondamenti di Informatica I  a.a. 2008-09
27
Esempio sulle unioni  2
union doub
{
char c[8];
double val;
};
double get_double()
{
extern char get_byte();
int j;
union doub d;
for (j0; j<8; j)
d.c[j]  get_byte();
return d.val;
}
Fondamenti di Informatica I  a.a. 2008-09
I caratteri ricevuti vengono
memorizzati in elementi successivi
di c[ ]: il valore del numero double
si ottiene accedendo al campo val
dell’unione
L’accesso ai campi di un’unione
non ha impatto alcuno sui bit
contenuti in memoria (non si
effettuano conversioni di tipo): il
compilatore interpreta in modo
diverso gli stessi bit
28
Le liste concatenate
Fondamenti di Informatica I  a.a. 2008-09
29
Allocazione dinamica
Finora, per gestire insiemi di dati, sono stati utilizzati array
(di strutture)
Tale approccio è valido se si conosce a priori il numero di
elementi che si devono gestire
Viceversa, l’utilizzo di array può essere estremamente oneroso,
perché rende necessaria l’allocazione di una quantità di
memoria sufficiente a memorizzare il caso peggiore:
Parte della memoria può andare sprecata (perché
inutilizzabile per scopi diversi)
Non è possibile accedere ad una quantità di memoria
maggiore di quella allocata inizialmente
La soluzione consiste nell’allocare memoria in modo
dinamico, con malloc() o calloc()  che, tuttavia, non
garantiscono la contiguità fisica per elementi logicamente
contigui  e nell’utilizzare liste concatenate
Fondamenti di Informatica I  a.a. 2008-09
30
Le liste concatenate  1
Il modo più comune per garantire la contiguità logica di strutture
allocate dinamicamente è l’uso delle liste concatenate
In una lista concatenata, ogni struttura contiene un elemento
aggiuntivo che punta alla struttura successiva
typedef struct vitalstat
{
char vs_name[20], vs_fiscode[16];
unsigned int vs_day,
vs_month,
vs_year;
struct vitalstat *next;
} VITALSTAT;
Lista concatenata semplice
Dati
Dati
Dati
Dati
Esistono liste semplici e liste doppiamente concatenate, in cui ogni
struttura possiede due puntatori, rispettivamente all’elemento
precedente ed al successivo
Fondamenti di Informatica I  a.a. 2008-09
31
Le liste concatenate  2
Le operazioni che si effettuano sulle liste sono:
Creazione di un elemento
Aggiunta di un elemento alla fine della lista
Inserimento di un elemento in una lista
Cancellazione di un elemento da una lista
Ricerca di un elemento in una lista
Tutte le operazioni, tranne la ricerca, sono indipendenti
dal contenuto informativo delle strutture e possono
essere formulate in modo generale
Fondamenti di Informatica I  a.a. 2008-09
32
La creazione di un elemento  1
Per creare un elemento di una lista, è sufficiente riservare
memoria per la struttura e restituire un puntatore all’area
allocata
include “v_stat.h”
include <stdlib.h>
Alloca la memoria
ad un elemento
della lista, ma non
lo collega alla lista
stessa
ELEMENT *create_list_element()
{
ELEMENT *p;
p  (ELEMENT *) malloc(sizeof(ELEMENT));
if (p  NULL)
{
printf(“create_list_element: malloc non riuscita. \n”);
exit(1);
}
p > next  NULL;
return p;
}
Fondamenti di Informatica I  a.a. 2008-09
33
La creazione di un elemento  2
Note:
Il nome ELEMENT rende la funzione indipendente dal tipo di
dati effettivamente gestiti
Per utilizzare la funzione create_list_element() in relazione alla
struttura vitalstat, è necessario includere nel file v_stat.h (che
contiene la definizione del tipo struttura) le ulteriori
dichiarazioni:
define NULL (void *) 0
typedef struct vitalstat ELEMENT;
ELEMENT diviene un sinonimo di struct vitalstat
Per dichiarare il puntatore occorre usare un’etichetta invece di
un typedef: è la sola modalità con cui una struttura può fare
riferimento a sé stessa, dato che il nome di typedef non è
definito fino al termine della dichiarazione
Fondamenti di Informatica I  a.a. 2008-09
34
L’aggiunta di un nuovo elemento  1
include “v_stat.h”
static ELEMENT *head;
void add_element(e)
ELEMENT *e;
{
ELEMENT *p;
/* se il primo elemento (testa) non esiste, viene creato */
if (head  NULL)
{
head  e;
return;
}
/* altrimenti, trova l’ultimo elemento della lista */
for (p  head; p>next ! NULL; p  p>next)
; /* istruzione vuota */
p > next  e;
}
Fondamenti di Informatica I  a.a. 2008-09
La variabile head è un
puntatore all’inizio della
lista ed è dichiarata con
ambito di visibilità a
livello di file, per renderla
disponibile a più funzioni
Nel ciclo for, la scansione
della lista è basata sul
controllo del valore di
p->next: se è diverso da
NULL, esiste un elemento
successivo, altrimenti è
stata raggiunta la fine
della lista
35
L’aggiunta di un nuovo elemento  2
L’assegnamento
p>next  e;
aggiunge una nuova struttura alla fine della lista
L’argomento e della funzione è un puntatore alla struttura
che è stata allocata dalla funzione chiamante
Esempio: Creare una lista concatenata di dieci strutture
vitalstat
include “v_stat.h”
static ELEMENT *head;
main()
{
for (j0; j<10; j)
add_element(create_list_element());
}
Fondamenti di Informatica I  a.a. 2008-09
36
L’inserimento di un elemento
Per inserire un elemento in una lista concatenata, deve essere
specificata la posizione in cui deve avvenire l’inserimento
q
prima
q
dopo
q>next
include “v_stat.h”
void insert_after(p,q) /* inserimento di p dopo q */
ELEMENT *p, *q;
{
/* controllo di validità degli argomenti */
if ((p  NULL)) || (q  NULL) || (p  q) ||
(q>next  p))
{
printf(“insert_after: argomenti errati.\n”);
return;
}
p > next  q >next;
q > next  p;
}
Fondamenti di Informatica I  a.a. 2008-09
q>next>next
p
37
La cancellazione di un elemento  1
Per la cancellazione di un elemento da una lista concatenata,
occorre individuare l’elemento che precede quello da eliminare
per riallacciare i puntatori della lista dopo l’eliminazione
Inoltre, è necessario utilizzare la funzione free() per rilasciare
la memoria dell’elemento eliminato
p
goner
p>next>next
prima
p
p>next
dopo
Fondamenti di Informatica I  a.a. 2008-09
38
La cancellazione di un elemento  2
include “v_stat.h”
static ELEMENT *head;
void delete_element(goner)
ELEMENT *goner;
{
ELEMENT *p;
if (goner  head)
head  goner>next;
else
{
for (p  head; (p ! NULL) && (p>next ! goner); p  p>next)
; /* istruzione vuota */
if (p  NULL)
{
printf(“delete_element: elemento non contenuto nella lista.\n”);
return;
}
p > next  p>next>next ;
}
free(goner);
}
Fondamenti di Informatica I  a.a. 2008-09
L’operatore freccia destra
ha associatività sinistra e
pertanto l’espressione
p>next>next
viene valutata come
(p>next)>next
39
La ricerca di un elemento
La funzione di ricerca di un elemento della lista viene fatta in
base al contenuto di uno o più campi della struttura
Esempio: Funzione che ricerca, fra strutture di tipo vitalstat,
un elemento per cui il valore del campo name coincida con
l’argomento della funzione
include “v_stat.h”
include <string.h>
static ELEMENT *head;
Fondamenti di Informatica I  a.a. 2008-09
ELEMENT *find(aname)
char *aname;
{
ELEMENT *p;
for (p  head; p ! NULL; p  p>next)
if (strcmp(p>vs_name, aname) )
return p;
return NULL;
40
}
Costruzione di una lista ordinata  1
/*
** Letta in input una sequenza di numeri interi la
** memorizza in una lista in ordine crescente.
**
*/
#include <stdlib.h>
#include <stdio.h>
/*
* struttura per la rappresentazione dei nodi della lista
*/
struct nodo {
int info;
struct nodo *next;
};
Fondamenti di Informatica I  a.a. 2008-09
/*
* Funzione principale.
*/
main(void)
{
struct nodo *primo;
primo  leggi_lista_ordinata();
stampa_lista(primo);
exit(0);
}
41
Costruzione di una lista ordinata  2
/*
* Legge una sequenza di numeri interi e li memorizza in
* una lista ordinata (in ordine crescente).
* Restituisce il puntatore al primo elemento della lista.
while ((p1 ! NULL) && (p1->info < p->info))
{
prec  p1;
p1  p1->next;
*/
struct nodo *leggi_lista_ordinata(void)
{
struct nodo *p, *p1, *primo, *prec;
int i, n, num;
}
if (prec ! NULL)
prec->next  p;
else
primo  p;
p->next  p1;
primo = NULL;
printf(“Inserire numero di elementi: ”);
scanf(“%d”, &n);
for (i0; i<n; i)
{
scanf(“%d”, &num);
p  malloc(sizeof(struct nodo));
p->info  num;
}
return(primo);
}
p1  primo;
prec  NULL;
Fondamenti di Informatica I  a.a. 2008-09
42
Costruzione di una lista ordinata  3
/*
* Stampa la lista, a partire dall’elemento puntato dal
* puntatore p, ricevuto come parametro.
*/
void stampa_lista(p)
struct nodo *p;
{
while (p ! NULL)
{
printf(“%d ---> ”, p->info);
p  p->next;
}
printf(“NULL\n”);
return;
}
Fondamenti di Informatica I  a.a. 2008-09
43
Scarica