I FILES IN TURBO PASCAL

 

 

Occorre definire:

 

1)    Struttura di tipo [Record].

2)    Variabile di tipo [File di Record]  (caratterizza  il nome logico del file).

3)    Variabile di tipo [String] (caratterizzante il nome fisico del file).

4)    Variabile di tipo [Record]  (caratterizza la variabile “buffer” attraverso la quale e’ possibile scambiare le informazioni tra la memoria ed il file di record.  La struttura record di tale variabile deve essere identica alla struttura record del file).

 

Esempio di definizione delle strutture e delle variabili:

 

 

type

        scheda = record

        cognome: string [30]

                nome: string [30]

                indirizzo: string [30]

                end;

Var

FILELOG = file of scheda;          (*nome logico del file*)

        FILEFIS: string [12];                    (*nome fisico del file*)

        RECSCHEDA:  scheda;        (*buffer per lo scambio del record tra RAM e file*)

 

Operazioni sui files:

 

ASSIGN ( FILELOG, FILEFIS);

REWRITE ( FILELOG);

RESET ( FILELOG );

READ ( FILELOG, RECSCHEDA );

WRITE ( FILELOG, RECSCHEDA );

SEAK ( FILELOG, NREC );

CLOSE ( FILELOG );

ERASE ( FILELOG );

EOF ( FILELOG );

FILEPOS ( FILELOG );

FILESIZE ( FILELOG );

SEEK ( FILELOG, FILESIZE (FILELOG));

 

 

ASSING ( FILELOG, FILEFIS);

Associa a FILEFIS caratterizzante il nome fisico del file il nome logico FILELOG.

 

REWRITE ( FILELOG);

