X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=blobdiff_plain;f=filestd.tex;h=dcbb3381f146bb7cd6d0141571274232de019601;hp=c8936db9b51950b41b290fd982215f245d171725;hb=a76ef671288ddb656f3a4aa599cfda5e05491c39;hpb=5283816ce55d9625355104e745a1964287605e1f diff --git a/filestd.tex b/filestd.tex index c8936db..dcbb338 100644 --- a/filestd.tex +++ b/filestd.tex @@ -11,7 +11,7 @@ dell'interfaccia nell'ultima sezione. \section{Introduzione} \label{sec:file_stream_intro} -Come visto in \capref{cap:file_unix_interface} le operazioni di I/O sui file +Come visto in \capref{cha:file_unix_interface} le operazioni di I/O sui file sono gestibili a basso livello con l'interfaccia standard unix, che ricorre direttamente alle system call messe a disposizione dal kernel. @@ -209,9 +209,10 @@ corrente in uno stream. \subsection{Apertura e chiusura di uno stream} \label{sec:file_fopen} -Le funzioni che permettono di aprire uno stream sono tre\footnote{\func{fopen} - e \func{freopen} fanno parte dello standard ANSI C, \func{fdopen} è parte -dello standard POSIX.1.}, i loro prototipi sono: +Le funzioni che si possono usare per aprire uno stream sono solo +tre\footnote{\func{fopen} e \func{freopen} fanno parte dello standard + ANSI C, \func{fdopen} è parte dello standard POSIX.1.}, i loro +prototipi sono: \begin{functions} \headdecl{stdio.h} \funcdecl{FILE * fopen(const char * path, const char *mode)} @@ -379,12 +380,12 @@ modalit \begin{enumerate*} \item\textsl{binario} in cui legge/scrive un blocco di dati alla volta, vedi \secref{sec:file_binary_io}. -\item\textsl{di linea} in cui si legge/scrive una linea (terminata dal - carattere di newline \verb|\n|) alla volta, vedi - \secref{sec:file_line_io}. \item\textsl{a caratteri} in cui si legge/scrive un carattere alla volta (con la bufferizzazione gestita automaticamente dalla libreria), vedi \secref{sec:file_char_io}. +\item\textsl{di linea} in cui si legge/scrive una linea (terminata dal + carattere di newline \verb|\n|) alla volta, vedi + \secref{sec:file_line_io}. \end{enumerate*} ed inoltre la modalità di input/output formattato. @@ -449,13 +450,16 @@ questa formattati. Le due funzioni che si usano per l'I/O binario sono: \begin{functions} \headdecl{stdio.h} - \funcdecl{size\_t fread(void * ptr, size\_t size, - size\_t nmemb, FILE * stream)} - \funcdecl{size\_t fwrite(const void * - ptr, size\_t size, size\_t nmemb, FILE * stream)} + + \funcdecl{size\_t fread(void * ptr, size\_t size, size\_t nmemb, FILE + * stream)} + + \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}. + 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 @@ -557,18 +561,144 @@ gestione delle applicazioni multi-thread (si veda ma non acquisiscono il lock implicito sullo stream. \end{functions} \noindent entrambe le funzioni sono estensioni GNU previste solo dalle - \acr{glibc}. +\acr{glibc}. -\subsection{Input/output a caratteri singoli} +\subsection{Input/output a caratteri} \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: +\begin{functions} + \headdecl{stdio.h} + + \funcdecl{int getc(FILE *stream)} Legge un byte da \param{stream} e lo + restituisce come intero. In genere è implementata come una macro. + + \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)}. + + 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 +tastiera, le altre due funzioni sono sostanzialmente equivalenti. La +differenza è che \func{gets} è ottimizzata al massimo e normalmente +viene implementata con una macro, per cui occorre stare attenti a cosa +le si passa come argomento, infatti \param{stream} può essere valutato +più volte nell'esecuzione, e non viene passato in copia con il +meccanismo visto in \secref{sec:proc_var_passing}; per questo motivo se +si passa una espressione si possono avere effetti indesiderati. + +Invece \func{fgets} è assicurata essere sempre una funzione, per questo +motivo la sua esecuzione normalmente è più lenta per via dell'overhead +della chiamata, ma è altresì possibile ricavarne l'indirizzo, che può +essere passato come parametro ad un altra funzione (e non si hanno i +problemi accennati in precedenza con \param{stream}). + +Le tre funzioni restituiscono tutte un \type{unsigned char} convertito +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 +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 è: +\begin{functions} + \headdecl{stdio.h} + + \funcdecl{wint\_t getwc(FILE *stream)} Legge un carattere esteso da + \param{stream}. In genere è implementata come una macro. + + \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)}. + + 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 +precedenti usate per leggere: \func{putc}, \func{fputc} e +\func{putchar}; i loro prototipi sono: +\begin{functions} + \headdecl{stdio.h} + + \funcdecl{int putc(int c, FILE *stream)} Scrive il carattere \param{c} + su \param{stream}. In genere è implementata come una macro. + + \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)}. + +\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}. +\end{functions} + +Tutte queste funzioni scrivono sempre un byte alla volta, anche se +prendono come parametro un \type{int} (che pertanto deve essere ottenuto +con un cast da un \type{unsigned char}). Anche il valore di ritorno è +sempre un intero; in caso di errore o fine del file il valore di ritorno +è \macro{EOF}. + +Come nel caso dell'I/O binario le \acr{glibc} provvedono per ciascuna +delle funzioni precedenti una seconda funzione, il cui nome è ottenuto +aggiungendo un \func{\_unlocked}, che esegue esattamente le stesse +operazioni evitando però il lock implicito dello stream. + +Per compatibilità con SVID sono provviste anche due funzioni per leggere +e scrivere una \textit{word} (che è sempre definita come \type{int}); i +loro prototipi sono: +\begin{functions} + \headdecl{stdio.h} + + \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. +\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}. \subsection{Input/output di linea} \label{sec:file_line_io} +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. + +Le funzioni per leggere una linea sono sostazialmente due, \func{gets} e +\func{fgets}, i rispettivi prototipi sono: +\begin{functions} + \headdecl{stdio.h} + + \funcdecl{char * gets(char * string)} Scrive su \param{string} una + linea letta da \var{stdin}. + + \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. +\end{functions} + + \subsection{Input/output formattato} \label{sec:file_formatted_io}