Linguaggio C

Transcript

Linguaggio C
Linguaggio C – Gestione File
Gestione File:
Il file è l'unità logica di memorizzazione dei dati su memoria di massa, che consente una memorizzazione
persistente dei dati non limitata dalle dimensioni della memoria centrale.
Nel linguaggio C, un file è visto come un flusso (stream) sequenziale di byte che termina con un marcatore di EOF
(end-of-file). I programmi C possono accedere a file (leggere e scrivere) mediante le funzioni standard definite nella
libreria di I/O "stdio.h" .
Ogni programma vede il file come una sequenza di componenti omogenee (record logici).
In C i file si possono dividere in due categorie:
•
•
file di testo : costituiti da caratteri ed organizzati in linee (ciascuna terminata da '\n').
file binari : visti come sequenze di byte.
Nel primo caso, abbiamo file di caratteri, organizzati in linee;
ogni linea è terminata da una marca di fine linea (newline, carattere '\n').
Il record logico può essere il singolo carattere oppure la singola linea.
Nota: I file hanno una struttura sequenziale, cioè i record logici sono organizzati in una sequenza rigidamente
ordinata; per accedere ad un particolare record logico è necessario "scorrere" tutti quelli che lo precedono.
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
In corrispondenza di file, le classiche operazioni sono:
Apertura di un file: prima di accedere ad un file è necessario aprirlo; l’operazione di apertura compie le azioni
preliminari necessarie affinchè il file possa essere acceduto.
Accesso ad un file: una volta aperto il file, è possibile leggere/scrivere il file.
Chiusura di un file: alla fine delle operazioni (lettura o scrittura) è necessario chiudere il file per memorizzare
permanentemente il suo contenuto in memoria di massa.
Per aprire un file in C è necessario definire una variabile di tipo puntatore a file:
FILE *fp;
// FILE : tipo non primitivo definito in stdio.h
FILE *fopen(char *name, char *mode); // funzione di apertura file.
dove:
name: è una stringa che rappresenta il nome (assoluto o relativo) del file nel file system.
mode: esprime la modalità di accesso scelta.
L'operazione di apertura (se eseguita con successo) ritorna come risultato un puntatore al file aperto;
Se l'apertura fallisce, fopen restituisce il valore NULL. Tipici motivi di fallimento:
- Il file non esiste.
- Il file viene aperto in una modalità incompatibile con le sue proprietà
( es.: file read-only , aperto in scrittura)
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
Modalità di apertura:
“r” : solo lettura - sul file sarà possibile eseguire soltanto operazioni di lettura (no scrittura).
Se il file non esiste la funzione fopen ritornerà il codice di errore NULL.
“w” : solo scrittura - sul file sarà possibile eseguire soltanto operazioni di scrittura (no lettura).
Se il file non esiste verrà creato, altrimenti il contenuto del file preesistente sarà perso.
“r+” : lettura e scrittura - sul file sarà possibile eseguire operazioni di lettura e scrittura.
Se il file non esiste la funzione fopen ritornerà il codice di errore NULL.
“w+” : scrittura e lettura - sul file sarà possibile eseguire operazioni di scrittura e lettura.
Se il file non esiste verrà creato, altrimenti il contenuto del file preesistente sarà perso.
“a” : append - sul file sarà possibile eseguire soltanto operazioni di scrittura a fine file, ovvero
tutte le scritture verranno eseguite in coda al contenuto attuale del file. Se il file non esiste
verrà creato, in caso contrario il contenuto del file preesistente verrà mantenuto.
“a+” : append e lettura - come append con l’aggiunta della lettura.
“b” : binary - se una b viene aggiunta alle modalità precedenti si indica che il file è binario.
Es.: apertura di file in lettura:
FILE *fp;
fp = fopen("filename", "r");
EOF
fp
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
Es.: apertura di file in scrittura:
FILE *fp;
fp = fopen("filename", "w");
File nuovo:
File esistente - sovrascritto:
EOF
fp
fp
Es.: apertura di file in append:
EOF
FILE *fp;
fp = fopen("filename", "a");
fp
Esempio pratico:
File *fp;
fp=fopen("elenco.dat", "r");
Nota: fp rappresenta, dall'apertura in poi, il riferimento da utilizzare nelle
operazioni di accesso al file specificato (elenco.dat); esso individua:
- il file
- l’elemento corrente all’interno del file
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
Chiusura file:
Al termine delle operazioni di accesso al file, esso deve essere chiuso.
L'operazione di chiusura si realizza con la funzione:
int fclose(FILE *fp); // dove fp è il puntatore al file da chiudere.
La funzione fclose ritorna il valore 0 se la chiusura è avvenuta correttamente, altrimenti la costante EOF.
Esempio:
#include <stdio.h>
int main() {
FILE *fp;
fp = fopen("c:\\documenti\\risultati.txt", "w");
// fp = fopen("c:/documenti/risultati.txt", "w"); notazione linux/unix
// … operazioni di scrittura su file
fclose(fp);
return 0;
}
Funzione feof():
Durante la fase di accesso ad un file, questa funzione ci consente di verificare la presenza della marca di fine file;
prototipo:
int feof(FILE *fp);
In altre parole, controlla se è stata raggiunta la fine del file fp nella operazione di lettura o scrittura precedente.
Restituisce il valore 0 se non è stata raggiunta la fine del file, altrimenti un valore diverso da zero.
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
File standard di I/O:
Quando inizia l’esecuzione di un programma in C, tre file di testo vengono aperti automaticamente:
• stdin, standard input, aperto in lettura
• stdout, standard output, aperto in scrittura
• stderr, standard error, aperto in scrittura
Dove stdin, stdout, stderr sono variabili di tipo puntatore a file, automaticamente (ed implicitamente) definite.
Il file pointer stdin è associato dal sistema alla tastiera, mentre gli altri due sono assegnati al video.
Lettura e scrittura di file:
Dopo aver aperto un file, su di esso possiamo eseguire operazioni di lettura e/o scrittura, compatibilmente con
quanto specificato in fase di apertura.
File di testo: sono disponibili funzioni di:
a) Lettura/scrittura con formato: fscanf, fprintf
b) Lettura/scrittura di caratteri: fgetc, fputc
c) Lettura/scrittura di stringhe di caratteri: fgets, fputs.
File binari: si utilizzano funzioni di lettura/scrittura di blocchi: fread, fwrite.
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
a) Lettura/scrittura con formato:
Date le funzioni scanf e printf, esistono le rispettive versioni che operano su file in maniera esattamente uguale;
presentano un parametro aggiuntivo per il puntatore al file di testo sul quale si vuole leggere o scrivere.
int fscanf(FILE *fp, stringa_formato, indir_elementi);
int fprintf(FILE *fp, stringa_formato, elementi);
Le due funzioni restituiscono rispettivamente il numero di elementi letti/scritti;
oppure un valore negativo in caso di errore.
Esempi:
……
FILE *fp;
int X; char Y; float Z;
fp=fopen("risultati.txt", "r");
fscanf(fp, "%d %c %f", &X, &Y, &Z);
prinf("X= %d Y= %c Z= %f", X, Y, Z);
fclose(fp);
…….
Si noti che:
scanf(stringa_formato, indir_elementi);
printf(stringa_formato, elementi);
……
FILE *fp;
int X=6; char Y='h'; float Z=9.8;
fp=fopen("risultati.txt", "w");
fprintf(fp, "%d %c %f", X, Y, Z);
fclose(fp);
…….
equivalgono a:
fscanf(stdin, stringa_formato, indir_elementi);
fprintf(stdout, stringa_formato, elementi);
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
// Visualizzazione contenuto di un file testo
#include <stdio.h>
int main() {
char buf[80];
FILE *fp;
fp=fopen("testo.txt", "r");
if(fp != NULL) {
while(!feof(fp)) {
if(fscanf(fp,"%s",buf) > 0)
printf("%s ", buf);
}
fclose(fp);
} else printf("Errore apertura file ! " );
return 0;
}
Oppure:
……….
if (fp != NULL) {
while (fscanf(fp,"%s", buf)>0)
printf("%s ", buf);
fclose(fp)
} else printf ("Errore apertura file ! " );
…………
// Scrittura su file testo: elenco nominativi
#include <stdio.h>
#include <string.h>
int main() {
char item[80];
FILE *fp;
fp=fopen("testo.txt", "w");
if(fp != NULL) {
printf("Inizio inserimento (0 - per finire):\n");
printf("Nominativo: ");
scanf("%s", item);
while(strcmp(item,"0") != 0) {
fprintf(fp, "%s\n", item);
printf("Nominativo: ");
scanf("%s", item);
}
fclose(fp);
} else printf("Errore apertura file !" );
return 0;
}
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
b)
Lettura/scrittura di caratteri:
Funzioni simili a getchar e putchar, ma con un parametro aggiuntivo che rappresenta il puntatore al file sul quale si
vuole leggere o scrivere:
int fgetc (FILE *fp);
int fputc (int c, FILE *fp);
( esiste anche la getc() )
( esiste anche la putc() )
Nota: In caso di esecuzione corretta, restituiscono
rispettivamente il carattere letto o scritto come
intero (no char), altrimenti EOF.
Esempi:
FILE *fp;
int c;
// apertura file
……
c = fgetc(fp);
FILE *fp;
int c = 'A';
// apertura file
……
fputc(c, fp);
Esercizio: in aggiunta all’esempio a fianco, far
scrivere i caratteri in un altro file.
// Conta numero di caratteri numerici in un file.
#include <stdio.h>
int main() {
FILE *fp;
int c, nc=0;
fp = fopen("c:\\documenti\\risultati.txt", "r");
if(fp != NULL) {
while( (c=fgetc(fp)) != EOF )
if ( (c >= '0') && (c <= '9') ) nc++;
printf("Numero di caratteri numerici: %d", nc);
fclose(fp);
} else printf("Errore apertura file !" );
return 0;
}
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
c) Lettura/scrittura di stringhe di caratteri:
in questo caso abbiamo funzioni simili a gets e puts:
char *fgets(char *s, int n, FILE *fp);
Trasferisce nella stringa s i caratteri letti dal file puntato da fp; i caratteri trasferiti sono n-1 oppure un numero
inferiore se si incontra newline o la fine del file. La funzione fgets restituisce il puntatore a carattere: coincide con la
stringa letta se tutto è andato bene, vale NULL in caso di errore o il file pointer sia a fine file.
La funzione aggiunge automaticamente il carattere di fine stringa \0.
int *fputs(char *s, FILE *fp);
Trasferisce la stringa s nel file puntato da fp. Non copia il carattere terminatore \0 nè aggiunge un newline finale.
La funzione restituisce l'ultimo carattere scritto in caso di terminazione corretta; EOF altrimenti.
Esercizio1: creare un programma conta caratteri che:
-
Usi le funzioni fgets() e fputs();
Prenda in input un file di testo (input.txt);
Per ogni riga calcoli il numero dei caratteri presenti nella riga;
Scriva la riga su un altro file (output.txt) aggiungendo il numero dei caratteri calcolato.
Esercizio2: creare un programma che conti le righe di un file passato da riga di comando.
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
Lettura/scrittura di blocchi (file binari):
Da un file binario possiamo leggere/scrivere un intero blocco di dati. Esso deve essere aperto in modalità binaria
("b"). Un file binario memorizza dati di qualunque tipo, in particolare dati che non sono caratteri (interi, reali,
vettori o strutture).
Nota: Il test di fine del file viene ottenuto con la funzione feof .
int fread(void *vet, int size, int n, FILE *fp);
La funzione fread legge n "elementi" dal file puntato da fp inserendoli nel vettore vet, ciascuno di dimensione size.
Restituisce un intero che rappresenta il numero di elementi effettivamente letti.
Esempio:
…….
FILE *fp;
int vet[10], x;
fp=fopen("valori.txt", "rb");
x=fread(vet, sizeof(int),10, fp);
printf("Valori effettivamente letti: %d\n", x);
for (i=0; i<10; i++) printf("%d ",vet[i]);
……
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
int fwrite(void *vet, int size, int n, FILE *fp);
La funzione fwrite scrive sul file puntato da fp n elementi del vettore vet, ciascuno di dimensione size. Restituisce
un intero che rappresenta il numero di oggetti effettivamente scritti (inferiore ad n solo in caso di errore).
Esempio:
…….
FILE *fp;
int vet[10];
int i, x=0;
for (i=0; i<10; i++) vet[i]=i;
fp=fopen("valori.txt", "wb");
x=fwrite(vet, sizeof(int),10, fp);
printf("Valori effettivamente scritti: %d\n", x);
…….
Oppure:
……
fp=fopen("valori.txt", "wb");
for(i=0; i<10; i++)
x += fwrite(&i, sizeof(int),1, fp);
…….
Esercizio: programma che richieda in input il nome di un file e scriva in questo file un vettore di float.
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
/* Programma che scrive una sequenza di record
(dati da input) in un file binario */
#include<stdio.h>
typedef struct {
char nome[20];
char cognome[20];
int eta;
} persona;
int main() {
FILE *fp;
persona p;
int fine=0;
if((fp=fopen("elenco.dat","wb")) != NULL) {
do {
printf("Dati persona?");
scanf("%s%s%d",p.nome, p.cognome, &p.eta);
fwrite(&p,sizeof(persona),1,fp);
printf("Fine (si=1,no=0)?");
scanf("%d", &fine);
} while(fine == 0);
fclose(fp);
} else printf("Errore apertura file !" );
return 0;
}
/* Programma che legge e stampa il contenuto di un
file binario */
#include<stdio.h>
typedef struct {
char nome[20];
char cognome[20];
int eta;
} persona;
int main() {
FILE *fp;
persona p;
if((fp=fopen("elenco.dat","rb")) != NULL) {
fread(&p, sizeof(persona),1, fp);
while(!feof(fp)) {
printf("%s %s %d\n",p.nome, p.cognome, p.eta);
fread(&p,sizeof(persona),1,fp);
}
fclose(fp);
} else printf("Errore apertura file !" );
return 0;
}
Oppure: if((fp=fopen("elenco.dat","rb")) != NULL) {
while(1) {
if(fread(&p,sizeof(persona),1,fp) == 0) break;
printf("%s %s %d\n",p.nome, p.cognome, p.eta); }
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
Funzione fseek():
In C, oltre al modo sequenziale è possibile operare su file di byte anche in modalità random. La funzione fseek
permette di muovere il puntatore di lettura/scrittura in una qualunque posizione all’interno del file.
int fseek(FILE *fp, long offset, int whence);
fp
: è il file pointer;
offset : indica di quanti byte il file pointer deve essere spostato; se negativo lo spostamento è all’indietro.
whence : indica a partire da quale posizione muovere il file pointer:
0 (SEEK_SET) : inizio file
1 (SEEK_CUR): posizione corrente
2 (SEEK_CUR): fine file.
La funzione fseek ritorna un valore negativo se si è verificato un errore, altrimenti uguale o maggiore di 0.
Es.: int err, mode=0;
FILE *fp ;
long n=10L ;
err = fseek(fp, n, mode) ; // il file pointer è posizionato sul decimo byte.
La funzione ftell() ritorna la posizione corrente del file pointer (fp): long ftell(FILE *fp);
Es.: FILE *fp ;
long n;
n = ftell(fp) ;
Nota: la ftell ritorna il numero di byte dall’inizio del file fino alla posizione corrente.
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
Funzione fflush():
In genere le operazioni di lettura/scrittura lavorano in modalità bufferizzata; ad esempio le operazioni di
scrittura non vengono singolarmente eseguite su disco, ma vengono temporaneamente memorizzate su dei
buffers per ottimizzare le prestazioni.
Anche in fase di lettura da disco il sistema cerca di trasferire in memoria centrale una quantità di informazioni
superiore a quella richiesta dal programmatore, al fine di ridurre il numero di letture e quindi di accesso a disco.
Al momento della chiusura di un file o al termine dell’esecuzione del programma il contenuto dei buffer viene
scaricato su disco.
La funzione fflush() assolve il compito di scaricare il contenuto del buffer associato al file pointer;
es.:
FILE *fp;
fp = fopen("nomefile", "w");
fprint(fp, "stringa di testo");
….....
fflush(fp);
………
Per disabilitare la bufferizazzione su di un file pointer (fp), si può usare la funzione:
setbuf(fp, NULL);
ad esempio per lo standard di output: setbuf(stdout, NULL);
Corso di Informatica 2
A.A 2015/16
Linguaggio C – Gestione File
Esercizi:
- Programma che concateni due file binari, i cui nomi sono passati come parametri.
- Programma "copyfile" che faccia la copia (testo/binaria) di un file in un altro, acquisiti come parametri;
esempio esecuzione: copyfile.exe nomefile1 nomefile2
Corso di Informatica 2
A.A 2015/16