Sei sulla pagina 1di 43

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
C
L an
gu
ag
e

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)
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)
variabile

Fondamenti di Informatica I  a.a. 2008-09 3


Le strutture  1

Esempio:
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:
soluzione memorizzare le informazioni in variabili
distinte
char name[20], fiscode[16]; Le informazioni relative ad
una persona sono sparse
short day, month, year; 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 Vi sono due dichiarazioni: la
struct vitalstat prima contiene lo schema della
{ struttura vitalstat,
vitalstat la seconda
char vs_name[20], vs_fiscode[16]; dichiara una variabile vs di tipo
short vs_day, vs_month, vs_year; struct vitalstat
}; Nota:
Nota includere un prefisso nei
struct vitalstat vs; nomi dei campi, per distinguerli
da campi di strutture diverse
L’allocazione della struttura vs
sulla macchina di riferimento vs_name[]
presuppone che i campi siano
memorizzati consecutivamente,
nell’ordine in cui sono dichiarati,
vs_fiscode[]
ma non necessariamente in
maniera contigua vs_day[] vs_month[]

Fondamenti di Informatica I  a.a. 2008-09


vs_year[] 6
Le strutture  4
Il nome vitalstat è un’etichetta (o tag)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 short vs_day, vs_month, vs_year;
consentono di definire una sola }
volta lo schema di una struttura, VITALSTAT;
per dichiarare variabili del tipo
struttura quando necessario
Le dichiarazioni di struttura sono normalmente raggruppate
in file header,
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,
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 */ 9
Fondamenti di Informatica I  a.a. 2008-09
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
VITALSTAT *pvs;
vs.vs_day  23; ………
vs.vs_month  3; pvs>vs_day  23;
vs.vs_year  1989; 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 è equivalente a (*pvs).vs_day


Fondamenti di Informatica I  a.a. 2008-09 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 Esempio:
Esempio Funzione che
typedef VITALSTAT */ calcola il numero di persone
int agecount(vsa, size, low_age, high_age, current_year)
con età compresa in un
VITALSTAT vsa[]; intervallo specificato
int size, low_age, high_age, current_year;
Le variabili locali p e p_last
{
int age, count0;
sono state introdotte per
VITALSTAT *pvsa, *p_last&vsa[size]; mantenere invariato il valore
for (; p<p_last; p) del parametro formale vsa
{ (che altrimenti potrebbe
agecurrent_year  p>vs_year; essere usato direttamente
if ((age > low_age) && (age < high_age))
count;
nel ciclo)
}
return count;
}
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 typedef struct
{ {
char vs_name[20], vs_fiscode[16]; char day;
struct vs_birth_date char month;
{ short vs_day; short year;
short vs_month; } DATE;
short vs_year; typedef struct
}; {
} VITALSTAT; char vs_name[20], vs_fiscode[16];
DATE vs_birth_date;
Per identificare l’anno di nascita in una struttura
vs dichiarata VITALSTAT,
VITALSTAT si deve scrivere } 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

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 mem1 mem2 mem3


1000 1001 1003
{
char mem1; Allocazione con restrizioni di allineamento
short mem2; mem1 spazio vuoto mem2
char mem3; 1000 1001 1002
} s1;
mem3 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) func2(pvs)
VITALSTAT vs; /* l’argomento è VITALSTAT *pvs; /* l’argomento è un
* una struttura */ * 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; /* st è un puntatore a struttura */
Fondamenti di Informatica I  a.a. 2008-09 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
Fondamenti (&result); I  a.a. 2008-09
di Informatica 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;
……… 24
Fondamenti di Informatica I  a.a. 2008-09
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:
Esempio
1000 1001 1002 1004
typedef union
{ c1 c2
struct
{
char c1, c2; j
} s;
long j;
x
float x;
} U;

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

I caratteri ricevuti vengono


union doub
{ memorizzati in elementi successivi
char c[8]; di c[ ]: il valore del numero double
double val;
si ottiene accedendo al campo val
};
dell’unione
double get_double()
{ L’accesso ai campi di un’unione
extern char get_byte(); non ha impatto alcuno sui bit
int j;
contenuti in memoria (non si
union doub d;
effettuano conversioni di tipo): il
for (j0; j<8; j)
d.c[j]  get_byte();
compilatore interpreta in modo
return d.val; diverso gli stessi bit
}

Fondamenti di Informatica I  a.a. 2008-09 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


{ Lista concatenata semplice
char vs_name[20], vs_fiscode[16];
Dati Dati
unsigned int vs_day,
vs_month,
vs_year; Dati Dati
struct vitalstat *next;
} VITALSTAT;

Esistono liste semplici e liste doppiamente concatenate,


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 ELEMENT *create_list_element()
della lista, ma non {
lo collega alla lista ELEMENT *p;
stessa 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:
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,
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:
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” La variabile head è un


static ELEMENT *head; puntatore all’inizio della
lista ed è dichiarata con
void add_element(e)
ELEMENT *e;
ambito di visibilità a
{ livello di file, per renderla
ELEMENT *p; disponibile a più funzioni
/* se il primo elemento (testa) non esiste, viene creato */ Nel ciclo for,
for la scansione
if (head  NULL) della lista è basata sul
{ controllo del valore di
head  e; p->next:
p->next se è diverso da
return;
NULL, esiste un elemento
}
/* altrimenti, trova l’ultimo elemento della lista */
successivo, altrimenti è
for (p  head; p>next ! NULL; p  p>next)
stata raggiunta la fine
; /* istruzione vuota */ della lista
p > next  e;
}
Fondamenti di Informatica I  a.a. 2008-09 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:
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>next

include “v_stat.h”

void insert_after(p,q) /* inserimento di p dopo q */


ELEMENT *p, *q;
{ q dopo q>next>next
/* controllo di validità degli argomenti */
if ((p  NULL)) || (q  NULL) || (p  q) ||
(q>next  p)) p

{
printf(“insert_after: argomenti errati.\n”);
return;
}
p > next  q >next;
q > next  p;
} 37
Fondamenti di Informatica I  a.a. 2008-09
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;
L’operatore freccia destra
ha associatività sinistra e
void delete_element(goner)
ELEMENT *goner;
pertanto l’espressione
{
p>next>next
ELEMENT *p;
if (goner  head) viene valutata come
head  goner>next;
else (p>next)>next
{
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 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:
Esempio Funzione che ricerca, fra strutture di tipo vitalstat,
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;
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;
Fondamenti di Informatica I  a.a. 2008-09 40
}
Costruzione di una lista ordinata  1
/* /*
** Letta in input una sequenza di numeri interi la * Funzione principale.
** memorizza in una lista in ordine crescente. */
** main(void)
*/ {
struct nodo *primo;
#include <stdlib.h>
#include <stdio.h> primo  leggi_lista_ordinata();
stampa_lista(primo);
/*
exit(0);
* struttura per la rappresentazione dei nodi della lista
}
*/
struct nodo {
int info;
struct nodo *next;
};

Fondamenti di Informatica I  a.a. 2008-09 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))
{
struct nodo *leggi_lista_ordinata(void) prec  p1;
{ p1  p1->next;
struct nodo *p, *p1, *primo, *prec; }
int i, n, num; if (prec ! NULL)
primo = NULL; prec->next  p;
printf(“Inserire numero di elementi: ”); else
scanf(“%d”, &n); primo  p;
for (i0; i<n; i) p->next  p1;
{ }
scanf(“%d”, &num); return(primo);
p  malloc(sizeof(struct nodo)); }
p->info  num;
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

Potrebbero piacerti anche