04.5-Linguaggio C - Gestione dei file [modalità compatibilità]

Transcript

04.5-Linguaggio C - Gestione dei file [modalità compatibilità]
Università degli Studi di Cagliari
Corso di Laurea in Ingegneria Biomedica (Industriale), Chimica, Meccanica, Elettrica
Sommario
FONDAMENTI DI INFORMATICA 1
http://www.diee.unica.it/~marcialis/FI1
Scrivere e leggere da qualunque I/O
Il tipo FILE
Funzioni fscanf e fprintf
EOF
A.A. 2010/2011
Funzioni sscanf e sprintf
Docente: Gian Luca Marcialis
LINGUAGGIO C
Gestione dei file
Il tipo FILE
Passaggio da standard I/O
Lo stato della “macchina virtuale C” dopo la lettura di
due valori numerici dalla tastiera
Bus di sistema
12
28
CPU
12
28
&a
&b
&somma
Locazioni
libere
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
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
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
Scrittura/lettura su file
fprintf(FILE
*fp,
*StringaDaScrivere, parametri)
char
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,
EspressioneDaLeggere, parametri)
Analogo di scanf per i file
Es. fscanf(fp,”%d %d”,&a,&b);
char*
− Si aspetta di legge due valori interi da file e li memorizza nelle
variabili a e b
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
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
Esercizio
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]);
return 0;
}
Scrittura e lettura su stringhe
sprintf(char*
StringaDiScrittura,
*StringaDaScrivere, parametri);
char
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>
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
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
Esercizio
Scrivere un programma che legge un file di testo geometri.txt
così formattato:
<Forma Geometrica> v1 [v2 v3]
Dove
<Forma
Geometrica>
=
Triangolo
Rettangolo
v1 [v2 v3] sono al massimo tre valori reali
|
Quadrato
|
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
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;
else
if(!strcmp(forma.nome_forma,”RETTANGOLO”)
forma.numero_lati=2;
else
if(!strcmp(forma.nome_forma,”QUADRATO”)
forma.numero_lati=1;
else
{
forma.numero_lati=0;
printf(“\nForma non definita\n”);
}
for(i=0; i<forma.numero_lati; i++)
fscanf(fp,”%d”,&(forma.lati[i]));
return forma;
}
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);
}
Soluzione: vista top-down
/*Apri il file geometri.txt*/
/*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*/
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);
}
else
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, PearsonPrentice Hall