Nessun titolo diapositiva - PowerPoint PPT Presentation

1 / 47
About This Presentation
Title:

Nessun titolo diapositiva

Description:

Title: Nessun titolo diapositiva Last modified by: monica Document presentation format: Presentazione su schermo Other titles: Times New Roman Courier New Wingdings ... – PowerPoint PPT presentation

Number of Views:36
Avg rating:3.0/5.0
Slides: 48
Provided by: ingUnisiI
Category:

less

Transcript and Presenter's Notes

Title: Nessun titolo diapositiva


1
Le strutture e le unioni in C
2
Sommario
  • Le strutture e le unioni
  • Le liste concatenate
  • Allocazione dinamica
  • Creazione ed aggiunta di un nuovo elemento alla
    lista
  • Inserimento e cancellazione di elementi
  • La ricerca di un elemento

2
3
Le strutture e le unioni
3
4
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 disomogenei, è
    necessario usare il tipo struttura (o record)
  • Lulteriore 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)

4
5
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

5
6
Le strutture ? 2
  • Possibile soluzione memorizzare le informazioni
    in variabili distinte
  • Unorganizzazione 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

6
7
Le strutture ? 3
Esempio
  • 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

struct vitalstat char vs_name20,vs_fiscode
16 short vs_day,vs_month,vs_year struct
vitalstat vs










  • Lallocazione della struttura vs sulla macchina
    di riferimento presuppone che i campi siano
    memorizzati consecutivamente, nellordine in cui
    sono dichiarati, ma non necessariamente in
    maniera contigua

vs_name
vs_fiscode
vs_day
vs_month
vs_year
7
8
Le strutture ? 4
  • Il nome vitalstat è unetichetta (o tag) e struct
    vitalstat rappresenta un nuovo tipo di dati
    definito dallutente, per il quale non viene
    riservata memoria
  • Letichetta può essere utilizzata ogni volta che
    è necessario creare ulteriori variabili che
    contengono gli stessi campi
  • La sintassi della dichiarazione di una struttura
    può assumere diverse forme
  • Dichiarazione delletichetta e uso delletichetta
    (insieme alla parola chiave struct) per definire
    le variabili
  • Uso di typedef per definire un particolare tipo
    struttura

struct vitalstat vsa1000, pvs pvs ? vsa10
8
9
Le strutture ? 5
  • Il tipo VITALSTAT rappresenta lintera struttura,
    compresa la parola chiave struct
  • Il nome di tipo è scritto maiuscolo, per
    distinguerlo dai nomi di etichette e variabili
  • Unetichetta o un typedef consentono di definire
    una sola volta lo schema di una struttura, per
    dichiarare variabili del tipo struttura quando
    necessario

typedef struct char vs_name20,vs_fiscode1
6 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

9
10
Linizializzazione di strutture ? 1
  • 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,
MRCRSS91C23D612K, 23, 3, 1991
10
11
Linizializzazione di strutture ? 2
  • Un valore iniziale non può essere incluso in una
    dichiarazione che contiene solo unetichetta 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 /
11
12
Laccesso 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 dalloperatore punto .
  • Nel caso di accesso tramite puntatore alla
    struttura, si usa loperatore freccia destra
    ?gt, formato dalla concatenazione del segno meno
    e del simbolo maggiore
  • Loperatore ?gt è una forma abbreviata per
    accedere allindirizzo contenuto nel puntatore e
    quindi applicare loperatore punto

VITALSTAT pvs pvs?gtvs_day ? 23
pvs?gtvs_month ? 3 pvs?gtvs_year ? 1991
vs.vs_day ? 23 vs.vs_month ? 3 vs.vs_year ?
1991
pvs?gtvs_day è equivalente a (pvs).vs_day
12
13
Gli array di strutture
  • Gli array di strutture vengono dichiarati facendo
    precedere al nome dellarray il nome typedef
    della struttura
  • Esempio Funzione che calcola il numero di
    persone con età compresa in un intervallo
    specificato
  • Le variabili locali p e p_last sono state
    introdot-te per mantenere invariato il valore del
    parametro formale vsa (che altrimenti potrebbe
    essere usato direttamente nel ciclo)

?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?vsasize
for ( pltp_last p??)
age?current_year ? p?gtvs_year if
((age gt? low_age) (age lt? high_age))
count?? return count
13
14
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 day char
month short year DATE typedef
struct char vs_name20, vs_fiscode16
DATE vs_birth_date VITALSTAT
typedef struct char vs_name20,
vs_fiscode16 struct vs_birth_date
short vs_day short vs_month
short vs_year VITALSTAT
Per identificare lanno di nascita in una
struttura vs dichiarata VITALSTAT, si deve
scrivere vs.vs_birth_date.vs_year
14
15
Le strutture innestate ? 2
  • Una struttura innestata viene inizializzata
    racchiudendo i valori iniziali fra parentesi
    graffe
  • 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

