Operazioni di I/O da console e da file in C standard Sono eseguite attraverso funzioni di libreria...
-
Upload
tonia-martini -
Category
Documents
-
view
219 -
download
0
Transcript of Operazioni di I/O da console e da file in C standard Sono eseguite attraverso funzioni di libreria...
Operazioni di I/Oda console e da file
in C standard
• Sono eseguite attraverso funzioni di libreria
• Non differiscono molto se rivolte a console o a file
• Richiedono l’header <stdio.h>
Operazioni standard di I/Oda console - 1
Sono il più possibile portabili, per cui• Non comprendono la gestione dello
schermo né il posizionamento del cursore
• Non comprendono la gestione di sistemi a finestre (p.es. Windows)
• Permettono di scrivere in formato di puro testo (p.es. console DOS o Unix)
Operazioni standard di I/Oda console - 2
• Accettano input dallo standard input(stdin, generalmente la tastiera)
• Producono output verso lo standard output(stdout, generalmente lo schermo)
I canali standard di input e output non sono altro che file “speciali”
Output su console : Caratteri
• int putchar( int c );– Converte il carattere in int
e ignora il byte più significativo– Restituisce il carattere scritto
oppure EOF in caso di errore
Input da console : Caratteri - 1
• int getchar( void );• int getche( void );• int getch( void );
– Convertono il carattere in int e ignorano il byte più significativo
– Restituiscono il carattere letto oppure EOF in caso di errore
Input da console : Caratteri - 2
bufferizzata
echo ANSI
getchar
getche getch
…char ch, str[81];int i = 0;
do {ch = getche(); // o getch(); o getchar(); fflush();str[ i++ ] = ch;
} while( ch != '.' && i < 80 );str[i] = '\0'; // va inserito esplicitamente
i = 0;while( str[i] != '\0' )
putchar( str[ i++ ] );…
console_c
Output su console : Stringhe
• int puts( const char* str );– Rimpiazza il carattere nullo di
terminazione ('\0') con il ritorno a capo ('\n')
– Riconosce i caratteri speciali ('\t', '\n'… )– Restituisce un intero non negativo
oppure EOF in caso di errore
Input da console : Stringhe
• char* gets( char* str );– Rimpiazza il ritorno a capo ('\n')
con il carattere nullo di terminazione ('\0')
– Restituisce str oppure NULL in caso di errore
– NON fa alcun controllo sulla dimensione del buffer rappresentato da str
#include <stdio.h>
void main(){
char str[81];
puts( "\n Scrivi una parola o frase e premi " "<invio> (max.80 caratteri):" );
gets( str );
puts( "\n La riga inserita e\':" );puts( str );
}
console_s
Operazioni standard di I/Oda file - 1
• Si opera su stream (detti anche canali)• Ad ogni stream si associa un
file/periferica/dispositivo• Lo stream fornisce un livello di
astrazione comune per tutti i dispositivi fisici
la funzione di scrittura su uno stream resta la stessa indipendentemente dalla periferica sulla quale si deve scrivere (disco, video, stampante, …)
Operazioni standard di I/Oda file – 2
• Si parla genericamente di file per indicare in realtà un file/dispositivo/periferica
• Gli stream sono tutti uguali, i file no• Se il file lo permette, lo stream prevede
–operazioni bufferizzate per ottimizzare gli accessi al file
–operazioni di posizionamento per accedere ai dati in ordine diverso rispetto a quello in cui si trovano nel file
Operazioni standard di I/Oda file – 3
• Lo stream è rappresentato nel programma da una variabile di tipo FILE*
–La struttura FILE contiene le informazioni relative all’identificazione, all’utilizzo e allo stato del file
–Tutte le operazioni di I/O su file avvengono attraverso questa variabile
• Tra l’operazione di apertura (fopen) e di chiusura (fclose) dello stream esiste un canale di comunicazione tra programma e file
Output su file : Caratteri
• intfputc( int c, FILE* stream );• intputc( int c, FILE* stream );
– Convertono il carattere in int e ignorano il byte più significativo
– Restituiscono il carattere scritto oppure EOF in caso di errore
– Spostano la posizione all’interno del file sul prossimo carattere “libero”
Input da file : Caratteri
• int fgetc( FILE* stream );• int getc( FILE* stream );
– Convertono il carattere in int e ignorano il byte più significativo
– Restituiscono il carattere letto oppure EOF in caso di errore o fine del file
– Spostano la posizione all’interno del file
sul prossimo carattere
…int i;char ch;FILE *fpSrc, *fpDest;
if( (fpSrc = fopen( "src.txt", "r" )) == NULL ) {puts( "Errore durante l'apertura di
src.txt" );exit(1);
}
if( (fpDest = fopen( "dest.txt", "w" )) == NULL ) {puts( "Errore durante la creazione di
dest.txt" );exit(2);
}
file_c - 1
i = 0;while( (ch = fgetc( fpSrc )) != EOF ) {
fputc( ch, fpDest );printf( "\nCarattere n.%d (%c)"
"\tPremi un tasto...", i++, ch );getch();
}
fclose( fpDest );fclose( fpSrc );
puts( "Copia effettuata." );…
file_c – 2
Output su file : Stringhe
• int fputs( const char* str, FILE* stream );– Copia la stringa sul file sino al
carattere nullo di terminazione (escluso)– Riconosce i caratteri speciali– Restituisce un intero non negativo
oppure EOF in caso di errore– Sposta la posizione all’interno del file
sul prossimo carattere “libero”
Input su file : Stringhe - 1
• char* fgets( char* str, int n, FILE* stream );– Copia la stringa dal file sino al primo
evento/carattere tra i seguenti: carattere di ritorno a capo (incluso) numero massimo n-1 di caratteri letti carattere di fine del file (escluso)
Input su file : Stringhe - 2
– Implementa attraverso n un controllo sulla dimensione del buffer (str)
– Aggiunge il carattere nullo di terminazione alla fine della stringa nel buffer
– Restituisce str oppure NULL in caso di errore o fine del file
– Sposta la posizione all’interno del file sul prossimo carattere “libero”
…int i, n = 81;char* str[81];FILE *fpSrc, *fpDest;…i = 0;while( fgets( str, n, fpSrc ) != NULL ) {
fputs( str, fpDest );printf( "\nRiga n.%d (%s)"
"\tPremi un tasto...", i++, str );getch();
}…
file_s
Output su file : Byte
• size_t fwrite( void* mem, size_t size, size_t n, FILE* stream
);– Copia dalla zona di memoria sul file
n elementi grandi size byte ognuno– Restituisce il numero di elementi scritti
(minore di n in caso di errore)– Sposta la posizione all’interno del file
del numero di byte scritti
Input da file : Byte
• size_t fread( void* mem, size_t size, size_t n, FILE*
stream );– Copia dal file nella zona di memoria
n elementi grandi size byte ognuno– Restituisce il numero di elementi letti
(minore di n in caso di errore o fine del file)– Sposta la posizione all’interno del file
del numero di byte letti
…struct memo_t {
char nome[81];int anni;
};int vet[3] = { 8, -1, 5 };double db = 3.2e-6;struct memo_t pers;FILE* fpDest;…fwrite( vet, sizeof( int ), 3, fpDest );fwrite( &db, sizeof( double ), 1, fpDest );fwrite( &pers, sizeof( struct memo_t ), 1, fpDest );…
file_b
Modo testo e modo binario - 1
• Uno stream può essere aperto in modalità testo oppure in modalità binaria ('b')
• Uno stream di testo è visto come– una sequenza di caratteri – una sequenza di righe separate dal ritorno a
capo
• Uno stream binario è visto come– una sequenza indistinta di byte
• Su entrambi si può scrivere ogni tipo di dati
Modo testo e modo binario - 2
• Uno stream di testo PUÒ prevedere operazioni di traduzione (NL CR/LF)– Può mancare la corrispondenza 1:1 tra
caratteri nello stream e caratteri nel file
• Uno stream binario NON prevede nessuna operazione di traduzione– Sussiste la corrispondenza 1:1 tra
caratteri nello stream e caratteri nel file
…char str[81] = "Oggi e\' proprio\nuna bella giornata.\n"
"Quasi quasi faccio\nun giro in bici.";char ch;int n;FILE *fpText, *fpBin;
fpBin = fopen( "esempio.dat", "wb" );…fpText = fopen( "esempio.txt", "wt" );…printf( "\nLunghezza della stringa in memoria: "
"%d byte\n", strlen( str ) );
modo_t_b - 1
n = fwrite( str, sizeof( char ), strlen( str ), fpBin );printf( "\n%d caratteri scritti su esempio.dat\n", n );
n = fwrite( str, sizeof( char ), strlen( str ), fpText );printf( "\n%d caratteri scritti su esempio.txt", n );
printf( "\nLunghezza di esempio.dat: %d byte\n", ftell( fpBin ) );
printf( "\nLunghezza di esempio.txt: %d byte", ftell( fpText ) );
fclose( fpText );fclose( fpBin );…
modo_t_b - 2
…fpBin = fopen( "esempio.dat", "rb" );fpText = fopen( "esempio.txt", "rb" ); // come binario
puts( "\nByte scritti in esempio.dat:" );n = 0;while( fread( &ch, sizeof( char ), 1, fpBin ) != 0 ) {
printf( "%02X ", ch );if( ch == 0x0A ) puts( "" ); // va solo a capon++;
}printf( "\nTotale byte: %d\n", n );
modo_t_b - 3
puts( "\nByte scritti in esempio.txt:" );n = 0;while( fread( &ch, sizeof( char ), 1, fpText ) != 0 ) {
printf( "%02X ", ch );if( ch == 0x0A ) puts( "" ); // va solo a capon++;
}printf( "\nTotale byte: %d\n", n );
fclose( fpBin );fclose( fpText );…
modo_t_b - 4
Lunghezza della stringa in memoria: 71 byte
71 caratteri scritti su esempio.dat
71 caratteri scritti su esempio.txt
Lunghezza di esempio.dat: 71 byte
Lunghezza di esempio.txt: 74 byte
Byte scritti in esempio.dat:
4F 67 67 69 20 65 27 20 70 72 6F 70 72 69 6F 0A
75 6E 61 20 62 65 6C 6C 61 20 67 69 6F 72 6E 61 74 61 2E 0A
51 75 61 73 69 20 71 75 61 73 69 20 66 61 63 63 69 6F 0A
75 6E 20 67 69 72 6F 20 69 6E 20 62 69 63 69 2E
Totale byte: 71
Byte scritti in esempio.txt:
4F 67 67 69 20 65 27 20 70 72 6F 70 72 69 6F 0D 0A
75 6E 61 20 62 65 6C 6C 61 20 67 69 6F 72 6E 61 74 61 2E 0D 0A
51 75 61 73 69 20 71 75 61 73 69 20 66 61 63 63 69 6F 0D 0A
75 6E 20 67 69 72 6F 20 69 6E 20 62 69 63 69 2E
Totale byte: 74
modo_t_b - 5
Accesso sequenziale e accesso diretto
Esistono due modalità con cui accedere ai dati contenuti in un file:
• Accesso sequenziale– Per accedere all’i-esimo dato occorre
accedere a tutti quelli precedenti
– Orientato ad operazioni globali
• Accesso diretto o random– Si può accedere direttamente al dato i-esimo– Orientato ad operazioni locali
Posizionamento su file - 1
• int fseek( FILE* stream, long n, int origine );
– Sposta la posizione all’interno del file di n byte a partire dalla posizione specificata dalla macro origine
– Restituisce 0 in caso di successo oppure un intero diverso da 0 in caso di errore
Posizionamento su file - 2
macro int posizione
SEEK_SET 0 dall’inizio del file
SEEK_CUR 1dalla posizione corrente
SEEK_END 2 dalla fine del file
Posizionamento su file - 3
• void rewind( FILE* stream );– Riporta all’inizio (“riavvolge”)
la posizione all’interno del file
• long ftell( FILE* stream );– Restituisce la posizione corrente all’interno
del file oppure -1 in caso di errore– In genere è usata in coppia con fseek
…int vet[5] = { 21, -1, 8, -17, 33 };int n, i = 3;FILE *fpDest;…fwrite( vet, sizeof( int ), 5, fpDest );
fseek( fpDest, i*sizeof( int ), SEEK_SET );fread( &n, sizeof( int ), 1, fpDest );printf( "\nElemento n.%d: %d", i, n );
fseek( fpDest, 0, SEEK_END );n = (int) ftell( fpDest ); // numero di byte del fileprintf( "\nNumero di elementi: %d\n", n/sizeof( int ) );…
file_pos1
Posizionamento su file - 4
• int fgetpos( FILE* stream, fpos_t* pos );• int fsetpos( FILE* stream, fpos_t* pos );
– Legge/scrive il valore dell’indicatore della posizione corrente all’interno del file
– Restituiscono 0 se l’operazione è riuscita oppure un intero diverso da 0 in caso di errore
– DEVONO essere usate in coppia perché l’indicatore usa un formato interno speciale
…int vet[5] = { 21, -1, 8, -17, 33 };int num;fpos_t segnaposto;FILE *fpDest;…fwrite( vet, sizeof( int ), 3, fpDest );fgetpos( fpDest, &segnaposto );fwrite( &vet[3], sizeof( int ), 2, fpDest );// oppure fwrite( vet+3, …
fsetpos( fpDest, &segnaposto );fread( &num, sizeof( int ), 1, fpDest );printf( "\nL\'elemento in posizione %d "
"vale %d\n", segnaposto, num );…
file_pos4
Controlli su file
• int feof( FILE* stream );– Restituisce un intero diverso da 0 se la
posizione corrente è sulla fine del file, viceversa restituisce 0
• int ferror( FILE* stream );– Restituisce un intero diverso da 0 se ci
sono stati errori sul file, viceversa restituisce 0
…char str[100];FILE *fpSrc…while( !feof( fpSrc ) ) {
fread( str, sizeof( char ), 100, fpSrc );if( ferror( fpSrc ) ) {
puts( “Errore durante la lettura!" );break;
}}puts( “Fine del file raggiunta." );fclose( fpSrc );…
file_verif
Buffer associato a file
• int fflush( FILE* stream );– Svuota sul file il buffer temporaneo usato
per ottimizzare l’accesso al file– Se si passa NULL come argomento
opera su tutti i file aperti in scrittura– Restituisce 0 se l’operazione è riuscita
oppure EOF in caso di errore
Redirezione di file
• FILE* freopen( const char* path, const char* mode, FILE* stream );
– Chiude il file associato a stream e assegna quest’ultimo al file avente percorso path
– Restituisce un puntatore al file appena aperto oppure NULL in caso di errore(il file iniziale viene comunque chiuso)
…FILE *fpDest;
fpDest = freopen( "output.txt", "w", stdout );…fputs( "Questa andra\' sul file output.txt\n", fpDest );
puts( "Anche questa fatta col semplice \'puts\'\n" );
printf( "E anche con \'printf\': %d.\n", 5 );
fclose( fpDest );
fputs( "E questa verso \'stdout\' ?\n", stdout );fputs( "E questa verso \'stderr\' ?\n", stderr );…
freopen
Operazioni di I/Oin C ++
Obiettivi del sistema di I/O
Gli stream
Tipi di stream
File
Classi di stream
Apertura e chiusura
Lettura e scrittura
Obiettivi
• Descrive come sottoporre a overload gli operatori << e >> in modo da ottenere l’input e l’output di oggetti appartenenti a classi scritte dal programmatore
• Come formattare l’output
• Come utilizzare i manipolatori di I/O
• Il funzionamento dell’I/O su file
Stream
• È un’interfaccia logica mediante la quale vengono effettuate le operazioni di I/O
• Produce e consuma informazioni ed è collegato ad un dispositivo fisico tramite il sistema di I/O del C++
– È comune per i vari dispositivi che costituiscono il computer
– Il comportamento è identico per tutti gli stream anche se sono
collegati a dispositivi differenti.
• Per il programmatore tutti i dispositivi risultano simili tra loro
– Le operazioni di I/O possono operare su tutti i tipi di dispositivo.
Stream predefinti
• cin: associato allo standard input
• cout: associato allo standard output
– collegati a cout:
• clog: è bufferizzato, l’output è scritto solo dopo che il buffer è pieno
• cerr: non è bufferizzato, l’oiutout è scritto non appena è inviato
• versioni a caratteri estesi( a 16 bit)
– wcin, wcout, wclog, wcerr
Classi di stream
• Il supporto al sistema di I/O del C++ è fornito dall’intestazione standard
• <iostream>
– definisce un insieme di gerarchie di classi che supportano le
operazioni di I/O
• Si fonda su due gerarchie di classi correlate ma diverse:
– basic_streambuf
• classe di basso livello
• fornisce supporto per le operazioni di basso livello
– basic_ios
• classe di alto livello
• fornisce formattazione, controllo di errore e informazioni di stato in
relazione all’I/O
Classi a caratteri
• Ios
– contiene funzioni e variabili membro che controllano il funzionamento di uno stream
– costituisce la classe base per molte classi derivate:
• streambuf
• ios
• istream
• ostream
• iostream
• fstream Stream associati ai file
• ifstream “
• ofstream “
Overload degli operatori di I/O
• È possibile effettuare l’overload degli operatori
– << operatore di inserimento:
• inserisce caratteri in uno stream
– >>operatore di estrazione:
• estrae caratteri da uno stream
– In <iostream>, gli operatori << e >> sono
soggetti ad overload per effettuare I/O su tutti i tipi di dati predefiniti
I/O su file
• l sistema di I/O può essere usato per effettuare I/O su file
• È necessaria l’intestazione <fstream>
Apertura
• Apertura di uno stream di input
– Occorre dichiarare che appartiene alla classe <ifstream>
• Apertura di uno stream di output
– Occorre dichiarare che appartiene alla classe <ofstream>
• Apertura di uno stream che eseguirà operazioni di input e di output
– Occorre dichiarare che appartiene alla classe <fstream>
Funzione open
• open()
• associa uno stream ad un file
• membro di tutte le tre classi stream
– Argomenti della funzione
• Nomefile: può contenere anche il path
• Modalità di apertura: determina come verrà aperto il file
– Il valore è determinato da openmode
– app: aggiunge l’output alla file del file
– ate: ricerca la fine del file ma lo apre in modo che le operazioni
possano avvenire in qualunque posizione
– binary: apre il file in modalità binaria
– in: il file è in grado did produrre dati
– out: specifica che il file è in grado di ricevere output
– trunc: distrugge il contenuto del file preesistente
– OR di due qualsiasi dei precedenti (|)
Esempio apertura un file di output:
ofstream out;
out.open(“test”);
la modalità di apertura in alcuni compilatori è per default un valore appropriato al tipo di stream aperto
Apertura mediante costruttore
• ifstream, ofstream e fstream hanno
funzioni costruttore che provvedono automaticamente all’apertura del file
• i costruttori hanno gli stessi parametri e valori di default della funzione open
Esempio
Apertura di un file per l’input mediante il costruttore
ifstream mystream(“test”);
Chiusura
Si usa la funzione close
out.close();
La funzione non ha parametri e non restituisce valori
Lettura e scrittura
• Si usano gli operatori<<>>
Esempio di scrittura su un file testo
#include <iostream>#include <fstream>using namespace std;void main(){ofstream out(“test”);if (!out) {cout << “impossible aprire il file”;}out<<10<<“ “<123.23<<“\n”;out<< file di testo”;out.close();}
Esempio di lettura da un file testo
#include <iostream>#include <fstream>using namespace std;void main(){char ch;int i;float f;char str[80];ifstream in(“test”);if (!in) { cout<< “ Impossible aprire il file”;}in>>i; in>>f;in >>ch; in >> str;cout<< i <<“ “ <<f<<“ “ <<ch<<“\n”;cout<<str,in.close();}
Lettura e scrittura di file binari non formattati
• Può avvenire in due modi:• Usando funzioni– a byte• put ()• get()– a blocchi• read()• write()
Uso della get#include<iostream>#include<fstream>using namespace std;void main(){char ch;ifstream in”test” ios::in | ios::binary);if(!in){ cout<<“impossibile aprire il file”;}while (in){// in è falso quando si raggiunge la fine del filein.get(ch);if(in) cout <<ch;}in.close();}
Uso della funzione put
#include<iostream>#include<fstream>using namespace std;void main(){char *s=“stringa di prova”;ofstream out(”test”, ios::out | ios::binary);if(!out){ cout<<“impossibile aprire il file”;}while (*s) out.put(*s++);out.close();}
Funzioni read e write• read:• Legge un numero num di byte dallo stream associato e li mette nel buffer
• write:• Scrive sullo stream associato un numero num di byte provenienti dal buffer
Uso della funzione write#include<iostream>#include<fstream>using namespace std;void main(){char s[80]=“stringa”;int i;ofstream out(“test”, ios::out | ios::binary);if(!out) {cout<<“Impossibile aprire il file”;}out.write(s, sizeof(s));cout<<“ scrittura “<<“\n”;in.close();}
Uso della funzione read
#include<iostream>#include<fstream>using namespace std;void main(){char s[80];int i;ifstream in(“test”, ios::in | ios::binary);if(!in) {cout<<“Impossibile aprire il file”;}in.read(s, sizeof(s));cout<<“ scrittura “<<“\n”;cout<<s;in.close();}
Accesso casuale• La lettura e la scrittura può avvenire in modo casuale.• Si usano le funzioni seekg, seekp, specificando i valori di:
– Offset: un intero che specifica il numero di byte di cui spostarsi– Origine: la posizione a partire dalla quale spostarsi
ios::begios::curios::end
Puntatori al file• get:– specifica in che punto del file avverrà la successiva operazione di input• put– specifica in che punto del file avverrà la successiva operazione di output
• Ogni volta che viene effettuata un’operazione il puntatore appropriato viene fatto avanzare automaticamente
Uso delle funzioni seekg e seekp• Seekg()– Sposta il puntatore get correntemente associato al file di un numero offset di byte a partire dal punto specificato da origine• Seekp()– Sposta il puntatore put correntemente associato al file di un numero offset di byte a partire dal punto specificato da origine
Esempi di uso di seekg e seekp#include<iostream>#include<fstream>using namespace std;void main(){int i;ftsream out(“test”, ios::in | ios::out | ios:: binary);if (!out) {cout<<impossibile aprire il file;}out.seekp(atoi(“test”),ios::beg);out.put(“x”);out.close();}
#include<iostream>
#include<fstream>
using namespace std;
void main()
{
int i;
ifstream in(“test”,ios::in|ios::binary);
if(!in){cout<<“impossibile aprire il file”;}
in.seekg(atoi(“test”),ios::beg);
while (in.get(ch)) cout <<ch;
}
Funzioni per determinare la posizione corrente dei puntatori
• pos_type tellg();
• pos_type tellp();