Laurea In Ingegneria dell Informazione. Esercitazioni Guidate di Tecniche della Programmazione

Documenti analoghi
Esercitazioni di Tecniche di Programmazione

3. Terza esercitazione autoguidata: progetto gestione voli

Tecniche della Programmazione lezione 17

Rappresentazione di dati

Rappresentazione di dati

Laurea In Ingegneria dell Informazione. Esercitazioni Guidate di Tecniche della Programmazione

- tipo - costruttori di tipo - typedef: alias per i nuovi tipi

Esercizio (o esempio?)

Esercitazioni di Tecniche di Programmazione. 4. Quarta esercitazione autoguidata: liste concatenate rappresentate mediante struct e puntatori

5. Quinta esercitazione autoguidata: liste semplici

Tecniche della Programmazione, lez.28

Strutture. Array dei nomi degli esami (MAX ESAMI è il massimo numero degli esami). Array con i crediti degli esami.

APPELLO SCRITTO DI PROGRAMMAZIONE 1 CORSO DI LAUREA IN MATEMATICA UNIVERSITÀ DEGLI STUDI DI MILANO II.2017

Esercitazioni di Tecniche di Programmazione. 6. Sesta esercitazione autoguidata: file binari e ricorsione

Laurea In Ingegneria dell Informazione. Esercitazioni Guidate di Tecniche della Programmazione

Introduzione al linguaggio C Puntatori

Esercizio 1. Tavola ordinata in memoria centrale

Informatica per Statistica Riassunto della lezione del 21/10/2011

Esercizio 1: media di numeri reali (uso funzioni e struct)

C: panoramica. Violetta Lonati

Esercitazione 11. Liste semplici

Le classi in java. Un semplice programma java, formato da una sola classe, assume la seguente struttura:

I Dati Strutturati ed il Linguaggio C

Stringhe e allocazione dinamica della memoria

Esercizi. Filtraggio

Informatica B Allievi Meccanici con cognome da Cl a L II prova intermedia del 13/02/01 Prof. Elisabetta Di Nitto

Esercitazioni di FONDAMENTI DI INFORMATICA MODULO B

Dati due punti sul piano calcolare la loro distanza

Lo scopo. Il primo esperimento. Soluzione informale. Le variabili

Strutture dati dinamiche in C. Emilio Di Giacomo

APPELLO SCRITTO DI PROGRAMMAZIONE 1 CORSO DI LAUREA IN MATEMATICA UNIVERSITÀ DEGLI STUDI DI MILANO VI.2015

Informatica A (per gestionali) A.A. 2004/2005. Esercizi C e diagrammi a blocchi. Preparazione prima prova intermedia

INTRODUZIONE ALLA PROGRAMMAZIONE AD ALTO LIVELLO IL LINGUAGGIO JAVA. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica

INTRODUZIONE ALLA PROGRAMMAZIONE AD ALTO LIVELLO IL LINGUAGGIO JAVA. Fondamenti di Informatica - Programma

Lab 13 Strutture e programmi su più file "

Laboratorio di Informatica I

Le strutture. UNIVERSITÀ DEGLI STUDI DEL SANNIO Benevento DING DIPARTIMENTO DI INGEGNERIA

Lezione 6: Array e puntatori

Laboratorio. Due. 1) Switch 2) Costrutti Iterazione (For, While, do while)

L AMBIENTE CODE BLOCKS E L IO

9 - Array. Programmazione e analisi di dati Modulo A: Programmazione in Java. Paolo Milazzo

Le Funzioni in C. Fondamenti di Informatica Anno Accademico 2010/2011. Corso di Laurea in Ingegneria Civile Politecnico di Bari Sede di Foggia

Corso di Informatica

Variabili e Funzioni. Informatica 1 / 19

Lab 09 Strutture e programmi su più file

Elementi lessicali. Lezione 4. La parole chiave. Elementi lessicali. Elementi lessicali e espressioni logiche. Linguaggi di Programmazione I

Titolo presentazione INFORMATICA. sottotitolo A.A Milano, XX mese 20XX Laboratorio n 6 Ing. Gian Enrico Conti Dott.

Esercizi. La funzione swapint() primo tentativo

La copia di un file. contare di quanti caratteri sia composto il file (e quindi determinare la dimensione del file di origine)

