Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR Introduzione al C Unità 9 File D. Bloisi, A. Pennisi, S. Peluso, S. Salza
Sommario Unità 9 Input/Output in C Stream File Pagina 2
I/O in C Il sistema di I/O del C è una interfaccia uniforme per il programmatore indipendentemente dal dispositivo di lettura e scrittura utilizzato. Scrivere o leggere da file o da video/tastiera non comporta differenze. Pagina 3
Schema di un calcolatore Tastiera Mouse Stampante Modem Porte I/O Controller dischi Hard disk CD/ROM DVD CPU Scheda video Monitor Memoria Scheda audio Casse Microfono bus Scheda rete Altro PC Internet Pagina 4
Sistema di I/O Il sistema di I/O del C crea un livello di astrazione tra il programmatore e l oggetto (sia esso un file o dispositivo) Viene creato un meccanismo di astrazione tramite un flusso di dati o stream Pagina 5
Stream Uno stream (flusso di dati) fornisce un canale di comunicazione tra il programma e l esterno (file o device) Uno stream è una struttura costituita da una sequenza di byte terminante con un apposito carattere che ne identifica la fine. Pagina 6
Stream Gli stream vengono associati (con opportuni comandi) Ø ai dispositivi fisici collegati al computer (tastiera, video, stampante, etc ) Ø a file residenti sulla memoria di massa Pagina 7
Bufferizzazione Gli streams di I/O sono bufferizzati: questo significa che ogni volta viene letto da un file o scritto su di esso un "pezzo" di dimensioni stabilite attraverso alcune aree temporanee di immagazzinamento (è importante notare che il file puntatore punta effettivamente a questo buffer). Pagina 8
Bufferizzazione Questo metodo rende efficiente l'i/o, ma è necessario fare attenzione: i dati scritti in un buffer non compaiono nel file (o nel device) finché il buffer non è riempito o scaricato (e.g. "\n" serve a questo). Qualsiasi uscita anormale del programma può causare problemi. Pagina 9
FILE Esiste una struttura di dati interna al C, FILE, che rappresenta uno stream ed è definita nel file stdio.h. Viene usato il nome FILE per motivi storici, anche se la struttura FILE può essere usata per rappresentare un oggetto diverso da un file in senso tecnico. E' sufficiente fare riferimento alla struttura FILE nei programmi C quando si realizza l'i/o utilizzando uno stream. Pagina 10
Esempio printf Produce una sequenza di caratteri che viene inviata allo stream stdout (video) Pagina 11
Esempio scanf Legge i caratteri dallo stream stdin (tastiera), ossia lo stream di input e li deposita convertendoli nello specifico formato nelle variabili il cui indirizzo è specificato Pagina 12
File I file rappresentano la principale struttura per la memorizzazione di dati in maniera permanente su memoria di massa (hanno la caratteristica di sopravvivere allo spegnimento della macchina). Essi possono contenere caratteri alfanumerici codificati in formato standard (es. ASCII) direttamente leggibili dall utente (file di testo), oppure dati in un formato interpretabile dai programmi (file binari ). Pagina 13
File Flusso sequenziale di byte terminato dal carattere di terminazione chiamato End-Of-File (EOF). Pagina 14
File di testo I file di testo sono normalmente organizzati in sequenze di linee ciascuna delle quali contiene una sequenza di caratteri. In questo corso tratteremo solamente file di testo. Pagina 15
File e directory Ogni file è caratterizzato da un nome e una directory (o cartella) in cui risiede. Le operazioni fondamentali sui file sono: creazione, lettura, scrittura, rinominazione ed eliminazione. Queste operazioni possono essere effettuate tramite il sistema operativo (o altri programmi applicativi) oppure mediante apposite istruzioni del linguaggio C. Pagina 16
Operazioni sui file Per eseguire operazioni di lettura e scrittura sui file è necessario Ø aprire il file prima di eseguire le operazioni Ø chiudere il file al termine dell esecuzione delle operazioni. Pagina 17
File e stream Il file deve essere connesso al programma tramite l astrazione dello stream. L apertura e la chiusura dello stream associato al file non sono automatici come invece nel caso di stdin, stdout, stderr Pagina 18
Aprire un File Aprire un file significa indicare al sistema operativo la volontà di eseguire operazioni sui file. Il sistema operativo verificherà all atto dell apertura del file se tale operazione è possibile. Pagina 19
Scrittura e lettura L apertura del file si distingue in due casi: 1.apertura in lettura 2.apertura in scrittura che definiscono un comportamento differente nel sistema operativo (ad esempio, è possibile che due applicazioni aprano lo stesso file contemporaneamente in lettura, ma non in scrittura). In molti linguaggi di programmazione l apertura in scrittura di un file coincide con la sua creazione. Pagina 20
Le funzioni fprintf e fscanf fprintf ( <descrittorefile>, <stringa di controllo>, <altri-argomenti> ) fscanf ( <descrittorefile>, <stringa di controllo>, <altri-argomenti> ) Sono le versioni di printf e scanf relative ad un generico file esterno. Pagina 21
Descrittore di File Cosa è <descrittorefile>: È una connessione tra: il mondo interno al programma (tutto in memoria centrale) e il mondo esterno (rappresentato dai file residenti nelle memoria di massa) È legato al nome fisico del file e ad altre caratteristiche strutturali Pagina 22
Descrittore di File Per usare file esterni Ø Si deve introdurre questo rappresentante interno del mondo esterno Ø Si deve creare una associazione temporanea tra mondo esterno e rappresentante interno Pagina 23
Sintassi - Descrittore di File Il descrittore di file è una variabile Bisogna specificare un nome e un tipo per poterlo dichiarare FILE *<identificatore>; Esempio FILE *ingressodsc; Pagina 24
Puntatore a File FILE *ingressodsc; FILE * si riferisce ad uno specifico tipo puntatore a file esterno ingressodsc è una variabile di tipo puntatore a file Attenzione: manca ancora il legame con l esterno Pagina 25
Le funzioni fprintf e fscanf int fprintf ( FILE * stream, const char * format,... ); int fscanf ( FILE * stream, const char * format,... ); Sono definite in stdio.h Pagina 26
Connessione La funzione fopen crea la connessione tra il descrittore ed il file vero e proprio (esterno) <descrittorefile> = fopen( <nomefileesterno>, <modalità di uso> ); Esempio ingressodsc = fopen("filedaleggere.txt", "r"); Pagina 27
Modalità di uso Si deve specificare se il file va usato in lettura o scrittura (si ricordi la distinzione tra stdin e stdout ) File in lettura "r" (read) File in scrittura "w" (write) Scrittura alla fine del file "a" (append) Pagina 28
Esempio FILE *uscitadsc; uscitadsc = fopen("filedascrivere.txt", "w"); Pagina 29
Dettagli sulle modalità (1/2) r : Apre il file in lettura. Lo stream è posizionato all inizio del file. r+ : Apre il file in lettura e scrittura. Lo stream è posizionato all inizio del file. w : Apre un file in scrittura cancellandone il contenuto. Se il file non esiste allora è creato. Lo stream è posizionato all inizio del file. w+ : Apre un file in scrittura e lettura cancellandone il contenuto. Se il file non esiste allora è creato. Lo stream è posizionato all inizio del file. Pagina 30
Dettagli sulle modalità (2/2) a : Apre un file in scrittura. Se il file non esiste allora è creato. Lo stream è posizionato alla fine del file. a+ : Apre il file in lettura e scrittura. Se il file non esiste allora è creato. Lo stream è posizionato alla fine del file. Pagina 31
Chiusura della connessione Quando il file esterno non serve più, deve essere chiuso Questo si ottiene cancellando esplicitamente la connessione con l esterno fclose(<descrittorefile>); Pagina 32
Esempio int main (void) { //altre dichiarazioni di variabili FILE *inputdsc; FILE *outputdsc; inputdsc = fopen("filedatiingresso", "r") outputdsc = fopen("filedatiuscita.txt", "w") fclose(inputdsc); fclose(outputdsc); } Pagina 33
Eccezioni Nella comunicazione con il mondo esterno può accadere che il file non si apra correttamente. Questo viene segnalato da un valore particolare del descrittore di file, indicato con NULL. Dopo fopen( ) inserire sempre un controllo if (inputdsc == NULL) { } Pagina 34
Esempi if (inputdsc == NULL) printf ("errore nella apertura del file di ingresso"); if (outputdsc == NULL) printf ("errore nella apertura del file di uscita"); Pagina 35
Modello ideale per il File Un file può essere immaginato come un nastro con delle informazioni ed una testina di lettura che è l indicatore di posizione. La testina viene spostata da istruzioni come fscanf e fprintf o in modo esplicito con fseek Pagina 36
Funzione fseek int fseek(file *stream, long offset, int whence); Imposta la nuova posizione dell indicatore di posizione puntato da stream. La nuova posizione (in bytes) è ottenuta sommando offset alla posizione specificata da whence. Se whence è SEEK_SET, SEEK_CUR, o SEEK_END l offset è relativo rispettivamente all inizio del file, alla posizione corrente dell indicatore di posizione oppure alla fine del file. Ritorna 0 in caso di successo, -1 altrimenti. Pagina 37
La fine del file (EOF) La fine del file viene segnalata da un carattere particolare, il simbolo di End-of-File (EOF) La codifica del carattere EOF dipende dalla macchina Ctrl-z per Windows Ctrl-d per Mac Ctrl-x per Unix e Linux Pagina 38
Riassumendo 1. Viene dichiarato il descrittore del file FILE *<descrittore>; 2. Il file si apre con la funzione fopen <descrittore> = fopen( <nome_file>, <modo_apertura ); <nome_file> è il nome fisico del file, come è chiamato sul disco, es. ingresso.dat <modo_apertura>: "w" se il file è aperto in scrittura "r" se il file è aperto in lettura etc. Pagina 39
Riassumendo 3. Possono essere eseguite operazioni di lettura e scrittura utilizzando il descrittore del file 4. Il file viene chiuso fclose(<descrittore>); Pagina 40
Esempio FILE *fp; fp = fopen("test.dat", "r"); FILE *fptr; fptr = fopen("prova.dat", "w"); //lettura utilizzando fp e // scrittura utilizzando fptr fclose(fp); fclose(fptr); Pagina 41
Esercizio Leggere un file di testo esempio.txt e stampare ogni parola in una singola riga Contenuto del file di testo. Output Contenuto del file di testo. esempio.txt Pagina 42
Condizioni sull input Esiste già un file che deve essere aperto in lettura e analizzato per produrre il risultato desiderato. Pagina 43
Soluzione #include <stdio.h> int main (){ char ch; FILE *fd; //descrittore del file fd = fopen("esempio.txt", "r"); if(fd!= NULL){ while (fscanf(fd, "%c", &ch)!= EOF) { if(ch == ' ') printf("\n"); else printf("%c", ch); } } else printf ("\nerrore di apertura!"); fclose(fd); return 0; } Pagina 44
Valore di ritorno per fscanf int fscanf ( FILE * stream, const char * format,... ); fscanf restituisce un valore che è pari ad EOF quando viene raggiunta la fine del file Pagina 45
Operatori per leggere e scrivere caratteri Da tastiera e video getchar (lettura) putchar (scrittura) Da file fgetc(<filedescrittore>); fputc (<intero>, <filedescrittore>); Pagina 46
Esempio while((ch = fgetc(fd))!= EOF) { if(ch == ' ') putchar('\n'); else putchar(ch); } Pagina 47
Esercizio scrittura su file Memorizzare su un file clienti.txt i seguenti dati: Numero conto Bilancio per un massimo di 10 clienti inseriti da tastiera. Digitare EOF per terminare prima l inserimento. Pagina 48
Soluzione scrittura su file int main () { int conto, i; float bilancio; FILE *cfptr; /* descrittore file */ if ((cfptr = fopen("clienti.txt", "w")) == NULL) printf("il file non puo' essere aperto"); else { for (i=1; i<=10; i++) { printf("immetti il conto e il bilancio\n"); if(scanf("%d %f", &conto, &bilancio) == EOF) break; fprintf(cfptr, "%d %f\n", conto, bilancio); } fclose(cfptr); } return EXIT_SUCCESS; } Pagina 49
Esecuzione Immetti il conto e il bilancio 23 456 Immetti il conto e il bilancio 12 8764 Immetti il conto e il bilancio 90-78 Immetti il conto e il bilancio ^Z 23 456.000000 12 8764.000000 90-78.000000 clienti.txt Pagina 50
Esercizio lettura da file Leggere dal file clienti.txt i seguenti dati: Numero conto Bilancio Pagina 51
Soluzione lettura da File int main () { int conto, i; float bilancio; FILE *cfptr; /* descrittore file */ if ((cfptr = fopen("clienti.txt", "r")) == NULL) printf("il file non puo\' essere aperto\n"); else { printf("conto \t\t Bilancio\n"); for (i=1; i<=10; i++) { if(fscanf(cfptr,"%d %f",&conto,&bilancio) == EOF) break; printf("%d \t\t %f\n", conto, bilancio); } fclose(cfptr); } return EXIT_SUCCESS; } Pagina 52
Esecuzione Conto Bilancio 23 456.000000 12 8764.000000 90-78.000000 Pagina 53
Esempio: conteggio caratteri in un file int main( ) { FILE *fptr ; char ch ; long int cont = 0 ; if((fptr = fopen( input.txt", "r"))!= NULL){ while( fscanf(fptr, "%c", &ch )!= EOF ) { cont++ ; } printf( "cont = %ld\n", cont ) ; // cont = numero caratteri in "lettera.txt" fclose( fptr ) ; } else printf( "errore apertura file" ) ; return EXIT_SUCCESS; } Pagina 54
Esercizio: acquisizione array da file Si scriva un programma che legga un array da un file. Il file è denominato arr.dat ed è composto da 10 righe rappresentanti un array di dieci elementi interi, con un elemento per riga. Si stampi poi il contenuto dell array. Pagina 55
Soluzione #include <stdio.h> #include <stdlib.h> int main( ) { int max_d = 10; FILE *frptr; int v[max_d], pos; if ((( frptr = fopen( arr.dat", "r" ))!= NULL )) { for( pos = 0 ; pos < max_d ; pos++ ) fscanf( frptr, "%d", &v[pos] ) ; fclose( frptr ) ; } else printf( "errore apertura file\n" ) ; for( pos = 0 ; pos < max_d ; pos++ ) printf("%d ", v[ pos ] ) ; printf("\n"); return EXIT_SUCCESS; } Pagina 56
Convertire caratteri numerici in interi #include <stdlib.h> int atoi(const char *str); La funzione atoi converte la porzione iniziale puntata dalla stringa str in una rappresentazione di tipo int. Esempio: char* str = "23ciao"; int i = atoi(str); printf("%d\n", i); return 0; Pagina 57
Esercizio Realizzare un programma sommafile che prenda tre parametri in ingresso: <A> primo addendo intero; <B> secondo addendo intero; <C> nome di un file. Il programma deve sommare A e B, creare un file denominato con il nome C e stampare il risultato nel file. Pagina 58