%% filestd.tex
%%
-%% Copyright (C) 2000-2002 Simone Piccardi. Permission is granted to
+%% Copyright (C) 2000-2003 Simone Piccardi. Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with the Invariant Sections being "Prefazione",
stream, come la posizione corrente, lo stato del buffer e degli indicatori di
stato e di fine del file.
-Per questo motivo gli utenti non devono mai utilizzare direttamente o
-allocare queste strutture, ma usare sempre puntatori del tipo \ctyp{FILE
- *} ottenuti dalla libreria stessa (tanto che in certi casi il termine
-di puntatore a file è diventato sinonimo di stream). Tutte le funzioni
-della libreria che operano sui file accettano come parametri solo
-variabili di questo tipo, che diventa accessibile includendo l'header
-file \file{stdio.h}.
-
+Per questo motivo gli utenti non devono mai utilizzare direttamente o allocare
+queste strutture (che sono dei \textsl{tipi opachi}\index{tipo!opaco}) ma
+usare sempre puntatori del tipo \ctyp{FILE *} ottenuti dalla libreria stessa
+(tanto che in certi casi il termine di puntatore a file è diventato sinonimo
+di stream). Tutte le funzioni della libreria che operano sui file accettano
+come parametri solo variabili di questo tipo, che diventa accessibile
+includendo l'header file \file{stdio.h}.
\subsection{Gli stream standard}
effettivamente tre variabili di tipo \ctyp{FILE *} che possono essere
usate come tutte le altre, ad esempio si può effettuare una redirezione
dell'output di un programma con il semplice codice:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
- fclose(stdout);
- stdout = fopen("standard-output-file", "w");
-\end{lstlisting}
+\includecodesnip{listati/redir_stdout.c}
ma in altri sistemi queste variabili possono essere definite da macro, e
se si hanno problemi di portabilità e si vuole essere sicuri, diventa
opportuno usare la funzione \func{freopen}.
riguarda l'aspetto della scrittura dei dati sul file.
I caratteri che vengono scritti su di uno stream normalmente vengono
-accumulati in un buffer e poi trasmessi in blocco\footnote{qiesta operazione
+accumulati in un buffer e poi trasmessi in blocco\footnote{questa operazione
viene usualmente chiamata \textsl{scaricamento} dei dati, dal termine
inglese \textit{flush}.} tutte le volte che il buffer viene riempito, in
maniera asincrona rispetto alla scrittura. Un comportamento analogo avviene
dell'input/output interattivo, bisognerà tenere presente le caratteristiche
delle operazioni di scaricamento dei dati, poiché non è detto che ad una
scrittura sullo stream corrisponda una immediata scrittura sul dispositivo (la
-cosa è particolaemente evidente quando con le operazioni di input/output su
+cosa è particolarmente evidente quando con le operazioni di input/output su
terminale).
Per rispondere ad esigenze diverse, lo standard definisce tre distinte
blocchi di dati binari in maniera compatta e veloce; un primo caso di uso
tipico è quello in cui si salva un vettore (o un certo numero dei suoi
elementi) con una chiamata del tipo:
-%\footnotesize
-\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}
-%\normalsize
+\includecodesnip{listati/WriteVect.c}
in questo caso devono essere specificate le dimensioni di ciascun
elemento ed il numero di quelli che si vogliono scrivere. Un secondo
caso è invece quello in cui si vuole trasferire su file una struttura;
si avrà allora una chiamata tipo:
-%\footnotesize
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
-struct histogram {
- int nbins;
- double max, min;
- double *bin;
-} histo;
-
-int WriteStruct(FILE *stream, struct histogram *histo)
-{
- if ( fwrite(vec, sizeof(*histo), 1, stream) !=1) {
- perror("Write error");
- }
- return nread;
-}
-\end{lstlisting}
-%\normalsize
+\includecodesnip{listati/WriteStruct.c}
in cui si specifica la dimensione dell'intera struttura ed un solo
elemento.
esattamente le stesse operazioni delle loro equivalenti, evitando però il lock
implicito dello stream (vedi \secref{sec:file_stream_thread}). Come per le
altre forma di I/O, dette funzioni hanno lo stesso nome della loro analoga
-normale, con l'aggiuta dell'estensione \code{\_unlocked}.
+normale, con l'aggiunta dell'estensione \code{\_unlocked}.
Come abbiamo visto, le funzioni di lettura per l'input/output di linea
previste dallo standard ANSI C presentano svariati inconvenienti. Benché
necessaria a contenere la linea. In tutti i casi si ottiene dalla funzione un
puntatore all'inizio del testo della linea letta. Un esempio di codice può
essere il seguente:
-\begin{lstlisting}[labelstep=0,frame=,indent=1cm]{}
- size_t n = 0;
- char *ptr = NULL;
- int nread;
- FILE * file;
- ...
- nread = getline(&ptr, &n, file);
-\end{lstlisting}
-e per evitare memory leak occorre ricordarsi di liberare \var{ptr} con
-una \func{free}.
+\includecodesnip{listati/getline.c}
+e per evitare memory leak\index{memory leak} occorre ricordarsi di liberare
+\var{ptr} con una \func{free}.
Il valore di ritorno della funzione indica il numero di caratteri letti
dallo stream (quindi compreso il newline, ma non lo zero di
\cmd{\%X} &\ctyp{unsigned int}& Stampano un intero in formato esadecimale,
rispettivamente con lettere minuscole e
maiuscole. \\
- \cmd{\%f} &\ctyp{unsigned int}& Stampa un numero in virgola mobile con la
+ \cmd{\%f} &\ctyp{double} & Stampa un numero in virgola mobile con la
notazione a virgola fissa \\
\cmd{\%e},
\cmd{\%E} &\ctyp{double} & Stampano un numero in virgola mobile con la
proposito dei \textit{value result argument}) l'indirizzo della stringa
allocata automaticamente dalle funzioni. Occorre inoltre ricordarsi di
invocare \func{free} per liberare detto puntatore quando la stringa non serve
-più, onde evitare memory leak.
+più, onde evitare memory leak\index{memory leak}.
Infine una ulteriore estensione GNU definisce le due funzioni \func{dprintf} e
\func{vdprintf}, che prendono un file descriptor al posto dello stream. Altre
In corrispondenza alla famiglia di funzioni \func{printf} che si usano per
l'output formattato, l'input formattato viene eseguito con le funzioni della
famiglia \func{scanf}; fra queste le tre più importanti sono \funcd{scanf},
-\funcd{fscanf} e \funcd{sscanf}, i cui proprotipi sono:
+\funcd{fscanf} e \funcd{sscanf}, i cui prototipi sono:
\begin{functions}
\headdecl{stdio.h} \funcdecl{int scanf(const char *format, ...)} Esegue una
scansione di \file{stdin} cercando una corrispondenza di quanto letto con il
conversione delle stringhe; se invece il formato è più complesso diventa più
facile utilizzare uno strumento come \cmd{flex}\footnote{il programma
\cmd{flex}, è una implementazione libera di \cmd{lex} un generatore di
- analizzatori lessicali, per i dettagli si può fare riferimento al manuale
+ analizzatori lessicali. Per i dettagli si può fare riferimento al manuale
\cite{flex}.} per generare un analizzatore lessicale o il
\cmd{bison}\footnote{il programma \cmd{bison} è un clone del generatore di
parser \cmd{yacc}, maggiori dettagli possono essere trovati nel relativo
La sostituzione di tutte le funzioni di I/O con le relative versioni
\code{\_unlocked} in un programma che non usa i thread è però un lavoro
-abbastanza noioso; per questo motivo le \acr{glibc} provvedono al
+abbastanza noioso; per questo motivo le \acr{glibc} forniscono al
programmatore pigro un'altra via\footnote{anche questa mutuata da estensioni
introdotte in Solaris.} da poter utilizzare per disabilitare in blocco il
locking degli stream: l'uso della funzione \funcd{\_\_fsetlocking}, il cui