Debug di un programma

Ingresso ed Uscita in C. Informatica 1 / 15

Esercizio 2 (punti 7) Dato il seguente programma C: #include <stdio.h> int swap(int * nome, int length);

L AMBIENTE CODE BLOCKS E L IO

STRUTTURE DI CONTROLLO DEL C++

Implementazione dell albero binario in linguaggio C++

Algoritmi di Ricerca. Esempi di programmi Java. Prof. Angela Bonifati

L'Allocazione Dinamica della Memoria nel linguaggio C

Variabili e input/ Alessandra Giordani Lunedì 18 marzo

Passare argomenti al programma

Laboratorio di Algoritmi e Strutture Dati

Dati aggregati. Violetta Lonati

giapresente( ) leggi( ) char * strstr(char * cs, char * ct) NULL

Laboratorio di Programmazione 1. Docente: dr. Damiano Macedonio Lezione 5 31/10/2013

Laboratorio di Programmazione: Linguaggio C Lezione 21 del 19 maggio 2014

Lezione 23 - ADT LISTA

Tipi di dato, variabili, istruzioni

Assegnazione di una variabile

Perché il linguaggio C?

Esercitazione 4. Comandi iterativi for, while, do-while

Passaggio dei parametri Per valore Il valore viene copiato dall environment esterno all environment della funzione o procedura Cambiamenti dei paramet

Esercizio 1: funzione con valore di ritorno di tipo puntatore

Algoritmi di Ricerca. Esempi di programmi Java

Esercitazioni di Fondamenti di Informatica - Lez. 4 23/10/2018

Passaggio dei parametri. Passaggio dei parametri

Nella propria home directory creare una sottodirectory chiamata es08, in cui metteremo tutti i file C di oggi.

Ogni parte non cancellata a penna sarà considerata parte integrante della soluzione.

Puntatori e array. Violetta Lonati

Perché il linguaggio C?

APPELLO SCRITTO DI PROGRAMMAZIONE 1 CORSO DI LAUREA IN MATEMATICA UNIVERSITÀ DEGLI STUDI DI MILANO VII.2019

Gli array. impone al programma, in fase di esecuzione, di riservare dello spazio in memoria per 10 variabili di tipo int

Implementazione di DFA in C

Dispensa 18 CORSO DI PROGRAMMAZIONE A.A CORSO DI LAUREA IN INGEGNERIA E SCIENZE INFORMATICHE CESENA. Laboratori

Progetto per il Laboratorio di Programmazione Un interprete per il linguaggio PINO. Modulo I: Le tavole dei simboli (TS)

7. Settima esercitazione autoguidata: alberi binari

Indovina la lettera...

C: primi elementi. Lezione 4

Laboratorio 1. 2) All interno della directory c:\temp\cognome\codici creare il file sorgente hello.c contenente il seguente codice:

INFORMATICA A. Titolo presentazione sottotitolo. Laboratorio n 4 Dott. Michele Zanella Ing. Gian Enrico Conti

Liste concatenate e allocazione dinamica

Le basi del linguaggio Java

Il linguaggio C. Puntatori e dintorni

Fondamenti Teorici e Programmazione

Quadrato Magico. Fondamenti di Programmazione

Laboratorio di Informatica

Esame Laboratorio di Programmazione

Transcript:

