X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=filestd.tex;h=14867d51305f3577f41127638d4698390ee0e167;hp=dcbb3381f146bb7cd6d0141571274232de019601;hb=b9ab696dcd693cb09fb09be5065f487c814c6f03;hpb=a76ef671288ddb656f3a4aa599cfda5e05491c39 diff --git a/filestd.tex b/filestd.tex index dcbb338..14867d5 100644 --- a/filestd.tex +++ b/filestd.tex @@ -223,15 +223,16 @@ prototipi sono: stream)} Apre il file specificato da \param{path} associandolo allo stream specificato da \param{stream}, se questo è già aperto prima lo chiude. - - Le funzioni ritornano un puntatore valido in caso di successo e \macro{NULL} - in caso di errore, in tal caso \var{errno} viene settata al valore ricevuto - dalla funzione sottostante di cui è fallita l'esecuzione. - Gli errori pertanto possono essere quelli di \func{malloc} per tutte e tre - le funzioni, quelli \func{open} per \func{fopen}, quelli di \func{fcntl} per - \func{fdopen} e quelli di \func{fopen}, \func{fclose} e \func{fflush} per - \func{freopen}. + \bodydesc{Le funzioni ritornano un puntatore valido in caso di + successo e \macro{NULL} in caso di errore, in tal caso \var{errno} + viene settata al valore ricevuto dalla funzione sottostante di cui è + fallita l'esecuzione. + + Gli errori pertanto possono essere quelli di \func{malloc} per tutte + e tre le funzioni, quelli \func{open} per \func{fopen}, quelli di + \func{fcntl} per \func{fdopen} e quelli di \func{fopen}, + \func{fclose} e \func{fflush} per \func{freopen}.} \end{functions} Normalmente la funzione che si usa per aprire uno stream è \func{fopen}, @@ -341,10 +342,11 @@ Uno stream viene chiuso con la funzione \func{fclose} il cui prototipo \begin{prototype}{stdio.h}{int fclose(FILE * stream)} Chiude lo stream \param{stream}. - Restituisce 0 in caso di successo e \macro{EOF} in caso di errore, nel qual - caso setta \var{errno} a \macro{EBADF} se il file descriptor indicato da - \param{stream} non è valido, o uno dei valori specificati dalla sottostante - funzione che è fallita (\func{close}, \func{write} o \func{fflush}). + \bodydesc{Restituisce 0 in caso di successo e \macro{EOF} in caso di errore, + nel qual caso setta \var{errno} a \macro{EBADF} se il file descriptor + indicato da \param{stream} non è valido, o uno dei valori specificati + dalla sottostante funzione che è fallita (\func{close}, \func{write} o + \func{fflush}).} \end{prototype} La funzione effettua uno scarico di tutti i dati presenti nei buffer di @@ -360,7 +362,7 @@ prototipo \begin{prototype}{stdio.h}{int fcloseall(void)} Chiude tutti gli stream. - Restituisce 0 se non ci sono errori ed \macro{EOF} altrimenti. + \bodydesc{Restituisce 0 se non ci sono errori ed \macro{EOF} altrimenti.} \end{prototype} la funzione esegue lo scarico dei dati bufferizzati in uscita e scarta quelli in ingresso, chiudendo tutti i file. Questa funzione è provvista solo per i @@ -432,7 +434,7 @@ ogni volta che si chiama una funzione di libreria. Entrambi i flag (di errore e di end-of-file) possono essere cancellati usando la funzione \func{clearerr}, il cui prototipo è: -\begin{prototype}{stdio.h}{void clearerr( FILE *stream)} +\begin{prototype}{stdio.h}{void clearerr(FILE *stream)} Cancella i flag di errore ed end-of-file di \param{stream}. \end{prototype} \noindent in genere si usa questa funziona una volta che si sia identificata e @@ -457,13 +459,12 @@ formattati. Le due funzioni che si usano per l'I/O binario sono: \funcdecl{size\_t fwrite(const void * ptr, size\_t size, size\_t nmemb, FILE * stream)} - Le funzioni rispettivamente leggono e scrivono \param{nmemb} elementi - di dimensione \param{size} dal buffer \param{ptr} al file - \param{stream}. + Rispettivamente leggono e scrivono \param{nmemb} elementi di dimensione + \param{size} dal buffer \param{ptr} al file \param{stream}. - Entrambe le funzioni ritornano il numero di elementi letti o scritti, - in caso di errore o fine del file viene restituito un numero di - elementi inferiore al richiesto. + \bodydesc{Entrambe le funzioni ritornano il numero di elementi letti o + scritti, in caso di errore o fine del file viene restituito un numero di + elementi inferiore al richiesto.} \end{functions} In genere si usano queste funzioni quando si devono trasferire su file @@ -557,8 +558,8 @@ gestione delle applicazioni multi-thread (si veda \funcdecl{size\_t fwrite\_unlocked(const void * ptr, size\_t size, size\_t nmemb, FILE * stream)} - Le funzioni sono identiche alle analoghe \func{fread} e \func{fwrite} - ma non acquisiscono il lock implicito sullo stream. + \bodydesc{Le funzioni sono identiche alle analoghe \func{fread} e + \func{fwrite} ma non acquisiscono il lock implicito sullo stream.} \end{functions} \noindent entrambe le funzioni sono estensioni GNU previste solo dalle \acr{glibc}. @@ -568,10 +569,9 @@ gestione delle applicazioni multi-thread (si veda \label{sec:file_char_io} La seconda modalità di input/output è quella a caratteri, in cui si -trasferisce un carattere alla volta. - -Le funzioni per la lettura a caratteri sono tre, \func{fgetc}, -\func{getc} e \func{getchar}, i rispettivi prototipi sono: +trasferisce un carattere alla volta. Le funzioni per la lettura a +caratteri sono tre, \func{fgetc}, \func{getc} e \func{getchar}, i +rispettivi prototipi sono: \begin{functions} \headdecl{stdio.h} @@ -581,11 +581,11 @@ Le funzioni per la lettura a caratteri sono tre, \func{fgetc}, \funcdecl{int fgetc(FILE *stream)} Legge un byte da \param{stream} e lo restituisce come intero. È una sempre una funzione. - \funcdecl{int getchar(void)} è equivalente a \func{getc(stdin)}. + \funcdecl{int getchar(void)} Equivalente a \func{getc(stdin)}. - Tutte queste funzioni leggono un byte alla volta, che viene restituito - come intero; in caso di errore o fine del file il valore di ritorno è - \macro{EOF}. + \bodydesc{Tutte queste funzioni leggono un byte alla volta, che viene + restituito come intero; in caso di errore o fine del file il valore + di ritorno è \macro{EOF}.} \end{functions} A parte \func{getchar}, che si usa in genere per leggere un carattere da @@ -608,7 +608,7 @@ ad \type{int} (si usa \type{unsigned char} in modo da evitare l'espansione del segno). In questo modo il valore di ritorno è sempre positivo, tranne in caso di errore o fine del file. -Nelle estenzioni GNU che provvedono la localizzazione sono definite tre +Nelle estensioni GNU che provvedono la localizzazione sono definite tre funzioni equivalenti alle precedenti che invece di un carattere di un byte restituiscono un carattere in formato esteso (cioè di tipo \type{wint\_t}, il loro prototipo è: @@ -621,10 +621,10 @@ byte restituiscono un carattere in formato esteso (cio \funcdecl{wint\_t fgetwc(FILE *stream)} Legge un carattere esteso da \param{stream} È una sempre una funzione. - \funcdecl{wint\_t getwchar(void)} è equivalente a \func{getwc(stdin)}. + \funcdecl{wint\_t getwchar(void)} Equivalente a \func{getwc(stdin)}. - Tutte queste funzioni leggono un carattere alla volta, in caso di - errore o fine del file il valore di ritorno è \macro{WEOF}. + \bodydesc{Tutte queste funzioni leggono un carattere alla volta, in + caso di errore o fine del file il valore di ritorno è \macro{WEOF}.} \end{functions} Per scrivere un carattere si possono usare tre funzioni analoghe alle @@ -639,11 +639,11 @@ precedenti usate per leggere: \func{putc}, \func{fputc} e \funcdecl{int fputc(FILE *stream)} Scrive il carattere \param{c} su \param{stream}. È una sempre una funzione. - \funcdecl{int putchar(void)} è equivalente a \func{putc(stdin)}. + \funcdecl{int putchar(void)} Equivalente a \func{putc(stdin)}. -\item \noindent Le funzioni scrivono sempre un carattere alla volta, - il cui valore viene restituito in caso di successo; in caso di errore - o fine del file il valore di ritorno è \macro{EOF}. + \bodydesc{Le funzioni scrivono sempre un carattere alla volta, il cui + valore viene restituito in caso di successo; in caso di errore o + fine del file il valore di ritorno è \macro{EOF}.} \end{functions} Tutte queste funzioni scrivono sempre un byte alla volta, anche se @@ -666,13 +666,57 @@ loro prototipi sono: \funcdecl{int getw(FILE *stream)} Legge una parola da \param{stream}. \funcdecl{int putw(int w, FILE *stream)} Scrive la parola \param{w} su \param{stream}. - - Le funzioni restituiscono la parola \param{w}, o \macro{EOF} in caso - di errore o di fine del file. + + \bodydesc{Le funzioni restituiscono la parola \param{w}, o \macro{EOF} + in caso di errore o di fine del file.} \end{functions} -l'uso di queste funzioni è deprecato in favore dell'uso di \func{fread} -e \func{fwrite}, in quanto non è possibile distinguere il valore -1 da una -condizione di errore che restituisce \macro{EOF}. +\noindent l'uso di queste funzioni è deprecato in favore dell'uso di +\func{fread} e \func{fwrite}, in quanto non è possibile distinguere il +valore -1 da una condizione di errore che restituisce \macro{EOF}. + +Una degli usi più frequenti dell'input/output a caratteri è nei +programmi di \textit{parsing} in cui si analizza il testo; in questo +contesto diventa utile poter analizzare il carattere successivo da uno +stream senza estrarlo effettivamente (la tecnica è detta \textit{peeking + ahead}) in modo che il programma possa regolarsi sulla base avendo +dato una \textsl{sbirciatina} a quello che viene dopo. + +Nel nostro caso questo tipo di comportamento può essere realizzato prima +leggendo il carattere, e poi rimandandolo indietro, cosicché ridiventi +disponibile per una lettura successiva; la funzione che inverte la +lettura si chiama \func{ungetc} ed il suo prototipo è: +\begin{prototype}{stdio.h}{int ungetc(int c, FILE *stream)} + Rimanda indietro il carattere \param{c}, con un cast a \type{unsigned + char}, sullo stream \param{stream}. + + \bodydesc{La funzione ritorna \param{c} in caso di successo e + \macro{EOF} in caso di errore.} +\end{prototype} +benché lo standard ANSI C preveda che l'operazione possa essere ripetuta +per un numero arbitrario di caratteri, alle implementazioni è richiesto +di garantire solo un livello; questo è quello che fa la \acr{glibc}, che +richiede che avvenga un'altra operazione fra due \func{ungetc} +successive. + +Non è necessario che il carattere che si manda indietro sia l'ultimo che +si è letto, e non è necessario neanche avere letto nessun carattere +prima di usare \func{ungetc}, ma di norma la funzione è intesa per +essere usata per rimandare indietro l'ultimo carattere letto. + +Nel caso \param{c} sia un \macro{EOF} la funzione non fa nulla, e +restituisce sempre \macro{EOF}; così si può usare \func{ungetc} anche +con il risultato di una lettura alla fine del file. + +Se si è alla fine del file si può comunque rimandare indietro un +carattere, il flag di end-of-file verrà automaticamente cancellato +perché c'è un nuovo carattere disponibile che potrà essere riletto +successivamente. + +Infine si tenga presente che \func{ungetc} non altera il contenuto del +file, ma opera esclusivamente sul buffer interno. Se si esegue una +qualunque delle operazioni di riposizionamento (vedi +\secref{sec:file_fseek}) i caratteri rimandati indietro vengono +scartati. \subsection{Input/output di linea} @@ -680,10 +724,11 @@ condizione di errore che restituisce \macro{EOF}. La terza ed ultima modalità di input/output non formattato è quello di linea, in cui legge o scrive una riga alla volta; questa è una modalità -molto usata, ma che presenta le caratteristiche più controverse. +molto usata per l'I/O da terminale, ma che presenta le caratteristiche +più controverse. -Le funzioni per leggere una linea sono sostazialmente due, \func{gets} e -\func{fgets}, i rispettivi prototipi sono: +Le funzioni per leggere una linea sono sostanzialmente due, \func{gets} e +\func{fgets}, i cui rispettivi prototipi sono: \begin{functions} \headdecl{stdio.h} @@ -693,9 +738,9 @@ Le funzioni per leggere una linea sono sostazialmente due, \func{gets} e \funcdecl{char * fgets(char * string, int size, FILE *stream)} Scrive su \param{string} la linea letta da \param{stream} per un massimo di \param{size} byte. - - Le funzioni restituiscono della stringa letta o \macro{NULL} in caso - di errore. + + \bodydesc{Le funzioni restituiscono della stringa letta o \macro{NULL} + in caso di errore.} \end{functions} @@ -780,7 +825,7 @@ stream; se non si Gli stream possono essere usati in applicazioni multi-thread allo stesso modo in cui sono usati nelle applicazioni normali, ma si deve essere -consapovoli delle possibili complicazioni anche quando non si usano i +consapevoli delle possibili complicazioni anche quando non si usano i thread, dato che l'implementazione delle librerie è influenzata pesantemente dalle richieste necessarie per garantirne l'uso coi thread.