I/O binario continua
[gapil.git] / filestd.tex
index 6730757a57cdb01d0fbea3d4153e3cf06cefaa89..2a22545a15e690ba79c4eeeefedda7601eb4c78e 100644 (file)
@@ -353,8 +353,8 @@ ricchezza delle funzioni disponibili per le operazioni di lettura e
 scrittura sui file. Sono infatti previste ben tre diverse modalità
 modalità di input/output non formattato:
 \begin{enumerate}
 scrittura sui file. Sono infatti previste ben tre diverse modalità
 modalità di input/output non formattato:
 \begin{enumerate}
-\item\textsl{a blocchi} in cui legge/scrive un blocco di dati alla
-  volta, vedi \secref{sec:file_block_io}.
+\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{di linea} in cui si legge/scrive una linea (terminata dal
   carattere di newline \verb|\n|) alla volta, vedi
   \secref{sec:file_line_io}.
@@ -362,23 +362,27 @@ modalit
   volta (con la bufferizzazione gestita automaticamente dalla libreria),
   vedi \secref{sec:file_char_io}.
 \end{enumerate}
   volta (con la bufferizzazione gestita automaticamente dalla libreria),
   vedi \secref{sec:file_char_io}.
 \end{enumerate}
-e una modalità di input/output formattato.
-
-A differenza dell'interfaccia dei file descriptor il raggiungimento
-della fine del file è considerato un errore, e viene notificato come
-tale dai valori di uscita delle varie funzioni; nella maggior parte dei
-casi questo avviene con la restituzione del valore intero (di tipo
-\type{int}) \macro{EOF}\footnote{la costante deve essere negativa, le
-  \acr{glibc} usano -1, altre implementazioni possono avere valori
-  diversi.}  definito anch'esso nell'header \func{stdlib.h}.
-
-Dato che le funzioni dell'interfaccia degli stream sono funzioni di
-libreria, esse non settano la variabile \var{errno}, che mantiene il
-valore settato dalla system call che ha riportato l'errore, ma siccome
-la condizione di end-of-file è anch'essa segnalata come errore, non
-esisterebbe alcuna possibilità di distinguerla da un errore (\var{errno}
-potrebbe essere stata settata in una altra occasione, vedi
-\secref{sec:sys_errno}). 
+ed inoltre la modalità di input/output formattato.
+
+A differenza dell'interfaccia dei file descriptor il raggiungimento della fine
+del file è considerato un errore, e viene notificato come tale dai valori di
+uscita delle varie funzioni; nella maggior parte dei casi questo avviene con
+la restituzione del valore intero (di tipo \type{int}) \macro{EOF}\footnote{la
+  costante deve essere negativa, le \acr{glibc} usano -1, altre
+  implementazioni possono avere valori diversi.}  definito anch'esso
+nell'header \func{stdlib.h}.
+
+Dato che le funzioni dell'interfaccia degli stream sono funzioni di libreria
+che si appoggiano a delle system call, esse non settano direttamente la
+variabile \var{errno}, che mantiene il valore settato dalla system call che ha
+riportato l'errore. 
+
+Siccome la condizione di end-of-file è anch'essa segnalata come errore, nasce
+il problema di come distinguerla da un errore effettivo; basarsi solo sul
+valore di ritorno della funzione e controllare il valore di \var{errno}
+infatti non basta, dato che quest'ultimo potrebbe essere stato settato in una
+altra occasione, (si veda \secref{sec:sys_errno} per i dettagli del
+funzionamento di \var{errno}).
 
 Per questo motivo tutte le implementazioni delle librerie standard
 mantengono per ogni stream almeno due flag all'interno dell'oggetto
 
 Per questo motivo tutte le implementazioni delle librerie standard
 mantengono per ogni stream almeno due flag all'interno dell'oggetto
@@ -397,11 +401,12 @@ questi flag possono essere riletti dalle funzioni:
   flag sono settati. 
 \end{functions}
 \noindent si tenga presente comunque che la lettura di questi flag segnala
   flag sono settati. 
 \end{functions}
 \noindent si tenga presente comunque che la lettura di questi flag segnala
