Il linguaggio C Le strutture Le unioni Le liste concatenate C Language

Slides:



Advertisements
Presentazioni simili
Puntatori Linguaggio C.
Advertisements

Introduzione al linguaggio C++
I tipi Strutturati.
LINGUAGGIO DI PROGRAMMAZIONE C
Stringhe di caratteri In linguaggio C.
PUNTATORI Introduzione
File System Cos’è un File System File e Directory
Algoritmi e Programmazione
Informatica Generale Marzia Buscemi
1 Informatica Generale Susanna Pelagatti Ricevimento: Mercoledì ore presso Dipartimento di Informatica, Via Buonarroti,
Fondamenti di Informatica I CDL in Ingegneria Elettronica - A.A CDL in Ingegneria Elettronica - A.A Strutture dati dinamiche.
Fondamenti di Informatica I CDL in Ingegneria Elettronica - A.A CDL in Ingegneria Elettronica - A.A Strutture dati dinamiche.
Introduzione al linguaggio C
Introduzione al linguaggio C Dr. Francesco Fabozzi Corso di Informatica.
Anno accademico Le classi di memorizzazione.
Le strutture e le unioni in C
Fondamenti di Informatica I a.a Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.
Anno accademico Array e puntatori in C.
Programmazione Procedurale in Linguaggio C++
Indirizzi delle variabili A ogni variabile sono associati tre concetti fondamentali: il valore memorizzato; il tipo dati di appartenenza; lindirizzo. Il.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Caratteri e stringhe di caratteri
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
1 FONDAMENTI DI INFORMATICA II Ingegneria Gestionale a.a ° Ciclo Liste.
Funzioni definite dall’utente
Fondamenti di Informatica II Ingegneria Informatica (A-I) Prof. M.T. PAZIENZA a.a – 3° ciclo.
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 21 Marzo 2013.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 4 Aprile 2013.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Stringhe e Puntatori Marco D. Santambrogio – Ver. aggiornata al 18 Marzo 2013.
Process synchronization
Laboratorio di Linguaggi lezione III Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso di Laurea.
Laboratorio di Linguaggi P R I M O C O M P I T I N O Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese.
1 Corso di Laurea in Biotecnologie Informatica (Programmazione) Introduzione a JAVA Anno Accademico 2009/2010.
1 Corso di Laurea in Biotecnologie Informatica (Programmazione) Array Anno Accademico 2009/2010.
1 Corso di Informatica (Programmazione) Lezione 13 (21 novembre 2008) Programmazione in Java: stringhe e array.
Fondamenti di Informatica I a.a Il linguaggio C Il controllo di flusso La selezione condizionale Listruzione switch I cicli Le istruzioni break,
Approfondimento delle classi
A.A. 2010/2011Ambienti di Programmazione per il Software di Base1 (Es. – 6) Ambienti di Programmazione per il Software di Base Le Stringhe in C Input.
Struct, enum, Puntatori e Array dinamici
Strutture di controllo in C -- Flow Chart --
Politecnico di Milano Esercizi Stringhe Ricerca binaria.
Esercizi Puntatori, struct con campi puntatore, puntatori a struct, rapporto tra array e puntatori. FUNZIONI Passaggio di parametri per indirizzo, passaggio.
I File.
Le funzioni.
Espressioni condizionali
Java base I: Sintassi e tipi di dati
2000 Prentice Hall, Inc. All rights reserved. Capitolo 6 (Deitel) I vettori Sommario Introduzione Vettori Dichiarazione di vettori 6.4.
1 ListaDiElem Cancella( ListaDiElem lista, TipoElemento elem ) { ListaDiElem puntTemp; if( ! ListaVuota(lista) ) if( lista–>info == elem ) { puntTemp =
CODIFICA Da flow-chart a C++.
2000 Prentice Hall, Inc. All rights reserved. Capitolo 10 (Deitel) Strutture, unioni ed enumerazioni Sommario Introduzione Definire le strutture.
Il linguaggio C Le funzioni C Language Il passaggio dei parametri
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.
Unità Didattica 3 Linguaggio C
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Array e stringhe Marco D. Santambrogio – Ver. aggiornata al 9 Agosto 2013.
Fopndamenti di programmazione. 2 La classe String Una stringa è una sequenza di caratteri La classe String è utilizzata per memorizzare caratteri La classe.
1Piero Scotto - C14. Finalità del corso Programma Materiale Requisiti Spendibilità 2Piero Scotto - C14.
Sviluppare un programma in C che, dato un array da 100 elementi interi caricato con numeri casuali compresi tra [10,100], sia in grado di cercare il valore.
Complessità di un algoritmo
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Corso di Programmazione 1 a.a.2006/2007 Prof.ssa Chiara Petrioli Corso di Laurea.
CORSO DI PROGRAMMAZIONE II Lezione 22
Prof.ssa Chiara Petrioli -- corso di programmazione 1, a.a. 2006/2007 Corso di Programmazione 1 a.a.2006/2007 Prof.ssa Chiara Petrioli Corso di Laurea.
Fondamenti di Informatica II Ingegneria Informatica / Automatica (A-I) Meccanica Prof. M.T. PAZIENZA a.a – 3° ciclo.
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
Fondamenti di Informatica II Ingegneria Informatica (A-I) Prof. M.T. PAZIENZA a.a – 3° ciclo.
1 Il linguaggio C Precisazioni sull’esperienza in laboratorio.
Operatori di incremento e decremento
Copyright © Istituto Italiano Edizioni Atlas
13. Strutture dati dinamiche Ing. Simona Colucci Informatica - CDL in Ingegneria Industriale- A.A
Transcript della presentazione:

Il linguaggio C Le strutture Le unioni Le liste concatenate C Language Allocazione dinamica Creazione e aggiunta di un nuovo elemento alla lista Inserimento e cancellazione di elementi La ricerca di un elemento C Language

Le strutture

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)

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

Le strutture  2 Possibile soluzione: memorizzare le informazioni in variabili distinte 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 Le informazioni relative ad una persona sono sparse per la memoria char name[20], fiscode[16]; short day, month, year;

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_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 vs_name[] vs_fiscode[] vs_day[] vs_month[] vs_year[]

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 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 struct vitalstat vsa[1000], *pvs; pvs  &vsa[10];

Le strutture  5 Il tipo VITALSTAT rappresenta l’intera struttura, compresa la parola chiave struct typedef struct { char vs_name[20], vs_fiscode[16]; short vs_day, vs_month, vs_year; } VITALSTAT; Il nome di tipo è scritto maiuscolo, per distinguerlo dai nomi di etichette e variabili Un’etichetta o un typedef consentono di definire una sola volta lo schema di una struttura, per dichiarare variabili del tipo struttura quando necessario Le dichiarazioni di struttura sono normalmente raggruppate in file header, così da poter essere accedute da più file sorgente

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 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 VITALSTAT vs  {“Marco Rossi”, “MRCRSS89C23D612K”, 23, 3, 1989 }; typedef struct { int a; float b; } s  {1, 1.0}; /* non ammesso */

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 L’operatore > è una forma abbreviata per accedere all’indirizzo contenuto nel puntatore e quindi applicare l’operatore punto VITALSTAT *pvs; … … … pvs>vs_day  23; pvs>vs_month  3; pvs>vs_year  1989; vs.vs_day  23; vs.vs_month  3; vs.vs_year  1989; pvs>vs_day è equivalente a (*pvs).vs_day

Gli array di strutture Gli array di strutture vengono dichiarati facendo precedere al nome dell’array 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 introdotte 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&vsa[size]; for (; p<p_last; p) agecurrent_year  p>vs_year; if ((age > low_age) && (age < high_age)) count; } return count;

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; char vs_name[20], vs_fiscode[16]; DATE vs_birth_date; } VITALSTAT; 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 vs.vs_birth_date.vs_year

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 event[20]; } CALENDAR; CALENDAR holiday  {{25, 12, 2009}, “Natale”};

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; };

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;

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 mem1 mem2 mem3 spazio vuoto Allocazione con restrizioni di allineamento Allocazione senza restrizioni di allineamento 1000 1001 1003 1002 1004 struct align_examp { char mem1; short mem2; char mem3; } s1;