CREA fisicamente un nuovo file e sposta i puntatori EOF e Puntatore corrente in testa al file.

          Se il file non esiste [ viene creato il file] vuoto.

          Se il file già esiste [ viene cancellato il file esistente e ricreato vuoto.

 

 

RESET ( FILELOG);

APRE il file se già esistente e porta il puntatore corrente all’inizio del file mente l’EOF viene posizionato alla fine del file ovvero dopo tutti i record in esso contenuti.

Se il file non esiste non viene creato alcun file ed il T.P.  ritorna con una segnalazione di ERRORE.

 

 

READ (FILELOG, RECSCHEDA );

Viene letto il file di record FILELOG ed in particolare il record puntato dal puntatore corrente. Il contenuto di tale record viene trasferito nel record di appoggio RECSCHEDA. Quindi viene spostato il puntatore corrente sul record successivo del  file. Se il record teste’ letto e’ l’ultimo del file lo spostamento del puntatore corrente in avanti provoca il settaggio della variabile di ambiente EOF a true in modo che il programmatore testando opportunamente tale variabile possa sapere di essere arrivato alla fine del file.

 

 

WRITE (FILELOG, RECSCHEDA);

Il contenuto del record RECSCHEDA viene trasferito nel file di record FILELOG sul record puntato dal puntatore corrente.  Quindi viene spostato il puntatore corrente sul record successivo del  file. Se il record teste’ scritto e’ l’ultimo del file viene spostato in avanti anche il puntatore EOF.

 

 

SEEK (FILELOG, NREC);

Il puntatore corrente viene spostato all’inizio del record individuato da NREC  (NREC e’ una variabile di tipo INTEGER).  N.B. Il record 0 è il 1°record del file.

 

 

CLOSE ( FILELOG );

 Si effettua la chiusura del file ovvero viene scaricato il buffer di I/O anche se questi non e’ pieno. Viene quindi aggiornata la FAT.

 

 

ERASE (FILELOG);

Viene cancellato fisicamente il file individuato da FILELOG.

 

 

EOF (FILELOG);

TRATTASI di una FUNZIONE BOOLEANA.  Restituisce  lo status del puntatore corrente. Viene settata automaticamente dal sistema dopo una operazione di READ   e/o WRITE.

        EOF vale: TRUE  se dopo l’operazione di I/O si è raggiunto l’ EOF

        EOF vale: False se dopo l’operazione  di I/O non si è raggiunto l’EOF      

 

 

FILEPOS (FILELOG);

TRATTASI di una FUNZIONE INTERA. Restituisce il numero del record su cui è posizionato il puntatore corrente.

 

 

 

 

FILESIZE (FILELOG);

TRATTASI di una FUNZIONE INTERA.  Restituisce il numero dei record che compongono il file.

 

 

SEEK ( FILELOG, FILESIZE (FILELOG));

Trattati di un utilizzo avanzato della istruzione SEEK. In particolare viene spostato il puntatore corrente sul file di Record FILELOG in posizione FILESIZE (FILELOG) dove FILESIZE (FILELOG)  identifica l’ultimo record del file. In altre parole viene spostato il puntatore corrente sull’ultimo record del file di record FILELOG. Questa istruzione deve essere utilizzata quando si vogliono accodare record ad un file di record gia’ esistente e quindi aperto con la RESET.

 

 

ALTRI TIPI DI FILES.

Oltre ai files di record possono esistere files di tipo:  char, boolean, integer, real, text.

 

 

FILES di TIPO char

Il file e’ costituito da una successione di char. Viene scritto e letto sul file un char alla volta.

 

 

FILES di TIPO integer.

Il file e’ costituito da una successione di interi. Viene scritto e letto sul file un integer alla volta.

 

 

FILES di TIPO real.

Il file e’ costituito da una successione di real. Viene scritto e letto sul file un real alla volta

 

 

FILES di TIPO TEXT.

Il file e’ costituito da una successione di sequenze di caratteri editabili.   La separazione tra una sequenze e l’altra è data da CR+LF. La fine del file è identificata da CR+LF+EOF

 

          CR    ------   ^ M   -------         ASCII (13)

          LF    -------    ^ L   -------        ASCII(10)

          EOF  ------    ^ Z    -------       ASCII(26)

 

Il carattere di controllo ^Z può essere inserito via software o meno in quanto il TP alla chiusura del file provvede   automaticamente ad inserirlo.

 

 

 

DIFFERENZA TRA WRITE e WRITELN NELLA SCRITTURA DI FILES DI RECORD.

I caratteri di controllo CR+LF vengono inseriti automaticamente dal TP dopo ogni WRITELN.  Se si utilizza la WRITE per scrivere record sul file i caratteri di controllo CR+LF non vengono inseriti

 

 

 

 

 

DIFFERENZA TRA READ e READLN  NELLA LETTURA DI FILES DI RECORD.

 

READ                                   Legge l’oggetto definito nella variabile del file a partire dalla posizione       del puntatore  corrente senza che  questi passi alla sequenza successiva.

 

READLN                            Legge l’oggetto definito nella variabile del file e fa avanzare il puntatore all’oggetto successivo ignorando tutte le altre informazioni presenti nella linea stessa.

 

EOF(nomefilelogico)           Trattasi di una funzione.  EOF ritorna torna .T. se il puntatore è alla fine del file.

 

EOLN(nomefilelogico)        Trattasi di una funzione.  EOLN ritorna  .T. se il puntatore è alla fine della linea. N.B. se EOF=.T. anche EOLN=.T.

 

SEEKEOF(nomefilelogico)   Si saltano gli spazi e/o le tabulazioni prima di controllare la fine       del file. Trattasi di una funzione.  SEEKEOF ritorna torna .T. se il puntatore è alla fine del file.

 

 

SEEKEOLN(nomefilelogico)  Si saltano gli spazi e/o le tabulazioni prima di controllare la fine       della linea. Trattasi di una funzione.  SEEKEOLN ritorna torna .T. se il puntatore è alla fine del file.

 


 

ESEMPIO I

Scrivere (n) righe su un file di testo dopo averlo creato nuovo. Completato il caricamento rileggere tutto il file e stampare tutte le righe lette.

 

Program f1

Var

        Nomeflog: file of text;

        Linea: string [ 255 ];

        I: Integer;

Begin

        Assign (nomeflog, “ARCHIV.DAT”);

 

/* genero il file nuovo  */

Rewrite (nomeflog);

 

/*  scrivo n righe di testo sul file  */

        Writeln (nomeflog, “IERI ERA UNA BELLA GIORNATA”);

        Writeln (nomeflog, “OGGI E’ UNA BELLA GIORNATA”);

        ......................................................

        Writeln (nomeflog, “DOMANI SARA’ UNA BELLA GIORNATA”);

        Close (nomeflog);

 

/*  apro il file posizionando il puntatore di lettura in testa al file  */

        Reset(nomeflog);

 

/*  leggo e stampo in sequenza tutte le righe del file  */

        While not eof (nomeflog);

        Begin

                Readln(nomeflog,linea);

                Writeln(linea);

        End;

       

Close (nomeflog);

End.


 

Esempio II

Definire un file di record avente come struttura record i seguenti campi  “cod_rec” e “descrizione_record”. Creare il file nuovo e scriverci (n) record.  Effettuare quindi da tastiera l’imput di un valore ed assegnarlo alla variabile “codice”. Ricercare quindi sul file di record l’eventuale presenza di un record avente il valore contenuto in “codice” = al valore contenuto in “cod_rec”. Visualizzare come risultato della ricerca la dicitura “Non Trovato” se non si riesce a trovare il record desiderato sul file, visualizzare nel caso di record trovato il corrispondente valore contenuto in “descrizione_record”. LEGGERE IL FILE SEQUENZIALMENTE AVENDO CURA DI ARRESTARE LA RICERCA SEQUENZIALE NON APPENA IL RECORD VIENE TROVATO. Utilizzare la tecnica della programmazione strutturata.

 

Program f2

 

Type  scheda = record

        Cod_rec : string[10];

        Descrizione_record : string [ 100 ];

        end;

Var

        nomeflog : file of scheda;

        Buffer : scheda;

        flag: Boolean;

        codice : string[10];

Descrizione : string [ 100 ];

 

Procedure Genera_file;

Begin

/* genero il file nuovo  */

Rewrite (nomeflog);

 

/*  scrivo (99) record sul file di record  */

for  I = 1 to 99

begin

buffer.cod_rec :=  ord(i):

while len (buffer.cod_rec) < 10 then

        buffer.cor_rec := “0” + buffer.cod_rec:

buffer.descrizione_rec:= “record numero” + “  “ +  buffer.cod_rec;

                Writeln (nomeflog, buffer);

        end; 

Close (nomeflog);

End;

 

Procedure ricerca_record;

Begin

/*  apro il file posizionando il puntatore di lettura in testa al file  */

        Reset(nomeflog);

 

        flag := false;

        While not eof (nomeflog) and flag = false;

        Begin

                Readln (nomeflog,  buffer);

If codice = buffer.cod_rec then

Begin

        Flag = True;

        Descrizione := descrizione.rec”

End;

       

Close (nomeflog);

End;

       

/* main program  */

       

Begin

/* assegno il nome fisico del file al nome logico  */

        Assign (nomeflog, “ARCHIV.DAT”);

       

/* chiamo la procedura per generare il file  */

Genera_file;

 

/*  accetto il valore da ricercare nel file  */

Readln (codice);

 

/* chiamo la procedura per ricercare sul file  */

Ricerca_record;

 

        If flag = “true” then

                Writeln (descrizione)

Else

Writeln(“record non trovato”;

 

End.

 

 


 

Esempio III

Definire un file di record avente come struttura record i seguenti campi  “cod_rec” e “descrizione_record”. Creare il file nuovo e scriverci (n) record.  Effettuare quindi da tastiera l’imput di un valore ed assegnarlo alla variabile “codice”. Ricercare quindi sul file di record l’eventuale presenza di un record avente il valore contenuto in “codice” = al valore contenuto in “cod_rec”. Visualizzare come risultato della ricerca la dicitura “Non Trovato” se non si riesce a trovare il record desiderato sul file, visualizzare nel caso di record trovato il corrispondente valore contenuto in “descrizione_record”. EFFETTUARE UNA RICERCA SUL FILE IN MODO DICOTOMICO SECONDO IL CAMPO COD_REC. Effettuare se necessario il preventivo ordinamento del file affinche’ risulti ordinato in modo crescente secondo il campo cod_rec. ARRESTARE LA RICERCA NON APPENA IL RECORD VIENE TROVATO. Utilizzare la tecnica della programmazione strutturata.

 

 

Program f3

 

Type  scheda = record

        Cod_rec : string[10];

        Descrizione_record : string [ 100 ];

        end;

Var

        nomeflog : file of scheda;

        Buffer : scheda;

        flag: Boolean;

        codice : string[10];

Descrizione : string [ 100 ];

tabscheda : array [1..1000] of scheda;

kmax,k,i,j : integer;

posiz,  posiz_iniziale, posiz_finale : integer;

 

Procedure scambio;

Begin

Buffer.cod_rec  := tabscheda[i].cod_rec;

tabscheda[i].cod_rec  := tabscheda[j].cod_rec;

tabscheda[j].cod_rec :=  Buffer.cod_rec;

 

Buffer.descrixione_rec  := tabscheda[i].descrizione_rec;

tabscheda[i].descrizione_rec  := tabscheda[j].descrizione_rec;

tabscheda[j].descrizione_rec  :=  Buffer.descrizione_rec;

End;

 

Procedure Genera_file;

Begin

/* genero il file nuovo  */

Rewrite (nomeflog);

 

/*  scrivo (99) record sul file di record  */

for  I = 1 to 99

begin

buffer.cod_rec :=  ord(i):

while len (buffer.cod_rec) < 10 then

        buffer.cor_rec := “0” + buffer.cod_rec:

buffer.descrizione_rec:= “record numero” + “  “ +  buffer.cod_rec;

                Writeln (nomeflog, buffer);

        end; 

Close (nomeflog);

End;

 

Procedure trasfer_file_tabella;

Begin

/*  apro il file posizionando il puntatore di lettura in testa al file  */

        Reset(nomeflog);

 

        K:=0;

        While not eof (nomeflog)

        Begin

K:= K+1;

        Readln (nomeflog, tabscheda[k]);

End;

        Kmax := k

Close (nomeflog);

End;

       

Procedure ordina_tabella;

Begin

 

For i = 1 to kmax-1 do

Begin

For j= I+1 to kmax do

begin

If  tabscheda[i].cod_rec  > tabscheda [j].cod_rec  the scambio;

end;

        end;

end;

 

Procedure trasfer_tabella_file;

Begin

/*  apro il file creandolo di nuovo ovvero cancellando tutto il suo contenuto  */

        Rewrite(nomeflog);

 

        For K=1 to kmax;

        Begin

                Writeln (nomeflog, tabscheda[k];

End;

Close (nomeflog);

End;

 

 

 

 

 

 

Procedure ordina_file;

Begin

 

        Trasfer_file_tabella;

ordina_tabella;

traasfer_tabella_file;

end;

 

Procedure ricerca_record;

Begin

/*  apro il file posizionando il puntatore di lettura in testa al file  */

        Reset(nomeflog);

       

Posiz_iniziale :=1:

        posiz_finale :=kmax;

        Flag:= false;

fine_ricerca:=false

        repeat

                if posiz_iniziale=posiz_finale then

begin

posiz=posiz_iniziale;

fine_ricerca:=true;

                end

                else

begin

Posiz :=  (posiz_iniziale – 1) + int( (posiz_finale + 1 –posiz_iniziale) / 2);

                end;

Seek (nomeflog, posiz);

                Readln (nomeflog,buffer);

If codice = buffer.cod_rec then

Begin

Flag: = True;

fine_ricerca:=true;

Descrizione := descrizione.rec”

End;

                Else

                Begin

                        If codice > buffer.cod_rec then

                        begin       

Posiz_iniziale := posiz+ 1;

end

                else

begin

        posiz_finale := posiz – 1;   

until  flag = true  or fine_ricerca=true

 

Close (nomeflog);

 

End;

 

       

/* main program  */

       

Begin

/* assegno il nome fisico del file al nome logico  */

        Assign (nomeflog, “ARCHIV.DAT”);

       

/* chiamo la procedura per generare il file  */

Genera_file;

 

/* chiamo la procedura per ordinare il file  */

ordina_file;

 

/*  accetto il valore da ricercare nel file  */

Readln (codice);

 

/* chiamo la procedura per ricercare sul file  */

ricerca_record;

 

        If flag = “true” then

                Writeln (descrizione)

Else

Writeln(“record non trovato”);

 

End.

 


Esempio IV

Definire un file di record avente come struttura record i seguenti campi:

 

  “codice”     string (6)

  “classe”      string (4)

 “Alunno”     string (40)

 “Indirizzo”   string (40)

 “Importo_versato”   real

 

Supporre il file già esistente, non vuoto ed ordinato secondo i campi “Classe” + “Alunno”.

 

Leggere  tutto il file e stampare i vari record via via che questi vengono letti. Stampare tutti i campi di ogni record letti avendo cura di allineare verticalmente i campi corrispondenti di ciascun record. Effettuare un salto pagina del foglio al variare della classe (rottura di classe).

 

Considerando che di norma non si hanno classi superiori a 30 alunni, considerando che il foglio di stampa o meglio la stampante ad aghi sia impostata per 66 righe (foglio di lunghezza 11”  e densità di scrittura verticale di 6 linee per pollice) su ogni foglio si avranno tutti gli alunni di una classe stampati ordinati per cognome. Non esiste quindi il caso che alunni di una stasse classe vengano stampati su de fogli consecutivi per cui e’ inutile effettuare controlli di questo tipo onde evitare che un alunno venga stampato sulla linea di perforazione orizzontale tra due fogli contigui.

 

Completata la stampa degli alunni di una classe prima di saltare al foglio successivo stampare un rigo aggiuntivo con indicato il totale dell’importo versata a livello di classe dagli alunni di quella classe. 

 

Completata la stampa di tutte le classi (se si hanno 60 classi nella scuola si saranno stampati 60 fogli) stampare su un foglio successivo il totale riepilogativo di quanto e’ stata versato da tutti gli alunni a livello di istituto.

 

Ipotizzare per il report di stampa relativo al foglio di classe una struttura di questo tipo:

 

classe      alunno                       Indirizzo                             codice      importo versato

xxxx      xxxxxxxxxxxxxxxx  xxxxxxxxxxxxxxxxxxxx    xxxxxx              xxxxx,xx

xxxx      xxxxxxxxxxxxxxxx  xxxxxxxxxxxxxxxxxxxx    xxxxxx              xxxxx,xx

xxxx      xxxxxxxxxxxxxxxx  xxxxxxxxxxxxxxxxxxxx    xxxxxx              xxxxx,xx

…….     ……………………  …………………………    ……….            …………

xxxx      xxxxxxxxxxxxxxxx  xxxxxxxxxxxxxxxxxxxx    xxxxxx              xxxxx,xx

 

                                               --------------------------------------------------

Totale versato dalla classe: ---------             xxxxxx,xx

 

 

Ipotizzare per il report di stampa relativo al totale versato a livello di istituto una struttura di questo tipo:

 

Totale versato dall’istituto: --------             xxxxxx,xx

 

 

 

 

Program f4

 

Type  scheda = record

Codice:     string (6)

 Classe:      string (4)

 Alunno:     string (40)

 Indirizzo:   string (40)

 “Importo_versato:   real

        end;

Var

        nomeflog : file of scheda;

        Buffer : scheda;

        primavolta: Boolean;

        classe-alunno-pre: string[44];

classe-alunno-cor: string[44];

        Tot-classe:  real;

        Tot-istituto real;

        Riga: string (80);

 

Function  RiempiStrToStr (stringainput, sizemax) : string;

/* La procedura accoda alla stringa passata (stringainput) tanti (blank) a dx */

/* fino al raggiungimento di una lunghezza pari al valore di (sizemax) */

Var

        Stringainput : string

        Sizemax : integer;

        K: integer;

Begin

        If lengtht (stringainput) < sizemax then

        begin

                For k = 1 to (sizemax – length (stringainput))

                Begin

                        stringainput := stringainput = “ “;

                end;

end

else

begin

        stringainput := midstr (stringainput, 1, sizemax):

        end;

        RiempiStrToStr := stringainput;

end;

 

Function  RiempiNumToStr (Numeroinput, sizemax, Numerodecimali) : string;

/* La procedura trasforma il numero passato (Numeroinput) in stringa */

/* lo allinea a dx in un campo lungo (sizemax) */

/* inserisce un numero di decimali fino a (Numero decimali) */

/* inserisce la (virgola) di separazione tra la parte intera e quella decimale */

/* inserice il (punto) quale separazione nella parte intera tra le migliaia) */

/* inserisce tanti (blank) a sx  affinché la stringa di output sia lunga (sizemax) */

 

Var

       

Stringaotput : string

Numeroinput : real;

Sizemax : integer;

        K: integer;

 

***********  da completare **************

        ***********  da fare per compito **************

Begin

        Numeroinput := Rounded (Numeroinput, Numerodecimali);

        Stringaoutput := FloatToStr (Numeroinput)

        If lengtht (stringaoutput) < sizemax then

        begin

                For k = 1 to (sizemax – length (stringaoutput))

                Begin

                        stringaoutput := “ “ + stringaoutput;

                end;

end

else

begin

        stringaoutput := “”;

For k = 1 to sizemax

                Begin

                        stringaoutput := stringaoutput + “*”;

        end;

        end;

        RiempiNumToStr := stringaoutput;

end;

 

Procedure stampa-testata;

var

        testo :string;    

begin

        testo := “classe      alunno                       Indirizzo                             “;

testo := testo + “codice      importo versato”;

        writeln (lpt1, testo);

end;

 

Procedure stampa-corpo;

begin

        writeln (lpt1,riga);

end;

 

Procedure stampa-coda;

begin

        wirteln (lpt1, “----------------------------------------------------------“);

        writeln  (lpt1,  “totale versato dalla classe ------  “,  Tot-classe);

end;

 

procedure stampa-totale-versato-da-istituto;

Begin

writeln  (lpt1,  “totale versato dall’istituto  ------  “,  Tot-istituto);

end;

 

procedura after-page;

Begin

writeln  (lpt1,  ASCII (15));

end;

 

Procedure prepara-riga-stampa;

Begin

        Riga := “”;

        Riga := Riga + RiempiStrToStr (buffer.classe, 4);

        Riga := Riga + “   “;

Riga := Riga + RiempiStrToStr (buffer.alunno, 40);

        Riga := Riga + “   “;

Riga := Riga + RiempiStrToStr (buffer.indirizzo, 40);

        Riga := Riga + “   “;

Riga := Riga + RiempiStrToStr (buffer.codice, 6);

        Riga := Riga + “   “;

Riga := Riga + RiempiNumToStr (buffer.importo-versato, 10, 2);

end;

 

/* main Program */

Begin

/* assegno il nome fisico del file al nome logico  */

        Assign (nomeflog, “ARCHIV.DAT”);

       

/* apro il file  */

Reset (nomefllog);

 

/* reset delle variabili di comodo */

Tot-classe := 0;

Tot_isituto := 0:

classe-alunno-pre := “”;

classe-alunno-cor := “”;

primavolta := .T.;

 

/*  lettura sequenziale del file  */

While not eof(nomeflog) do

Begin

Read (nomeflog, buffer);

buffer-classe := riempi (buffer.classe,4);

buffer-alunno := riempi (buffer-alunno,40);

classe-alunno-cor := buffer.classe + buffer.alunno;

 

if primavolta = .T. then

begin

        classe-alunno-pre := classe-alunno-cor;

                        primavolta := .F.;

                        stampa-testata;

                end;

 

                if classe-alunno-cor <> classe-alunno-pre then