In Pascal è possibile avere oltre ai file testo, cioè
file di char, anche file di interi, stringhe, records.
Unica condizione è quella che se un file è ad
esempio dichiarato di interi esso non può
contenere che interi.
Tutti i file di tipo non-testo sono detti file binari.
La sintassi di un file binario è diversa da quella
di un file testo.
identificatore
=
FILE
OF
type
La estensione di un file testo è NomeFile.txt
La estensione di un file binario è NomeFile.dat
PROGRAM FileTesto(output, Teresa);
VAR
Teresa:text;
Ch:char;
BEGIN
END.
Preparazione alla lettura del file
reset(NomeFile) es. reset(Reals)
PROGRAM FileBinari(output, Ints,Reals,Records);
TYPE
String30=STRING[30];
NameType=RECORD
First,
Middle,
Last:String30;
END;
IntsFile=FILE OF integer;
RealsFile=FILE OF real;
RecFile=FILE OF NameType;
VAR
Ints:IntsFile;
Reals:RealsFile;
Names:RecFile;
BEGIN
END.
Preparazione alla scrittura del file
rewrite(NomeFile) es. rewrite(Reals)
Il controllo di fine file viene eseguito come per i text file con la
funzione <eof>
eof(NomeFile)
Essendo i dati scritti uno di seguito all’altro non esiste più l’<eoln>.
Nel caso del RecFile i record
descritti da
NameType=RECORD
First,
Middle,
Last:String30;
avremo
……………..Giulio Luca RossiCarlo Maria BianchiGian Giacomo Verdi
……………..
Area Dati
AName.First  Carlo
AName.Middle  Maria
AName.Last  Bianchi
Carlo Maria Bianchi
La lettura avviene record per record, non stringa per stringa
E’ possibile leggere anche più di un valore alla volta da un file.
Esempio
read(Reals, R1, R2, R3,….)
Per leggere un intero file si può far uso dell’ <eof>
Esempio
reset(Ints);
WHILE NOT eof(Ints) DO
BEGIN
read(Ints, Intero);
elabora(Intero)
END;
L’uso dell’ <eoln> produce un errore di sintassi.
E’ possibile scrivere in un file binario se ovviamente è stato preparato
TYPE
per la scrittura.
String30=STRING[30];
NameType=RECORD
Esempio
First,
write(Ints, AnInt, 3*AnInt);
Middle,
Last:String30;
write(Reals, Re1, 3.1416);
END;
IntsFile=FILE OF integer;
write(Names, AName);
RealsFile=FILE OF real;
RecFile=FILE OF NameType;
write(Names, Name1, Name2);
VAR
Come si vede anche più di un dato può
contemporaneamente essere scritto in un file binario.
Ints:IntsFile;
Reals:RealsFile;
Names:RecFile;
Attenzione !!!
Ogni elemento che si scrive deve essere dello stesso Type del file.
Quindi sono sbagliate le scritture del tipo
write(Ints, Re1, 3.2*Re1);
Errore
write(Reals, AnInt, AnInt DIV 2);
write(Names, Aname.First, Aname.Middle, Aname.Last);
Non essendoci <eoln> non è permesso il writeln.
!!!
COPIA DI FILE BINARI
Supponiamo di avere due file binary AFile e Bfile aventi lo
stesso Type le cui componenti sono del tipo ComponentType.
WHILE NOT eof(Afile) DO
read(Afile, Acomponent)
write(Bfile, Acomponent)
PROCEDURE CopyFile(VAR InNames, OutNames:RecFile);
VAR
AName:NameType;
BEGIN
WHILE NOT eof(InNames) DO
read(InNames, AName);
write(OutNames, AName)
END
END;
Si noti che con una sola operazione di read o write si possono
leggere molti valori contemporaneamente se questo è previsto
dalla struttura dei file in gioco.
Ad esempio un record con 20 campi può essere scritto con una
sola operazione e non campo per campo.
Nel caso in cui si vogliono dare i valori di un record campo per
campo, ad esempio da tastiera, allora si può adoperare la seguente
procedura:
WITH RecordVar DO
introduci il valore del campo
write(OutFile, RecordVar)
PROCEDURE WriteAName(VAR OutFile:NameFile);
VAR
TYPE
String30=STRING[30];
Aname: NameType;
NameType=RECORD
First,
BEGIN
Middle,
Last:String30;
WITH Aname DO
END;
BEGIN
IntsFile=FILE OF integer;
OF real;
write(‘ First Name: ‘); RealsFile=FILE
RecFile=FILE OF NameType;
VAR
readln(First);
Ints:IntsFile;
write(‘ Middle Name: ‘);
Reals:RealsFile;
Names:RecFile;
readln(Middle );
write(‘ Last Name: ‘);
readln(Last );
END;
write(OutFile, AName)
END;
Studente
Anagrafe
Nascita
Matricola AnnoCorso Risultati Media
Cognome Nome Giorno Mese Anno
TYPE
Stringa20 = STRING[20]
RisultatiArray =ARRAY[1..TotaleProve] OF integer;
AnagraficaRecord = RECORD
Cognome,
Nome : Stringa20
END;
StuRecord
CONST
MaxStud=150;
TYPE
StuRecord = RECORD
……………….
END;
ClassArray=ARRAY[1..Maxstud] OF StuRecord;
StuRecFile=FILE OF StuRecord;
VAR
InFile:StuRecFile;
AClass: ClassArray;
TotalStudents:integer;
DataRecord = RECORD
Giorno,
Mese,
Anno : integer
END;
= RECORD
Anagrafe :AnagraficaRecord ;
Nascita:DataRecord ;
Matricola :StringaNome ;
AnnoCorso :StringaNome ;
Risultati:RisultatiArray ;
Media:real;
END;
Procedura per la costruzione di un Array di record a partire da
un file binario.
Supponiamo di introdurre meno di MaxStud record
PROCEDURE FillClass(VAR AClass: ClassArray; VAR TotalStudents: integer;
VAR InFile: StuRecFile);
VAR
AStudent: StuRecord;
BEGIN
StuRecord
= RECORD
TotalStudents:=0;
Anagrafe:AnagraficaRecord;
reset(InFile);
Nascita:DataRecord;
Matricola:StringaNome;
WHILE NOT eof(InFile) DO
AnnoCorso:StringaNome;
BEGIN
Risultati:RisultatiArray;
Media:real;
TotalStudents:= TotalStudents+1;
END;
read(InFile, AStudent);
Aclass[TotalStudents]:=AStudent
END
END;
AGGIORNAMENTO DI FILE DI RECORD BINARI
Dati due File di record binari ordinati, fare il merge del primo nel
secondo producendo un terzo file ordinato.
Corso Programmazione
Sessione Invernale
CSPI99
Corso Programmazione
Sessione Estiva
CSPE99
OldMaster
Semester
StuRecord
merge
Sessione
StuRecord
MStuRec
NewMaster
Corso Programmazione
CSP99
MStuRec
Sessione
StuRecord
Alcuni suggerimenti sui file
Evitare di usare il REPEAT … UNTIL quando si leggono file binari o testo.
reset(SomeFile)
REPEAT
read(SomeFile,SomeComponent)
elabora(SomeComponent)
UNTIL eof(SomeFile)
CORRETTO !!!!!!!!!!
SBAGLIATO !!!!!!!!!!
reset(SomeFile)
IF NOT eof(SomeFile) THEN
REPEAT
read(SomeFile,SomeComponent)
elabora(SomeComponent)
UNTIL eof(SomeFile)
Non mettere mai un reset o un rewrite all’interno di un loop.
WHILE NOT eof(SomeFile) DO
BEGIN
SBAGLIATO
reset(SomeFile);
read(SomeFile,SomeComponent)
elabora(SomeComponent)
END;
!!!!!!!!!!
Ricordare che il valore di una variabile file cambia sempre quando si usano il read o il
write, quindi le chiamate alle variabili file vanno sempre fatte per VAR e mai per valore.
Ricordare che readln e writeln si possono usare solo con i file testo e non con i file binari.
Quando si implementano procedure per la gestione di file realizzare sempre procedure per
provare se i record o comunque i dati sono correttamente inseriti facendo le prove con pochi
esempi.
UNIT STRINGHE
Si vuole creare una UNIT che operi sulle stringhe e che sia il più
possibile indipendente dal dialetto PASCAL adoperato.
Adoperiamo una struttura a RECORD per il data Type
StringADT
Chars
Array
Len
UNIT Stringa;
INTERFACE
CONST
MaxLength=80;
TYPE
SysString=STRING[MaxLength];
StringADT=RECORD
Chars:ARRAY[1.. MaxLength] OF char;
Len:0.. MaxLength
END;
Constructor - cambia o inizializza i valori di una variabile astratta
Primitive constructor - assegna un valore ad una variabile astratta
senza fare uso di altre variabili astratte dello stesso tipo. Ha una sola
variabile di output e quelle di input servono per costruire l’output.
IMPLEMENTATION
PROCEDURE NullString(VAR OutStr:StringADT);
BEGIN
END;
Primitive constructor
ritorna una la stringa nulla ‘’.
PROCEDURE ConvertSysString(StrValue:SysString; VAR OutStr:StringADT);
VAR
Position:1..MaxLength;
BEGIN
WITH OutStr DO
BEGIN
Len:=length(StrValue);
FOR Position:=1 TO Len DO
Chars[Position]:=StrValue[Position]
END
END;
converte una stringa rappresentata in un qualche sistema
nella stringa equivalente di type StringADT
Primitive constructor
PROCEDURE ReadString(Sentinel:char;VAR OutStr:StringADT;
VAR InFile:text);
VAR
Ch:char;
BEGIN
WITH OutStr DO
BEGIN
Len:=0;
ReadCh(Sentinel,Ch,Len,InFille)
WHILE Ch<>Sentinel DO
BEGIN
Len:=Len+1;
Chars[Len]:=Ch;
ReadCh(SentinelCh,Len,InFile)
END
END
END;
legge la stringa da un file escludendo eventuali caratteri sentinella
Primitive constructor
PROCEDURE ReadlnString (Sentinel:char; VAR OutStr:StringADT;VAR InFile:text);
VAR
Ch:char;
BEGIN
WITH InString DO
BEGIN
Len:=0;
WHILE NOT eoln(InFile) AND NOT (Len=MaxLength) DO
BEGIN
Read(Infile,Ch);
Len:=Len+1;
Chars[Len]:=Ch;
END
END
END;
legge una stringa da una linea di un file predeterminato
SELECTOR - fornisce informazioni su una variabile di input
ADT ad un parametro di uscita. Spesso è una funzione (il parametro
di uscita in tal caso è la funzione stessa).
Primitive selector - ritorna il valore di uno dei componenti della
variabile astratta.
FUNCTION ACh(Instr:StringADT;Position:integer):char;
BEGIN
IF Position>InStr.Len THEN
Ach:=chr(0)
ELSE
Ach:=InStr.Chars[Position]
END;
Primitive selector
ritorna il carattere N-esimo di una stringa
FUNCTION StrLength(Instr:StringADT):integer;
BEGIN
StrLength:=Instr.Len
END;
ritorna la lunghezza della stringa
Primitive selector
Non-primitive selector - ritorna il valore che non è relativo ad uno
dei componenti della variabile astratta ma ciò nonostante è utile al
client.
PROCEDURE WriteString (InStr:StringADT; VAR OutFile:text);
VAR
Position:integer;
BEGIN
Non-primitive
WITH InStr DO
FOR Position:=1 TO Len DO
write(OutFile,Chars[Position])
END;
selector
scrive una stringa in un file
PROCEDURE WritelnString(InStr:StringADT; VAR OutFile:text);
BEGIN
WriteString(Instr,OutFile);
Non-primitive
writeln(OutFile)
END;
scrive una stringa in un file seguita da un <eoln>
selector
FUNCTION StartPos((Substr, SearchStr:StringADT):integer;
VAR
SLen,Pos: integer;
Found: Boolean;
CandStr: StringADT;
BEGIN
SLen:=SubStr.Len;
Found:=FALSE;
Pos:=1;
WHILE NOT (SearchStr.Len+1-Pos>SLen) AND NOT Found DO
BEGIN
StrExtract(SearcStr,Pos,SLen,CandStr);
IF StrEqual(CandStr,SearchStr) THEN
Found:=TRUE
ELSE
Selector operations
Pos:=Pos+1
END;
IF Found THEN
StratPos:=Pos
ELSE
StratPos:=0
Ritorna la posizione di partenza di una data subEND;
stringa nell’ambito di una preassegnata stringa
PREDICATE - è una funzione booleana che ritorna informazioni
sul valore o lo stato di una variabile astratta.
FUNCTION StrEqual(Instr1, Instr2:StringADT):boolean;
VAR
Pos,
TotalChars:integer;
StillEqual:boolean;
Predicate operations
BEGIN
IF Instr1.Len<>Instr2.Len THEN
StillEqual:= FALSE
ELSE
StillEqual:= TRUE;
TotalChars:= Instr1.Len;
Pos:=1;
WHILE NOT(Pos>TotalChars) AND StillEqual DO
IF Minuscole(InStr1.Chars[Pos])<> Minuscole(InStr2.Chars[Pos])
THEN
StillEqual:= FALSE
ELSE
Pos:=Pos+1;
StrEqual:=StillEqual
END;
ritorna TRUE se due stringhe hanno gli stessi caratteri e la stessa
lunghezza
Predicate operations
FUNCTION StrLessThan(InStr1, InStr2:StringADT):boolean
BEGIN
……………….
END;
ritorna TRUE se la prima stringa precede alfabeticamente la seconda
Non-primitive constructor -. Ha almeno una variabile di input il cui
tipo è uguale a quello dell’output.
Non-primitive constructor
PROCEDURE ChConcat (Ch; VAR InOutStr:StringADT);
BEGIN
WITH InOutStr DO
IF Len<MaxLength THEN
BEGIN
Len:=Len+1;
Chars[Len]:=Ch
END
END;
concatena un singolo carattere ad una stringa
PROCEDURE StrExtract(InStr:StringADT; Start, TotalChs:integer; VAR OutStr: StringADT);
VAR
InStrPos,
OutStrPos
:integer;
Non-primitive constructor
BEGIN
WITH OutStr DO
BEGIN
IF Start > Instr.Len THEN
Len:=0
ELSE IF TotalChs > InStr.Len+1-Start THEN
Len:=InStr.Len+1-Start
ELSE
Len:=TotalChs;
InStrPos:=Start;
FOR OutStrPos:=1 TO Len DO
BEGIN
Chars[OutStrPos]:=InStr.Chars[InStrPos];
InStrPos:=InStrPos+1
END
END
END;
copia una stringa di una predeterminata lunghezza a partire da una
determinata posizione in una stringa di output
PROCEDURE StrRemove(Start, TotalChs:integer; VAR InOutStr: StringADT);
PredString,
Non-primitive constructor
SuccString:
StringADT;
BEGIN
IF NOT (Start>InOutStr.Len) THEN
BEGIN
StrExtract(InOutStr,1,Start-1,PredString);
StrExtract(InOutStr,1,Start+TotalChs,InOutStr.Len,SuccString);
StrConcat(PredString, SuccString,InOutStr)
END
END;
rimuove un predeterminato numero di caratteri a partire da
una certa posizione di una stringa di input/output
PROCEDURE StrInsert(InStr:StringADT; Start:integer; VAR InOutStr: StringADT);
BEGIN
END;
inserisce un predeterminata stringa di caratteri a partire da una
certa posizione in una variabile stringa.
Non-primitive constructor
PROCEDURE ReadCh(Sentinel:char;PresentLength:integer;
VAR Ch:char;VAR InFile:text);
BEGIN
IF NOT(eoln(InFile) OR (PredsentLength= MaxLength)) THEN
Read(InFile,Ch);
ELSE
Ch:=Sentinel
END;
legge i caratteri di una stringa da un file e se supera la lunghezza
prefissata o trova eoln restituisce un carattere sentinella
FUNCTION Minuscole(Ch:char):char;
BEGIN
IF Ch IN ['A'..'Z'] THEN
Minuscole:=chr(ordCh)+ord('a')-ord('A'))
ELSE
Minuscole:=Ch
END;
trasforma le maiuscole in minuscole
PROCEDURE ChConcat (Ch; VAR InOutStr:StringADT);
BEGIN
WITH InOutStr DO
IF Len<MaxLength THEN
BEGIN
Len:=Len+1;
Chars[Len]:=Ch
END
END;
concatena i caratteri in una stringa controllando che la
lunghezza massima non venga superata
Sia assegnato un file così caratterizzato
<Indirizzo Mittente>
ESERCIZIO
Informazioni Varie
<Fine Indirizzo>
Testo Messaggio
………………….
<Indirizzo Mittente >
Informazioni Varie
<Fine Indirizzo>
Testo Messaggio
………………….
<Indirizzo Mittente >
Informazioni Varie
<Fine Indirizzo>
Testo Messaggio
………………….
Scrivere una procedura per estrarre
per ogni mittente solo
il testo del messaggio.
Costruire un array con gli indirizzi
dei mittenti.
Mostrare per ogni mittente il
messaggio
Scarica

LEZIONE file binari sito