Completato I/O a caratteri, iniziato I/O di linea
authorSimone Piccardi <piccardi@gnulinux.it>
Tue, 11 Dec 2001 22:55:44 +0000 (22:55 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Tue, 11 Dec 2001 22:55:44 +0000 (22:55 +0000)
filestd.tex

index c8936db9b51950b41b290fd982215f245d171725..dcbb3381f146bb7cd6d0141571274232de019601 100644 (file)
@@ -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}