typedef struct DATE d char
event20 CALENDAR CALENDAR holiday ? 25,
12, 2010, Natale
15
16
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
  • Il compilatore consente di dichiarare un
    puntatore ad una struttura prima che sia stata
    dichiarata la struttura

struct s int a, b float c
struct s pointer_to_s
16
17
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
17
18
Lallineamento 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 allinterno delle strutture

struct align_examp char mem1 short
mem2 char mem3 s1
1005
18
19

Lallineamento dei campi delle strutture ? 2
  • Gli spazi vuoti vengono eliminati da una
    redistribuzione delle dichiarazioni degli
    elementi
  • Poiché le strutture possono essere memorizzate in
    modi diversi sui diversi calcolatori, è
    necessario accedervi con modalità portabili
  • Lallineamento 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

struct align_examp char mem1, mem3
short mem2 s1
19
20
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
  • Il passaggio per indirizzo è più efficiente
    perché solo il puntatore viene copiato nellarea
    di memoria degli argomenti, mentre il passaggio
    per valore richiede la copia dellintera
    struttura

VITALSTAT vs func1(vs) / Passaggio
per valore / func2(vs) / Passaggio
per indirizzo /
20
21
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
    allinterno della funzione come struttura o come
    puntatore a struttura

void func1(vs) VITALSTAT vs / largomento è
una struttura /
void func2(pvs) VITALSTAT pvs / largomento è
un puntatore a struttura /
21
22
Il passaggio di strutture come parametri di
funzione ? 3
  • La scelta della modalità di passaggio dei
    parametri struttura definisce gli operatori da
    impiegare allinterno della funzione chiamata
  • il punto se la struttura è passata per valore
  • la freccia destra se è passata per indirizzo

22
23
Il passaggio di strutture ed 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
    dellarray senza indici il compilatore
    interpreta il nome come un puntatore al primo
    elemento dellarray, 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
    lintera struttura
  • Applicando la stessa sintassi si ottiene una
    semantica diversa

int ar100 struct tag st funcv(ar) /
viene passato un puntatore al primo elemento di
ar / funcs(st) / viene passata
lintera struttura /
23
24
Il passaggio di strutture ed array come parametri
di funzione ? 2
  • La stessa inconsistenza si riproduce anche
    allinterno delle funzioni
  • Le due versioni basate su array sono equivalenti
  • Le due versioni basate su strutture non lo sono

void funcv(ar) int ar / ar viene
convertito in puntatore ad intero / void
funcv(ar) int ar / ar è un puntatore ad
intero /
void funcs(st) struct tag st / st è una
struttura completa / void funcs1(st) struct
tag st / st è un puntatore a struttura /
24
25
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 allesterno più
    di un valore

25
26
Strutture restituite da funzioni ? 2
?include ltstdio.hgt ?include ltmath.hgt ?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 gt
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)
26
27
Lassegnamento 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
27
28
Le unioni ? 1
  • Le unioni consentono agli elementi di sovrapporsi
    luno sullaltro per condividere la stessa area
    di memoria
  • Esempio
  • Il compilatore riserva sempre una quantità di
    memoria sufficiente allelemento più grande e
    tutti gli elementi iniziano allo stesso indirizzo

typedef union struct char c1, c2
s long j float x U
28
29
Esempio sulle unioni ? 1
  • I dati viaggiano sulla linea un byte alla volta
    le unioni consentono di raggruppare i byte in
    modo tale che i dati 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()

29
30
Esempio sulle unioni ? 2
  • I caratteri ricevuti vengono memo-rizzati in
    elementi successivi di c il valore del numero
    double si ottiene accedendo al campo val
    dellunione
  • Laccesso ai campi di ununione non ha impatto
    alcuno sui bit contenuti in memoria (non si
    effettuano conversioni di tipo) il compilatore
    interpreta in modo diverso gli stessi bit

union doub char c8 double
val double get_double() extern char
get_byte() int j union doub d for
(j?0 jlt8 j??) d.cj ? get_byte()
return d.val
30
31
Le liste concatenate
31
32
Allocazione dinamica ? 1
  • 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, lutilizzo di array può essere
    estremamente oneroso, perché rende necessaria
    lallocazione 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

32
33
Allocazione dinamica ? 2
  • La soluzione consiste nellallocare memoria in
    modo dinamico, con malloc() o calloc() ? che,
    tuttavia, non garantiscono la contiguità fisica
    per elementi logicamente contigui ? e
    nellutilizzare liste concatenate
  • Il modo più comune per garantire la contiguità
    logica di strutture allocate dinamicamente è
    infatti luso delle liste semplicemente/doppiament
    e concatenate

33
34
Le liste concatenate ? 1
  • In una lista concatenata, ogni struttura contiene
    un elemento aggiuntivo (un puntatore) che punta
    alla struttura successiva
  • Esistono liste semplici e liste doppiamente
    concatenate, in cui ogni struttura possiede due
    puntatori, rispettivamente allelemento
    precedente ed al successivo

