\subsection{I \textit{file stream}}
\label{sec:file_stream}
-Come più volte ribadito l'interfaccia dei file descriptor è un'interfaccia di
+Come più volte ribadito, l'interfaccia dei file descriptor è un'interfaccia di
basso livello, che non provvede nessuna forma di formattazione dei dati e
nessuna forma di bufferizzazione per ottimizzare le operazioni di I/O.
\subsection{Le modalità di bufferizzazione}
\label{sec:file_buffering}
-La bufferizzazione è una delle caratteristiche principali della
-interfaccia degli stream; lo scopo è quello di ridurre al minimo il
-numero di system call (\func{read} o \func{write}) eseguite nelle
-operazioni di input/output. Questa funzionalità è assicurata
-automaticamente dalla libreria, ma costituisce anche uno degli aspetti
-più comunemente fraintesi, in particolare per quello che riguarda
-l'aspetto della scrittura dei dati sul file.
-
-I caratteri che vengono scritti su uno stream normalmente vengono
-accumulati in un buffer e poi trasmessi in blocco in maniera asincrona
-rispetto alla scrittura (quello che viene chiamato lo \textsl{scarico}
-dei dati, dall'inglese \textit{flush}) tutte le volte che il buffer
-viene riempito. Un comportamento analogo avviene anche in lettura (cioè
-dal file viene letto un blocco di dati, anche se se ne sono richiesti
-una quantità inferiore), ma la cosa ovviamente ha rilevanza inferiore,
-dato che i dati letti sono sempre gli stessi; in caso di scrittura
-invece, quando si ha un accesso contemporaneo allo stesso file (ad
-esempio da parte di un altro processo) si potranno vedere solo le parti
-effettivamente scritte, e non quelle ancora presenti nel buffer.
+La bufferizzazione è una delle caratteristiche principali dell'interfaccia
+degli stream; lo scopo è quello di ridurre al minimo il numero di system call
+(\func{read} o \func{write}) eseguite nelle operazioni di input/output. Questa
+funzionalità è assicurata automaticamente dalla libreria, ma costituisce anche
+uno degli aspetti più comunemente fraintesi, in particolare per quello che
+riguarda l'aspetto della scrittura dei dati sul file.
+
+I caratteri che vengono scritti su uno stream normalmente vengono accumulati
+in un buffer e poi trasmessi in blocco in maniera asincrona rispetto alla
+scrittura (quello che viene chiamato lo \textsl{scarico} dei dati,
+dall'inglese \textit{flush}) tutte le volte che il buffer viene riempito. Un
+comportamento analogo avviene anche in lettura (cioè dal file viene letto un
+blocco di dati, anche se ne sono richiesti una quantità inferiore), ma la cosa
+ovviamente ha rilevanza inferiore, dato che i dati letti sono sempre gli
+stessi; in caso di scrittura invece, quando si ha un accesso contemporaneo
+allo stesso file (ad esempio da parte di un altro processo) si potranno vedere
+solo le parti effettivamente scritte, e non quelle ancora presenti nel buffer.
Allo stesso modo, se si sta facendo dell'input/output interattivo
bisognerà tenere presente le caratteristiche delle operazioni di scarico
La modalità \textit{line buffered} è quella che necessita di maggiori
chiarimenti e attenzioni per quel che concerne il suo funzionamento. Come già
accennato nella descrizione, \emph{di norma} i dati vengono inviati al kernel
-alla ricezione di un carattere di a capo; questo non è vero in tutti i casi,
-infatti, dato che le dimensioni del buffer usato dalle librerie sono fisse, se
-le si eccedono si può avere uno scarico dei dati anche prima che sia stato
-inviato un carattere di \textit{newline}.
+alla ricezione di un carattere di \textsl{a capo} (\textit{newline}); questo
+non è vero in tutti i casi, infatti, dato che le dimensioni del buffer usato
+dalle librerie sono fisse, se le si eccedono si può avere uno scarico dei dati
+anche prima che sia stato inviato un carattere di \textit{newline}.
Un secondo punto da tenere presente, particolarmente quando si ha a che fare
-con I/O interattivo, è che quando si effettua una lettura su uno stream che
-comporta l'accesso al kernel\footnote{questo vuol dire sempre se lo stream da
- cui si legge è in modalità \textit{unbuffered}.} viene anche eseguito lo
-scarico di tutti i buffer degli stream in scrittura.
+con I/O interattivo, è che quando si effettua una lettura da uno stream che
+comporta l'accesso al kernel\footnote{questo vuol dire che lo stream da cui si
+ legge è in modalità \textit{unbuffered}.} viene anche eseguito lo scarico di
+tutti i buffer degli stream in scrittura.
In \secref{sec:file_buffering_ctrl} vedremo come la libreria definisca delle
opportune funzioni per controllare le modalità di bufferizzazione e lo scarico
Apre il file specificato da \param{path} associandolo allo stream
specificato da \param{stream}, se questo è già aperto prima lo chiude.
- \bodydesc{Le funzioni ritornano un puntatore valido in caso di
- successo e \macro{NULL} in caso di errore, in tal caso \var{errno}
- viene impostata al valore ricevuto dalla funzione sottostante di cui è
- fallita l'esecuzione.
+ \bodydesc{Le funzioni ritornano un puntatore valido in caso di successo e
+ \macro{NULL} in caso di errore, in tal caso \var{errno} assumerà il valore
+ ricevuto dalla funzione sottostante di cui è fallita l'esecuzione.
Gli errori pertanto possono essere quelli di \code{malloc} per tutte
e tre le funzioni, quelli \func{open} per \func{fopen}, quelli di
\textit{append mode}, l'accesso viene posto in lettura e scrittura. \\
\hline
\texttt{b} & specifica che il file è binario, non ha alcun effetto. \\
- \texttt{x} & la apertura fallisce se il file esiste già. \\
+ \texttt{x} & l'apertura fallisce se il file esiste già. \\
\hline
\end{tabular}
\caption{Modalità di apertura di uno stream dello standard ANSI C che
\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}.
+\item\textsl{di linea} in cui si legge/scrive una linea alla volta (terminata
+ dal carattere di newline \verb|'\n'|), vedi \secref{sec:file_line_io}.
\end{enumerate*}
ed inoltre la modalità di input/output formattato.
Dato che le funzioni dell'interfaccia degli stream sono funzioni di libreria
che si appoggiano a delle system call, esse non impostano direttamente la
-variabile \var{errno}, che mantiene il valore impostato dalla system call che ha
-riportato l'errore.
+variabile \var{errno}, che mantiene il valore impostato 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 impostato in una
-altra occasione, (si veda \secref{sec:sys_errno} per i dettagli del
+infatti non basta, dato che quest'ultimo potrebbe essere stato impostato 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
\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
+\noindent in genere si usa questa funzione una volta che si sia identificata e
corretta la causa di un errore per evitare di mantenere i flag attivi, così da
poter rilevare una successiva ulteriore condizione di errore. Di questa
funzione esiste una analoga \func{clearerr\_unlocked} che non esegue il blocco
double *bin;
} histo;
-int WriteStruct(FILE *stream, struct histogram *histo, size_t nelem)
+int WriteStruct(FILE *stream, struct histogram *histo)
{
if ( fwrite(vec, sizeof(*histo), 1, stream) !=1) {
perror("Write error");
\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.
+ restituisce come intero. È sempre una funzione.
\funcdecl{int getchar(void)} Equivalente a \code{getc(stdin)}.
\end{itemize*}
-Dettagli ulteriori sulle varie opzioni possono essere trovati nella man page
-di \func{printf} e nella documentazione delle \acr{glibc}.
+Dettagli ulteriori sulle varie opzioni possono essere trovati nella pagina di
+manuale di \func{printf} e nella documentazione delle \acr{glibc}.
\begin{table}[htb]
\centering
separazione (che possono essere spazi, tabulatori, virgole etc.), mentre
caratteri diversi richiedono una corrispondenza esatta. Le direttive di
conversione sono analoghe a quelle di \func{printf} e si trovano descritte in
-dettaglio nelle man page e nel manuale delle \acr{glibc}.
+dettaglio nelle pagine di manuale e nel manuale delle \acr{glibc}.
Le funzioni eseguono la lettura dall'input, scartano i separatori (e gli
eventuali caratteri diversi indicati dalla stringa di formato) effettuando le
Legge il file descriptor sottostante lo stream \param{stream}.
\bodydesc{Restituisce il numero del file descriptor in caso di successo, e
- -1 qualora \param{stream} non sia valido, nel qual caso imposta \var{errno}
- a \macro{EBADF}.}
+ -1 qualora \param{stream} non sia valido, nel qual caso imposta
+ \var{errno} a \macro{EBADF}.}
\end{prototype}
\noindent ed in questo modo diventa possibile usare direttamente \func{fcntl}.