Laurea In Ingegneria dell Informazione Esercitazioni Guidate di Tecniche della Programmazione Note introduttive: 1) Le soluzioni agli esercizi e le versioni di programmi menzionate nel testo delle esercitazioni sono raggiungibili tramite la pagina web del corso. Nel titolo di ogni sezione di questo documento è specificato tra parentesi il nome del (o dei) file in cui è proposta una soluzione (se disponibile...). 2) I programmi che scriveremo dovranno essere in accordo con la definizione standard ANSI C del linguaggio C; perciò, prima di cominciare vogliamo assicurarci che l ambiente di programmazione che usiamo usi anche lui la medesima definizione. 3) Così, se si usa il Dev C++, ad esempio nella versione 4.9.9.2 (lingua inglese) bisogna andare nel menu Tools, selezionare Compiler Options, scegliere Settings e poi C Compiler (selezionare almeno Support all ANSI Standard C Programs ). 4) In questo blocco abbiamo due EG: la 6 sulle strutture, e la 7 relativa all esercizio Gestione Voli 6. Esercitazione Guidata 6 6.1. Uso di struct (punto.c, punto2.c). Scrivere un programma in cui - sia definito il tipo struct punto adatto a rappresentare i punti colorati nel piano cartesiano (due dimensioni); - vengano lette coordinate e colori di due punti e venga costruito il punto intermedio, stampandone i dati (il punto intermedia ha il medesimo colore dei due punti letti, se questi hanno il medesimo colore; altrimenti ha colore NERO ). Scrivere poi il medesimo programma, in cui il tipo dei punti colorati sia TipoPunto, definito mediante typedef ed usato nelle dichiarazioni dei punti usati nel programma. 6.2. Uso di struct (distanze.c). Scrivere un programma in cui viene letta una sequenza di punti colorati (definiti come negli esercizi precedenti) e, per ogni punto letto, dal secondo in poi, viene stampata la distanza colorata tra esso e il precedente. Ci sono dei colori prestabiliti come ammissibili: bianco, rosso, giallo, celeste, blu, NERO Quando viene letto il colore di un punto, se questo e al di fuori dei colori prestabiliti, sara considerato NERO. 1