typedef struct vitalstat char vs_name20,
vs_fiscode16 unsigned int vs_day,
vs_month, vs_year
struct vitalstat next VITALSTAT
34
35
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
    indipen-denti dal contenuto informativo delle
    strutture (dai campi dati) e possono essere
    formulate in modo generale

35
36
La creazione di un elemento ? 1
  • Per creare un elemento di una lista, è
    sufficiente riservare memoria per la struttura e
    restituire un puntatore allarea allocata

?include v_stat.h ?include ltstdlib.hgt 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 ?gt
next ? NULL return p
Alloca la memoria ad un elemento della lista, ma
non lo collega alla lista stessa
36
37
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
  • ELEMENT diviene un sinonimo di struct vitalstat
  • Per dichiarare il puntatore occorre usare
    unetichetta 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

?define NULL (void ) 0 typedef struct vitalstat
ELEMENT
37
38
Laggiunta di un nuovo elemento ? 1
?include v_stat.h static ELEMENT head void
add_element(e) ELEMENT e ELEMENT p /
se il primo elemento non esiste, viene creato
/ if (head ?? NULL) head ? e
return / altrimenti, trova lultimo
elemento / for (p?head p?gtnext !? NULL
p?p?gtnext) / istruzione vuota /
p ?gt next ? e
  • La variabile head è un puntatore allinizio della
    lista ed è dichiarata con ambito di visibilità a
    li-vello di file, per renderla disponibile a più
    funzioni
  • Nel ciclo for, la scan-sione della lista è basata
    sul controllo del valore di p-gtnext se è
    diver-so da NULL, esiste un elemento successivo,
    al-trimenti è stata rag-giunta la fine della
    lista

38
39
Laggiunta di un nuovo elemento ? 2
  • Lassegnamento
  • p?gtnext ? e
  • aggiunge una nuova struttura alla fine della
    lista
  • Largomento 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 jlt10 j??)
add_element(create_list_element())
39
40
Linserimento di un elemento
  • Per inserire un elemento in una lista
    concatenata, deve essere specificata la posizione
    in cui deve avvenire linserimento

?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?gtnext ?? p))
printf(insert_after argomenti errati.\n)
return p ?gt next ? q ?gt
next q ?gt next ? p
40
41
La cancellazione di un elemento ? 1
  • Per la cancellazione di un elemento da una lista
    concatenata, occorre individuare lelemento che
    precede quello da eliminare per riallacciare i
    puntatori della lista dopo leliminazione
  • Inoltre, è necessario utilizzare la funzione
    free() per rilasciare la memoria dellelemento
    eliminato

41
42
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?gtnext else for
(p?head(p!?NULL) (p?gtnext!?goner)p?p?gtnext)
/ istruzione vuota /
if (p ?? NULL)
printf(delete_element elemento non contenuto
nella lista.\n) return
p?gtnext ? p?gtnext?gtnext
free(goner)
Loperatore freccia destra ha associatività
sinistra e pertanto lespressione p?gtnext?gtnext vi
ene valutata come (p?gtnext)?gtnext
42
43
La ricerca di un elemento ? 1
  • 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 largomento della funzione

43
44
La ricerca di un elemento ? 2
?include v_stat.h ?include ltstring.hgt static
ELEMENT head ELEMENT find(aname) char
aname ELEMENT p for (p
? head p !? NULL p ? p?gtnext) if
(strcmp(p?gtvs_name, aname)??0)
return p return NULL
44
45
Costruzione di una lista ordinata ? 1
/ Letta in input una sequenza di numeri
interi la memorizza in una lista in ordine
crescente. / include ltstdlib.hgt include
ltstdio.hgt / struttura per la
rappresentazione dei nodi della lista /
struct nodo int info struct nodo
next
/ Funzione principale. / main(void)
struct nodo primo primo?leggi_lista_ordin
ata() stampa_lista(primo) exit(0)
45
46
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. / struct nodo
leggi_lista_ordinata(void) struct nodo
p, p1, primo, prec int i, n, num
primo NULL printf(Inserire numero di
elementi ) scanf(d, n) for (i?0
iltn i??) scanf(d, num)
p ? malloc(sizeof(struct nodo))
p-gtinfo ? num p1 ? primo prec
? NULL
while((p1!?NULL)(p1-gtinfoltp-gti
nfo)) prec ? p1 p1 ?
p1-gtnext if (prec !? NULL)
prec-gtnext ? p else primo ?
p p-gtnext ? p1 return(primo)

46
47
Costruzione di una lista ordinata ? 3
/ Stampa la lista, a partire dallelemento
puntato dal puntatore p, ricevuto come
parametro. / void stampa_lista(p) struct
nodo p while (p !? NULL)
printf(d ---gt , p-gtinfo) p ?
p-gtnext printf(NULL\n) return

47
Write a Comment
User Comments (0)
About PowerShow.com