L’allineamento 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 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 struct align_examp { char mem1, mem3; short mem2; } s1;

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 nell’area di memoria degli argomenti, mentre il passaggio per valore richiede la copia dell’intera struttura VITALSTAT vs; … … … func1(vs); /* Passaggio per valore */ func2(&vs); /* Passaggio per indirizzo */

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 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) func1(vs) VITALSTAT vs; /* l’argomento è * una struttura */ func2(pvs) VITALSTAT *pvs; /* l’argomento è un * puntatore a * struttura */

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 */

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: Le due versioni basate su strutture non lo sono: funcv(ar) int ar[]; /* ar viene convertito in puntatore ad intero */ funcv(ar); int *ar; /* ar è un puntatore ad intero */ funcs1(st) struct tag st; /* st è una struttura completa */ funcs2(st); struct tag *st; /* st è un puntatore a struttura */

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

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

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;

Le unioni

Le unioni  1 Le unioni consentono agli elementi di sovrapporsi l’uno sull’altro per condividere la stessa area di memoria Esempio: Il compilatore riserva sempre una quantità di memoria sufficiente all’elemento più grande e tutti gli elementi iniziano allo stesso indirizzo 1000 1001 1002 1004 typedef union { struct char c1, c2; } s; long j; float x; } U; c1 c2 j x

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

Esempio sulle unioni  2 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 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; }

Le liste concatenate

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

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 Esistono liste semplici e liste doppiamente concatenate, in cui ogni struttura possiede due puntatori, rispettivamente all’elemento precedente ed al successivo 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

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

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> 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; Alloca la memoria ad un elemento della lista, ma non lo collega alla lista stessa

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 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 define NULL (void *) 0 typedef struct vitalstat ELEMENT;

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; 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

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()); }

L’inserimento di un elemento Per inserire un elemento in una lista concatenata, deve essere specificata la posizione in cui deve avvenire l’inserimento prima q 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; dopo q q>next>next p

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

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); L’operatore freccia destra ha associatività sinistra e pertanto l’espressione p>next>next viene valutata come (p>next)>next

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; 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; }

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; }; /* * Funzione principale. */ main(void) { struct nodo *primo; primo  leggi_lista_ordinata(); stampa_lista(primo); exit(0); }

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; i<n; i) scanf(“%d”, &num); p  malloc(sizeof(struct nodo)); p->info  num; p1  primo; prec  NULL; while ((p1 ! NULL) && (p1->info < p->info)) prec  p1; p1  p1->next; } if (prec ! NULL) prec->next  p; else primo  p; p->next  p1; return(primo);

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;