Scaricare la presentazione
La presentazione è in caricamento. Aspetta per favore
1
Esercizi su File e Liste
2
Esercizio Si progetti e codifichi un programma C che apre il file di testo input.txt e genera il file di testo output.txt, che contiene, in ordine inverso ma inalterate, le sole linee di input.txt che hanno lunghezza compresa tra 10 e 20 caratteri (ignorando le altre linee). A tale scopo, il programma alloca una lista dinamica che contiene le linee da trasferire, genera il file scandendo la lista e la dealloca prima di terminare. Si usi la seguente definizione della lista: typedef struct EL { char linea[21]; struct EL * next; } Nodo; typedef Nodo * Lista; Si provi a costruire la lista nel modo più semplice che permetta poi di generare facilmente l'output Si può assumere che l'ultima linea di input.txt termini con '\n' e che nessuna linea superi i 255 caratteri
3
Essendo chiaramente assai più complicato (e inutile) scandire il file un carattere alla volta, scandisco il file di input una linea per volta con fgets() o con fscanf(…”%s”…), controllo subito se ogni linea è da trasferire, e nel caso la inserisco in testa alla lista dinamica, in un nodo appositamente allocato. Così facendo, al termine del file di input la lista in memoria contiene le linee già in ordine inverso: il file di output si genera con una semplice scansione lineare, durante la quale si dealloca la lista. int main () { FILE * fp; char buffer[256]; // max 255 caratteri + 1 per il '\0' Lista lis = NULL, tmp; if ( (fp=fopen("input.txt","r")) == NULL ) // Selezione linee da tenere return -1; while( fgets( buffer, 256, fp ) != NULL ) if ( strlen(buffer) >= 10 && strlen(buffer) <= 20 ) insTesta(&lis, buffer); close(fp); if ( (fp=fopen("output.txt","w")) == NULL ) return -2; while ( lis != NULL ) { // Man mano che trascrivo, dealloco fputs( lis->linea , fp ); tmp = lis; lis = lis->next; free(tmp); } return 0; void insTesta( Lista *lista, char * line ) { // Normale inserimento in Lista tmp = *lista; // testa con assegnamento *lista = (Lista) malloc(sizeof(Nodo)); // del "dato" con strcpy strcpy( (*lista)->linea, line ); (*lista)->next = tmp;
4
Esercizio (tde ) Le telecamere di un parcheggio multilivello riconoscono le targhe di ogni auto in ingresso. Se la targa è contenuta nel file credito.txt (formattato come nel riquadro) e il credito è di almeno 2,50 €, la funzione int checkin(char * targa) restituisce 1, altrimenti restituisce 0 (e una botola risucchia l’auto in un pozzo senza fondo). Si codifichi in C la funzione checkin
5
int checkin(char. targa) { FILE
int checkin(char * targa) { FILE * f; char line[100], plaque[8]; float credit; if( (f = fopen("credito.txt", "r")) == NULL ) return -1; while( fgets(line, 100, f) != NULL ) { sscanf(line, "%s%f", plaque, &credit); if( strcmp(targa,plaque) == 0 && credit >= 2.50 ) { fclose(f); return 1; } return 0;
6
Esercizio (continua) Le auto ammesse leggono su un display il piano a cui devono recarsi, che è calcolato automaticamente dal sistema come il primo che abbia almeno un posto libero. La struttura dati del sistema è la seguente typedef struct Car { char * targa; struct Car * next; } Auto; typedef Auto * Lista; typedef struct Level { int postiliberi; Lista macchine; struct Level * next; } Piano; typedef Piano * ListaDiListe; dove ogni piano è pieno se il suo attributo postiliberi vale 0 e vuoto se la sua lista macchine è vuota. Si codifichi in C la funzione int assegnapiano(ListaDiListe L, char * targa), che restituisce il numero del piano oppure -1 se non c’è posto. La funzione alloca anche il nodo corrispondente all’auto entrata
7
Vediamo prima una semplice soluzione iterativa int assegnapiano(ListaDiListe L, char * targa) { int p = 1; while( L != NULL && L->postiliberi == 0 ) { L = L->next; p++; } if( L == NULL ) return -1; L->macchine = instesta(L->macchine, targa); (L->postiliberi)--; return p; Lista instesta(Lista L, char * targa) { Lista punt; punt = (Lista)malloc(sizeof(Auto)); punt->targa = (char *)malloc(8); // 7 caratteri per la targa, uno per /0 strcpy(punt->targa,targa); punt->next = L; return punt;
8
E anche una semplice soluzione ricorsiva, usando la stessa funzione di servizio int assegnapiano(ListaDiListe L, char * targa) { int p; if( L == NULL ) return -1; if( L->postiliberi <= 0 ) { if( (p = assegnapiano(L->next, targa)) < 0 ) return -1; else return p + 1; } L->macchine = instesta(L->macchine, targa); (L->postiliberi)--; return 1;
9
Esercizio (continua) Si gestisca con la funzione ...checkout( ... ) l’uscita di un’auto dal parcheggio, in modo da lasciare la struttura dati in uno stato consistente. La funzione non si occupa dell’addebito del costo del parcheggio. Le soluzioni sostanzialmente ricorsive ricevono un punto di bonus
10
Possiamo definire due funzioni di servizio (ricorsive) direttamente ispirate a quelle viste a lezione per trovare e cancellare un’auto in una lista semplice (la lista macchine di ogni piano). int find(Lista cars, char * targa) { if( cars == NULL ) return 0; if( strcmp(cars->targa, targa) == 0 ) return 1; return find(cars->next, targa); } Lista remove(Lista cars, char * targa) { Lista punt; if( Lista != NULL ) if( strcmp(cars->targa, targa) == 0 ) { punt = cars->next; free(cars->targa); // era stata allocata una stringa dinamica free(cars); return punt; else { cars–>next = remove(cars->next, targa); return cars; else
11
E usarle in una funzione (ricorsiva) che in ogni piano del parcheggio prima verifica se c’è la macchina, e se la trova la dealloca e aggiorna il contatore dei posti liberi in quel piano. void checkout(ListaDiListe L, char * targa) { Lista cars; if( L == NULL ) printf("\n Nessuna traccia della macchina!\n"); else if( find(L, targa) ) { L->macchine = remove(L->macchine, targa); (L->numeroposti)++; } else checkout(L->next, targa);
Presentazioni simili
© 2024 SlidePlayer.it Inc.
All rights reserved.