Università degli Studi di Cagliari Corso di Laurea in Ingegneria Biomedica (Industriale), Chimica, Meccanica, Elettrica FONDAMENTI DI INFORMATICA 1 http://www.diee.unica.it/~marcialis/fi1 A.A. 2010/2011 Sommario Scrivere e leggere da qualunque I/O Il tipo FILE Funzioni fscanf e fprintf EOF Funzioni sscanf e sprintf Docente: Gian Luca Marcialis LINGUAGGIO C Gestione dei file Passaggio da standard I/O Il tipo FILE Lo stato della macchina virtuale C dopo la lettura di due valori numerici dalla tastiera CPU 12 28 Bus di sistema &a &b &somma Locazioni libere 12 28 Standard Input Standard Output E un particolare tipo, che serve ad identificare appunto I/O diverso da standard I/O Una variabile di tipo FILE identifica univocamente una lavagna ( stream ) nella quale si possono scrivere informazioni o cercarne ( leggerne ), se presenti Le funzioni per gestire i file sono presenti nella libreria <stdio.h> Per definire una variabile di tipo FILE: FILE *fp;
Funzioni per gestire i file Scrittura/lettura su file fp = fopen(char* NomeFile, char* Modalità) Apre lo stream identificato da fp (assegnandogli un valore) NomeFile è una stringa con il nome del file. Es. NomeFile= pippo.txt Modalità è una stringa di uno o due caratteri: w se il file è aperto in scrittura r se è aperto in lettura a se è aperto in modalità append, ovvero si vogliono aggiungere ai contenuti presenti nuovi contenuti scritti in fondo al file L uscita di fopen() è una costante di valore NULL se il file aperto in lettura/append non esiste oppure c è un errore nel nome del file. int fclose(file *fp) E la funzione che chiude il file dopo che su esso sono state compiute le operazioni desiderate, restituendo un valore diverso da 0 se l operazione è andata a buon fine Un file va sempre chiuso al termine del suo utilizzo fprintf(file *fp, char *StringaDaScrivere, parametri) E l analogo di printf per i file, si usa esattamente nella stessa maniera Es. fprintf(fp, L area del cerchio è pari a %f.\n,area); Scrive la stringa tra virgolette sul file aperto identificato da fp fscanf(file *fp, char* EspressioneDaLeggere, parametri) Analogo di scanf per i file Es. fscanf(fp, %d %d,&a,&b); Si aspetta di legge due valori interi da file e li memorizza nelle variabili a e b Esercizio Scrivere una funzione C scrivivettore, che, ricevendo in ingresso una stringa NomeFile e un vettore di N interi v, scriva il contenuto su un file di nome indicato da NomeFile, andando a capo per ogni valore scritto La funzione deve restituire il valore 1 se l operazione è andata a buon fine, 0 altrimenti Soluzione int scrivivettore(char* NomeFile, int* vettore, int N) FILE *fp; int i; fp=fopen(nomefile, w ); if (fp==null) return 0; for (i=0; i<n; i++) fprintf(fp, %d\n,v[i]); fclose(fp); return 1;
Gestione degli errori nei file Esercizio int feof(file *fp) Controlla nella struttura di descrizione dello stato del file cui fa riferimento fp se è stata raggiunta la fine del file nella precedente operazione di lettura o scrittura Restituisce 0 se la condizione di fine file non è stata raggiunta, un valore diverso da 0 in caso contrario Scrivere un programma che legge da file una sequenza di interi, separati da spazi o a capo, e la memorizza in un vettore. Il nome del file viene fornito da tastiera. Il vettore può avere al massimo 50 valori, ma il file presenta un numero di interi non definito. Si stampi a video eventualmente un avviso se la lunghezza massima del vettore è stata raggiunta interrompendo l acquisizione di valori Si stampi a video infine il vettore acquisito. Soluzione /*Programma che legge max 50 interi da file e li memorizza in un vettore*/ #include <stdio.h> int main() int i, j, vettore[50]; char nomefile[100]; FILE *fp; printf( Inserire il nome del file:\n ); scanf( %s,nomefile); fp=fopen(nomefile, r ); i=0; while((!feof(fp))&&(i<50)) /*finché il file non è finito e i<50*/ fscanf(fp, %d,&vettore[i]); i=i+1; /* oppure i++; */ if(i==50) printf( \nmax numero di valori acquisibile raggiunto.\n ); fclose(fp); for(j=0; j<i; j++) printf( \nv[%d] = %d,vettore[j]); Scrittura e lettura su stringhe sprintf(char* StringaDiScrittura, char *StringaDaScrivere, parametri); Analoga a printf e fprintf, solo che scrive nella stringa indicata da StringaDiScrittura, finché c è spazio Es. sprintf(frase, Il perimetro del rettangolo è %f.\n,perimetro); Scrive nella stringa frase l espressione tra virgolette sscanf(char* StringaDiLettura, char* EspressioneDaLeggere, parametri); Ulteriori funzioni per manipolare stringhe sono presenti nella libreria <string.h> return 0;
Alcune funzioni utili di <string.h> char* strcpy(s,ct) Copia la stringa ct nella stringa s, incluso \0 ; restituisce s char* strcat(s,ct) Concatena la stringa ct alla fine della stringa s; restituisce s int strcmp(cs,ct) Confronta la stringa cs con la stringa ct; restituisce <0 se cs<ct, 0 se cs==ct, >0 se cs>ct size_t strlen(cs) Restituisce la lunghezza di cs Esercizio Scrivere un programma che legge un file di testo geometri.txt così formattato: <Forma Geometrica> v1 [v2 v3] Dove <Forma Geometrica> = Triangolo Quadrato Rettangolo v1 [v2 v3] sono al massimo tre valori reali Per ogni riga di ingresso, il programma calcola e scrive, nel file di uscita risultati.txt, ed in modalità append, la forma della figura e il suo perimetro Si sviluppi la soluzione in forma modulare Attraverso procedure e funzioni Esempio di file geometri.txt Triangolo 34.2 45.1 90.4 Rettangolo 40.1 20.9 Rettangolo 12.1 55.5 Quadrato 45.0 Vincoli per scrivere la soluzione Si definisca una struttura dati Forma_Geometrica, caratterizzata da: un vettore di caratteri nome_forma indicanti il tipo ( Triangolo ; Quadrato ; Rettangolo ); un vettore di float lati di max 3 posizioni con i valori dei lati un valore float perimetro; un intero numero_lati tale che: Se 1 la forma è Quadrato Se 2 la forma è Rettangolo Se 3 la forma è Triangolo Altrimenti la forma non è definita, e contenga il valore 0; Si scriva inoltre: una funzione che calcoli il perimetro per ognuna delle tre forme: essa riceve in ingresso il vettore dei lati ed il numero di lati, e restituisce un valore reale pari al perimetro una funzione che legga il tipo di forma da file, calcoli il numero opportuno di lati restituisca una variabile di tipo Forma_Geometrica aggiornata una funzione che, ricevendo in ingresso una variabile di tipo Forma_Geometrica, scriva la forma e stampi il perimetro nel file su file in modalità append
Definizione della struttura dati richiesta typedef struct char nome_forma[50]; float lati[3]; float perimetro; int numero_lati; Forma_Geometrica; Implementazioni delle funzioni richieste: perimetro della forma float perimetro_forma(float *lati, int num_lati) switch(num_lati) case 1: return 4*lati[0]; case 2: return 2*(lati[0]+lati[1]); case 3: return lati[0]+lati[1]+lati[2]; return 0.0; Aggiornamento della forma Forma_Geometrica leggi_forma(file *fp) int i; Forma_Geometrica forma; fscanf(fp, %s,&(forma.nome_forma[0])); if(!strcmp(forma.nome_forma, TRIANGOLO ) forma.numero_lati=3; if(!strcmp(forma.nome_forma, RETTANGOLO ) forma.numero_lati=2; if(!strcmp(forma.nome_forma, QUADRATO ) forma.numero_lati=1; forma.numero_lati=0; printf( \nforma non definita\n ); for(i=0; i<forma.numero_lati; i++) fscanf(fp, %d,&(forma.lati[i])); Stampa della forma col perimetro void stampa_forma(forma_geometrica forma) FILE *out; out=fopen( risultati.txt, a ); if(out==null) return; fprintf(out, %s %f\n,forma.nome_forma,forma.perimetro); fclose(out); return forma;
Soluzione: vista top-down /*Programma per la stampa del perimetro di una forma geometrica su file*/ #include <stdio.h> #include <stdlib.h> #include <string.h> int main() FILE *in; Forma_Geometrica forma; /*Apri il file geometri.txt */ while (!feof(in)) /* Finché il file non è finito*/ /*Leggi la forma geometrica*/ /*Se la forma è definita: Calcola il perimetro della forma letta Stampa il perimetro della forma su file risultati.txt Altrimenti Esci dal ciclo*/ /*Chiudi il file geometri.txt*/ /*Apri il file geometri.txt*/ in=fopen( geometri.txt, r ); if(in==null) return 0; /*Chiudi il file geometri.txt*/ fclose(in); return 0; Ritorniamo al main /*Programma per la stampa del perimetro di una forma geometrica su file*/ #include <stdio.h> #include <stdlib.h> #include <string.h> int main() FILE *in; Forma_Geometrica forma; in=fopen( geometri.txt, r ); if(in==null) return 0; while (!feof(in)) /* Finché il file non è finito*/ forma=leggi_forma(in); if(forma.num_lati!=0) forma.perimetro=perimetro_forma(forma.lati,forma.numero_lati); stampa_forma(forma); break; fclose(in); return 0; Per saperne di più Ceri, Mandriola, Sbattella, Informatica arte e mestiere, Capp.3-4, McGraw-Hill Kernighan, Ritchie, Il linguaggio C, Cap. 1, Pearson- Prentice Hall