La distanza colorata tra due punti e definita come la coppia <dl, dc>, dove - dl=distanza lineare tra i due punti e - dc=distanza tra i colori dei due punti (stabilita in base alla definizione dei colori prestabiliti data in precedenza: ad es. la distanza tra bianco e rosso e 1, quella tra bianco e giallo e 2, quella tra giallo e nero e 3). Qualche suggerimento per la soluzione segue: non li leggete tutti d un fiato... Suggerimento 0 Quando il programma compila, probabilmente siamo solo a meta dell opera. Provare il programma anche usando le funzionalita di debugging: debugging? What s debugging?? - la linea rossa che si vede in figura e una linea su cui e stato impostato un breakpoint (basta cliccare accanto alla linea per impostare il breakpoint o per rimuoverlo). - Un breakpoint nel punto indicato e utile: cosi possiamo scegliere l opzione di compilazione con debug (F8) e usare F7 (Next Step) per far avanzare l esecuzione del programma passo passo (un istruzione alla volta). - Durante l esecuzione passo passo e utile tener d occhio il contenuto di alcune variabili significative: in figura si vede che e stata impostata la visualizzazione del contenuto delle variabili p1, p2, dc: e stato usato il comando Add Watch. (Nell aggiungere una nuova watch, puo essere necessario eseguire il passo successivo F7 prima di vederla effettivamente.). - La figura mostra un momento dell esecuzione in cui tutte le istruzione di lettura del punto p1 sono state eseguite (la watch su p1 mostra quei valori: 1, 5, rosso). - Se una watch corrisponde a variabili non nello scope dell istruzione in esecuzione, cio viene indicato (ad esempio nel punto del programma in esecuzione non potremmo vedere il contenuto della variabile i definita nella funzione coloreprestabilito(). - Quando e in esecuzione un istruzione di lettura, bisogna andare nella finestra di esecuzione e inserire il dato da leggere 2

- Se non si vuole piu procedere passo passo, Shift F7 (Continue) procura l avanzamento dell esecuzione fino alla prossima occorrenza di un breakpoint. Suggerimento 1di5 la struttura del TipoPunto e quella gia vista; inoltre potrebbe convenire dare una definizione di un tipo apposito per la DistanzaColorata. (una struct con un campo double per la distanza lineare e uno int per la distanza tra i colori. Inoltre e bene che sia data una chiara definizione dei colori prestabiliti. Questa potrebbe anche non essere la definizione di un tipo vero e proprio. Una possibilita e quella di usare un array top level di stringhe inizializzato opportunamente COLORI[]={bianco, rosso, giallo, celeste, blu, nero}. 3

Suggerimento 2di5 All array COLORI potrebbe essere affiancata una funzione coloreprestabilito che, ricevendo un colore, col, dica se col e o no uno di colori ammessi. Nella soluzione proposta questa e una funzione intera che restituisce 1 se col non e ammissibile, oppure l indice di col nell array COLORI. Suggerimento 3di5 La funzione coloreprestabilito (sempre nella soluzione proposta) viene usata anche per calcolare lo seconda parte della distanza colorata (infatti se il colore di p1 e k1 e il colore di p2 e k2, la distanza tra i colori sara k1-k2 o k2-k1...) Suggerimento 4di5 Schema del programma - lettura primo punto (p1) - ciclo del tipo while (continua!=0) {... } con richiesta finale all utente di inserire 1 se vuole continuare o 0 se vuole terminare (scelta che viene letta in continua). Suggerimento 5di5 4

- durante ogni iterazione del ciclo o si legge il punto p2 (si leggono le sue coordinate e colore) o si calcola la distanza colorata tra p1 e p2 (e la si stampa) o l utente indica la sua scelta (se continuare o meno) e di conseguenza viene assegnata la variabile continua. o Infine viene copiato p2 in p1, così in p1 ci sarà l ultimo punto letto da input, e se ne potrà calcolare la distanza da quello successivamente inserito 6.3. Funzioni che ricevono e/o restituiscono struct (punto3.c). Riscrivere il programma del punto 1.1, definendo ed usando le seguenti funzioni: /*funzione che riceve un punto e lo stampa */ void stampapunto(struct Punto p) /* funzione che riceve due punti e ne restituisce il punto medio */ struct Punto puntomedio(struct Punto pr, struct Punto sec) 6.4. Funzioni che ricevono puntatori a struct (punto4.c). Scrivere un programma che soddisfi i seguenti requisiti: - il programma legge i dati relativi a due punti colorati (definiti come in precedenza) - il programma calcola e stampa i dati relativi al punto medio tra i due letti da input; - poi il programma chiede in input un colore e assegna tale colore a tutti e tre i punti, stampandone successivamente i dati in output. Il programma deve far uso delle funzioni definite nell esercizio precedente e della funzione void cambiacolorea(tipopunto *p, char col[]) che, ricevendo un punto (o meglio, il suo indirizzo), e un colore (col), modifica il punto assegnandogli col come colore. Suggerimento: conviene prendere come punto di partenza il programma fatto per l esercizio precedente, aggiungendo la nuova funzione e modificando opportunamente la main(). 5

6.5. Funzioni che ricevono puntatori a struct (punto5.c). Ripetere l esercizio del 2.3, definendo e utilizzando, per la lettura di ciascun punto, una funzione leggipunto(...) Suggerimento 1di2: la funzione deve ricevere un punto e riempirlo con dati letti da input. Suggerimento 2di2: quindi la funzione deve ricevere l indirizzo del punto da riempire. 6.6. Funzioni che restituiscono puntatori a struct (punto6.c). Rifacendosi a quanto fatto in precedenza, scrivere una funzione creapuntomedio(...) che, ricevendo due punti, restituisce una struct appositamente allocata dinamicamente, contenente la rappresentazione del punto medio tra i due parametri. Suggerimento 1di2: Si tratta di rifare l esercizio precedente, ma sostituendo la funzione puntomedio con quella qui richiesta (che restituisce un puntatore a struct Punto e non una struct Punto. Suggerimento 2di2: ecco uno stralcio del programma PUNTO6.C in cui si vede come viene usata la funzione creapuntomedio: int main(){ TipoPunto p1, p2, *pm; /* puntatore per il punto medio */ printf("primo punto:"); leggipunto(&p1); printf("secondo punto:"); leggipunto(&p2); pm = creapmedio(p1, p2); /* la chiamata a pmedio restituisce il puntatore ad una struct che e' stata allocata appositamente, e che rappresenta il punto medio tra p1 e p2 */ printf(" - adesso i tre punti sono:\n - p1 = "); 6

6.7. Quadrilateri (quadri.c). L oggetto di questo esercizio e un programma capace di gestire quadrilateri dati in input. Un quadrilatero viene specificato come l insieme dei suoi quattro vertici, che sono punti colorati sul piano (cioe variabili del tipo TipoPunto definito precedentemente). Supponiamo che i punti dati in input siano tutti distinti e diano luogo ad una figura in cui i lati sono a 90 gradi. Cio assunto, il programma - costruisce un quadrilatero allocando dinamicamente un array di quattro punti e leggendo i dati relativi ai quattro vertici; - verifica se il quadrilatero e un quadrato - verifica se il quadrilatero e isotetico, cioe i suoi lati sono paralleli agli assi cartesiani; - stampa i dati dei quattro vertici e stampa un messaggio in cui sia specificato se il quadrilatero e o no un quadrato ed e o no isotetico. Se quad e l identificatore usato per il quadrilatero nel programma, si assume anche che i punti siano distribuiti come nel disegno qui sotto: quad[0] quad[1] +-------------+ +-------------+ quad[3] quad[2] Usare nel programma le seguenti funzioni: - void stampapunto(tipopunto ) (per stampare i dati di un punto passato per parametro) - void leggipunto( TipoPunto *) (per leggere un punto) - void leggiquadrilatero(tipopunto q[4]) (per leggere l intero quadrilatero, usando leggipunto); - void stampaquadrilatero(tipopunto q[4]) (per stampare i dati del quadrilatero, ad esempio come sequenza dei punti che ne sono vertici); - double lunghezza(tipopunto primo, TipoPunto secondo) (per calcolare la distanza tra due punti) Suggerimento 1di2: 7

per verificare che il quadrilatero quad sia un quadrato basta verificare che siano uguali le misure dei suoi lati (cioe' delle distanze tra vertici consecutivi: quad[0]--quad[1], quad[1]-- quad[2], quad[2]--quad[3], quad[3]--quad[0],). Per calcolare la lunghezza del lato quad[k]quad[h] si usa la funzione lunghezza(...). Suggerimento 2di2: per verificare che i lati sono paralleli agli assi, bisogna verificare che i lati - quad[0]--quad[1] e quad[2]--quad[3] sian paralleli all'asse delle ascisse - quad[1]--quad[2] e quad[3]--quad[0] sian paralleli all'asse delle ordinate. 8

7. Esercitazione Guidata 7 Qui ci occupiamo di scrivere un programma abbastanza lungo, dedicato alla gestione di una tabella di dati. Una tabella e una struttura dati che rappresenta all interno di un programma, un archivio di dati del mondo reale. 7.1. Cos e una tabella (in breve...) Di solito la tabella viene definita per permettere la gestione automatizzata di una collezione di dati strutturati (dati composti da varie informazioni di tipo disomogeneo e quindi normalmente rappresentati mediante struct). Un esempio di tabella e l elenco telefonico (una collezione di elementi; ciascu elemento e l insieme di dati relativi ad una persona, come il nome, l indirizzo, il numero di telefono, titoli professionali etc...). Un altro esempio e l elenco degli iscritti ad una associazione (anche qui ogli elemento in tabella e una collezione di dati relativi ad una persona, come il nome e indirizzo, ma anche l anzianita d iscrizione, la quota associativa pagata etc...). Le funzioni generiche di gestione di una tabella sono - l aggiunta di un elemento nella tabella, - l eliminazione di un certo elemento, - la modifica dei dati memorizzati in un un certo elemento - e la ricerca di un certo elemento tra quelli memorizzati nella tabella. Di solito uno dei dati memorizzati in ciascun elemento lo caratterizza univocamente e permette di distinguere quell elemento da tutti gli altri: ad esempio il codice fiscale permette di specificare una certa persona; la matricola permette di indicare univocamente uno degli associati al club, etc... Questi dati caratteristici vengono denominati chiavi di ricerca, o piu brevemente, chiavi, e vengono usati quando si stanno effettuando operazioni di ricerca e selezione di un certo elemento nella tabella. 7.2. Gestione voli (primo passo VOLI1.C) Il programma deve permettere la gestione di un archivio contenente informazioni sui voli aerei di un certo giorno. Un volo e' caratterizzato da o codice (5 caratteri alfanumerici) o destinazione (stringa di caratteri) o ora di partenza (ore, minuti: due interi) o numero di posti attualmente liberi (un intero) La tabella dei voli di quel giorno e una collezione di voli (informazioni su voli) su cui e possibile eseguire le seguenti operazioni di gestione: - stampare un volo della tabella, caratterizzato da un certo codice - stampare i voli della tabella - aggiungere un volo alla tabella - eliminare un volo avente caratterizzato da un certo codice - modificare l'ora di partenza di un volo caratterizzato da un certo codice 9

- prenotare k posti in un volo caratterizzato da un certo codice (cioe' modificarne il numero di posti liberi, diminuendolo, se possibile, di k) - memorizzare i dati di una tabella di voli in un file di voli - caricare nella tabella dati da un file di voli Si vede che in questa tabella il campo codice e' la chiave di ricerca per i voli memorizzati. Scrivere un abbozzo del programma che dovra permettere tutte le operazioni sopra indicate. In questo abbozzo di programma ci limitiamo a fornire - la definizione della struttura dati che useremo per rappresentare la tabella dei voli; - la dichiarazione e implementazione (programmazione) delle funzioni necessarie a realizzare le prime tre operazioni elencate sopra; - una funzione main in cui venga stampato un menu di scelte (stampa di un volo, stampa dei voli in tabella, aggiunta di un volo in tabella, termine programma) e vengano conseguentemente usate le funzioni definite. Il programma va scritto e testato. Una proposta di soluzione e in VOLI1.C. Suggerimento 1di3: (sulle strutture dati, tratto da VOLI1.C) tabelle di 10 voli, per scrivere e testare il programma. Dopo potremo cambiare questa dimensione #define MAXVOLI 10 il tipo struct per rappresentare un volo contiene un campo orapartenza. L'ora e' ben rappresentabile con un'altra struct struct ora { int ore, minuti; }; segue il volo 10

struct volo { char codice[6]; char * destinazione; struct ora orapartenza; int postiliberi; }; per i voli, decidiamo di definire un sinonimo di tipo typedef struct volo TipoVolo; /* la tabella di voli consiste di un array di MAXVOLI voli, ma anche di un intero quantivoli che in ogni momento specifica quanti sono i voli effettivamente presenti in tabella. Faremo in modo che, se in un dato momento ci sono k voli in tabella, essi siano i primi k elementi dell'array e quantivoli sia uguale a k. Ogni scansione della tabella si limitera' agli elementi di indice da 0 a quantivoli-1. Quindi una tabella di voli e' una struttura a due campi. */ typedef struct { TipoVolo arrayvoli[maxvoli]; /* sostegno di memoria */ int quantivoli; /* quanti voli presenti nel sostegno */ } TipoTabella; Suggerimento 2di3: ipotesi su alcune funzioni che useremo (solo intestazioni) void stampatabella(tipotabella t); /* stampa tutti i voli della tabella */ /*!!! */ /* per entrambe le precedenti funzioni sara' comodo usare una funzione come la seguente... */ void stampavolo(tipovolo v); /* stampa il volo v */ 11

int aggiungivolo(tipotabella *t); /* aggiunge un nuovo volo nella tabella *t, chiedendo e leggendo opportunamente i dati relativi Restituisce 1 o 0 a seconda della riuscita dell'ahggiunta. Passiamo l indirizzo t della tabella da modificare, in modo che le modifiche vengano fatte direttamente sulla tabella *t (e non su una sua copia). Sia (*t).arrayvoli (nell'elemento di indice dipendente da quantivoli), che (*t).quantivoli saranno modificati. L elemento in cui si inserisce il nuovo volo e (*t).arrayvoli[kkk] dove k deve essere uguale al campo quantivoli della tabella (KKK=(*t).quantiVoli). Poi (*t).quantivoli deve crescere di uno, perche abbiamo aggiunto un volo in tabella. */ Suggerimento 3di3: ecco la main() int main() { TipoTabella tabvoli; int riuscita, scelta; /* scelta nel menu' */ char buffer[40]; /* per leggere stringhe */ tabvoli.quantivoli=0; do { /* STAMPA MENU */ /* inizializzazione del numero di voli presenti in tabella (cosa ci sia effettivamente in tabvoli.arrayvoli e' di poco interesse. Tanto le scansioni che faremo saranno sempre limitate da quantivoli*/ printf(" - scegli -\n"); printf(" - stampa dei voli (1) -\n"); printf(" - stampa di un certo volo (2) -\n"); printf(" - aggiunta di un volo (3) -\n"); printf(" - fine (0) -\n"); scanf("%d", &scelta); /* SCELTA ESPRESSA DALL UTENTE */ 12

switch (scelta) { /* ELABORAZIONE IN BASE ALLA SCELTA */ case 1: printf("- %d voli in tabella:\n", tabvoli.quantivoli); stampatabella(tabvoli); break; case 2: /* funzione non ancora implementata; (rimanadata al prossimo esercizio) printf(" - codice volo? "); scanf("%s", buffer); stampaquelvolo(tabvoli, buffer); */ break; case 3: riuscita=aggiungivolo(&tabvoli); if(!riuscita) printf(" - aggiunta non effettuata -\n"); else printf(" - fatto -\n"); break; case 0: printf(" - USCITA DAL PROGRAMMA\n"); break; default: printf(" - opzione sballata\n"); } /* fine switch */ } while (scelta!=0); /* fine do_while*/ } printf("\nfine\n"); return 0; 7.3. Gestione voli (secondo passo VOLI2.C) Incrementare il programma costruito al passo precedente, con la funzionalita di stampa di un volo, dato il codice. (E poi testarlo...) Suggerimento 1di2: La funzione da implementare e la seguente: void stampaquelvolo(tipotabella t, char cod[]); 13

Suggerimento 2di2: Pero per stampare il volo di codice cod, bisogna cercarlo nella tabella. Questo problema di cercare un volo di codice dato ricorre, verosimilmente spesso nel resto del programma. Ecco come risolvere il problema una volta per tutte, con una funzione: int indicevolo(tipotabella t, char cod[]); /* cerca il volo di codice cod in t; cioe cerca nell array t.arrayvoli, limitando la scansione agli elementi che vanno da indice 0 a indice t.quantivoli-1 restituisce l'indice del volo oppure, se non lo ha trovato, -1 */ 7.4. Gestione voli (terzo passo VOLI3.C) Incrementare il programma costruito al passo precedente, con la funzionalita di eliminazione di un volo di codice dato. (E poi testarlo...). Suggerimento 1di2: Bisogna realizzare la funzione di eliminazione ed estendere la main() in modo che permetta di scegliere anche l opzione di eliminazione. Quando viene scelta questa opzione, il programma chiede il codice del volo da eliminare e poi chiama la funzione di eliminazione. La funzione da implementare e la seguente: int eliminavolo(tipotabella *t, char cod[]); /* elimina il volo di codice cod dalla tabella *t (cambiano arrayvoli e quantivoli) restituisce 0 o 1 a seconda del successo dell'operazione Si cerca l'elemento da eliminare, assegnando ad un indice il valore ritornato dalla funzione di ricerca, ad esempio k=indicevolo(*t, cod); e lo si ricopre copiandoci sopra l'ultimo elemento della tabella; ad esempio t->arrayvoli[k] = t->arrayvoli[ultimo]; (quanto vale l indice ultimo?) 14

poi si decrementa quantivoli ad esempio t->quantivoli-=1; */ Suggerimento 2di2: ultimo=t->quantivoli-1; 7.5. Gestione voli (quarto passo VOLI4.C) Incrementare il programma costruito al passo precedente, con le funzionalita di modifica richieste, cioe cambio dell ora di partenza di un volo di codice dato e prenotazione di un ecrto numero k di posti su un volo di codice dato. (E poi testarlo...). Bisogna realizzare due funzioni apposite, cambiaorapartenza(...) e cambiapostiliberi(...); e poi modificare la main() in modo che anche queste nuove operazioni siano accessibili dal menu. Suggerimento: le funzioni da realizzare potrebbero essere le seguenti: int cambiaorapartenza (TipoTabella *t, char cod[], int nuovaora, int nuovimin); /* restituisce 0 o 1 a seconda del successo dell'operazione */ int cambiapostiliberi(tipotabella *t, char cod[], int k); /* diminuisce di k i posti liberi, SE POSSIBILE restituisce 0 o 1 a seconda del successo dell'operazione */ Il parametro tabella qui deve essere l indirizzo della tabella attuale da modificare... 15

7.6. Gestione voli (quinto passo VOLI5.C) Incrementare il programma costruito al passo precedente, con le funzionalita di salvataggio su file della tabella e caricamento da file della tabella. (E poi testarlo...). Bisogna realizzare due funzioni apposite, void databellainfile(tipotabella t, char *nmf); /* riceve - una tabella da scaricare in memoria secondaria e - il niome del file in cui memorizzare le informazioni; e scarica i dati della tabella nel file di nome nmf*/ void dafileintabella(char *nmf, TipoTabella *t); /* riceve - l indirizzo di una tabella in cui memorizzare i dati contenuti in un file e - il nome del file da cui trarre i dati per riempire la tabella; e carica nella tabella puntata da t (cioe *t) i voli contenuti nel file di nome nmf */ e poi modificare la main() in modo che anche queste nuove operazioni siano accessibili dal menu. 7.7. Gestione voli (sesto passo VOLI6.C) Qui si richiede di risolvere il problema della gestione dei voli con un approccio piu dinamico, cioe facendo in modo che la memoria occupata dall array di voli arrayvoli (campo della tabella TipoVoli) non occupi un numero fissato MAXVOLI di locazioni di tipo TipoVolo (struct) ma modifichi l occupazione di memoria in ragione delle necessita (cioe del numero di voli effettivamente memorizzati nella tabella). Per realizzare questo scopo si suggerisce di adottare il seguente schema: - il tipo TipoTabella viene modificato, in modo che il campo arrayvolo non isa piu un array statico di MAXVOLI voli, ma il puntatore ad un array di voli dinamicamente allocato: TipoVolo * arrayvoli; - l inizializzazione della tabella non si limita piu all azzeramento del campo.quantivoli, ma deve anche procedere ad una prima allocazione del blocco di voli.arrayvoli. Questa allocazione fa in modo che arrayvoli punti ad una blocco di MAXVOLI voli (dove MAXVOLI e un simbolo di costante definito opportunamente, per il quale si consiglia un valore abbastanza basso, es 5 o 6); - la funzione di caricamento dei dati da file a tabella viene modificata, in modo che venga 16

o deallocato il blocco eventualmente puntato da arrayvoli e o allocato (e assegnato ad arrayvoli) un blocco di voli che verra riempito con i dati contenuti nel file; in particolare il primo dato letto dal file dice quanti sono i voli presenti nel file; il blocco viene allocato con un numero di voli di circa il 30% superiore a quelli effettivamente necessari, cosi dopo il caricamento dei dati, ci sara spazio per aggiungere nella tabella nuovi voli, ma senza esagerare con lo spazio occupato; - La funzione di aggiunta di un nuovo volo in tabella viene cambiata in modo che quando l aggiunta non e possibile per mancanza di spazio in arrayvoli, anziche lasciar perdere o si fa in modo che arrayvoli punti ad un blocoo di voli esteso (un po piu grande, ad esempio del 30%) o e poi si aggiunge il volo come si faceva prima Per fare in modo che arrayvoli punti ad un blocco di voli che contiene i voli gia presenti in tabella piu qualche altro spazio per nuovi voli, si possono usare varie soluzioni. La piu immediata consiste nel o salvare la tabella in un file TEMP.TXT o ricaricare subito la tabella, con la funzione di caricamento modificata, discussa in un punto precedente. Si consiglia di procedere facendo una copia del file in cui era stato risolto completamente il punto presedente (la cui proposta di soluzione era in VOLI5.C) e modificare questa copia, seguendo l ordine delle suggerimenti elencati sopra; Durante questa opera ci si potrebbe rendere conto che, aproposito di modifiche alla struttura dati di Tabella dei Voli, non tutto e stato detto fin qui: potrebbe essere necessario aggiungere un altra modifica. La scoperta di questa modifica è bella se viene fatta autonomamente... ma comunque se ne parla nel prossimo suggerimento. Suggerimento: visto che la dimensione del blocco di voli puntato da arrayvoli non e piu fissa (sempre uguale a MAXVOLI) durante l esecuzione del programma, diventa necessario averla memorizzata in una variabile. Questa variabile deve contenere, in qualsiasi momento, il numero di voli effettivamente allocati nel blocco arrayvoli, indipendentemente se occupati o disponibili. Quindi deve essere un valore associato stabilmente alla singola tabella (tab) con cui si sta lavorando. Ad esempio, durante l operazione di aggiunta di un nuovo volo si deve verificare che il numero di voli effettivamente memorizzato (.quantivoli) non sia diventato uguale al numero di strutture allocate nel blocco (altrimenti l aggiunta non si puo fare subito). Ne concludiamo che la variabile contenente il numero di voli allocati nel blocco arrayvoli deve essere un campo della tabella. E sara il terzo campo, che in VOLI6.C abbiamo chiamato.voliallocati. 17