-soltanto che si è avuto un errore, o si è raggiunta la fine del file, in
-una precedente operazione sullo stream.
+soltanto che c'è stato un errore, o che si è raggiunta la fine del file in una
+qualunque operazione sullo stream, il controllo quindi deve essere effettuato
+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 è:
+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)}
   Cancella i flag di errore ed end-of-file di \param{stream}. 
 \end{prototype}
 \begin{prototype}{stdio.h}{void clearerr( FILE *stream)}
   Cancella i flag di errore ed end-of-file di \param{stream}. 
 \end{prototype}
@@ -410,14 +415,70 @@ corretta la causa di un errore per evitare di mantenere i flag attivi,
 così da poter rilevare una successiva ulteriore condizione di errore.
 
 
 così da poter rilevare una successiva ulteriore condizione di errore.
 
 
-\subsection{Input/output a blocchi}
-\label{sec:file_block_io}
+\subsection{Input/output binario}
+\label{sec:file_binary_io}
+
+La prima modalità di input/output non formattato ricalca quella della
+intefaccia dei file descriptor, e provvede semplicemente la scrittura e
+la lettura dei dati da un buffer verso un file e vicecersa. In generale
+questa è la modalità che si usa quando si ha a che fare con dati non
+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)}
+  
+  Le funzioni 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.
+\end{functions}
+
+In genere si usano queste funzioni quando si devono leggere o scrivere
+un array o una struttura; un tipico esempio è quello in cui si salva una
+parte di un vettore con una chiamata del tipo:
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+int WriteVect(FILE * stream, double * vec, size_t nelem) 
+{
+    int size, nread;
+    size = sizeof(*vec);
+    if ( (nread = fwrite(vec, size, nelem, stream)) != nelem) {
+        perror("Write error");
+    }
+    return nread;
+}
+\end{lstlisting}
+nel qual caso devono essere specificate dimensione e numero degli
+elementi del vettore; nel caso di una struttura invece si avrà un
+qualcosa tipo:
+\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
+struct histogram {
+    int nbins; 
+    double max, min;
+    double * bin;
+} histo; 
+int WriteStruct(FILE * stream, struct histogram * histo, size_t nelem) 
+{
+    if ( fwrite(vec, sizeof(*histo), 1, stream) !=1) {
+        perror("Write error");
+    }
+    return nread;
+}
+\end{lstlisting}
+
+
 
 
 \subsection{Input/output a caratteri singoli}
 \label{sec:file_char_io}
 
 
 
 
 \subsection{Input/output a caratteri singoli}
 \label{sec:file_char_io}
 
 
+
+
 \subsection{Input/output di linea}
 \label{sec:file_line_io}
 
 \subsection{Input/output di linea}
 \label{sec:file_line_io}
 
@@ -464,7 +525,30 @@ stream; questo pu
   scrittura.
 \end{functions}
 
   scrittura.
 \end{functions}
 
-Altre due funzioni, \func{\_\_freading} e \func{\_\_fwriting} servono 
+Altre due funzioni, \func{\_\_freading} e \func{\_\_fwriting} servono ad un
+uso ancora più specialistico, il loro prototipo è: 
+\begin{functions}
+  \headdecl{stdio\_ext.h}
+  \funcdecl{int \_\_freading (FILE * stream)}
+  Restituisce un valore diverso da zero se \param{stream} è aperto in sola
+  lettura o se l'ultima operazione è stata di lettura.
+
+  \funcdecl{int \_\_fwriting(FILE * stream)}  
+  Restituisce un valore diverso da zero se \param{stream} è aperto in sola
+  scrittura o se l'ultima operazione è stata di scrittura.
+\end{functions}
+
+Le due funzioni hanno lo scopo di determinare di che tipo è stata l'ultima
+operazione eseguita su uno stream aperto in lettura/scrittura; ovviamente se
+uno stream è aperto in sola lettura (o sola scrittura) la modalità dell'ultima
+operazione è sempre determinata; l'unica ambiguità è quando non sono state
+ancora eseguite operazioni, in questo caso le funzioni rispondono come se
+una operazione ci fosse comunque stata.
+
+La conoscenza dell'ultima operazione effettuata su uno stream aperto in
+lettura/scrittura è utile in quanto permette di trarre conclusioni sullo stato
+del buffer e del suo contenuto.
+
 
 \subsection{Il controllo della bufferizzazione}
 \label{sec:file_buffering_ctrl}
 
 \subsection{Il controllo della bufferizzazione}
 \label{sec:file_buffering_ctrl}