Standardfilerna Input och Output
I
Standardfilerna Input och Output är textfiler av typen TEXT (som bara finns för filer).
I
Innehållet är av typen Char och filerna är strukturerade i form av rader.
I
En sådan fil kan läsas på vanligt sätt (med Emacs, more, . . . )
I
I standard Pascal skall programhuvudet, i program som använder in- och utmatning, innehålla
PROGRAM test(Input, Output);
I
Filerna kan omdirigeras med ” > ” och ” < ” (i UNIX) Ex. a.out < d.d > r.r
Om det finns en fil d.d så kommer alla satser Read(variabellista) eller
ReadLn(variabellista)
läsas från filen d.d och om vi läser en variabel av typen Integer så sker konvertering automatiskt.
Alla satser Write(variabellista) kommer att skrivas på filen r.r
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 1 / 24
Filer . . .
I
En fil är en strukturerad typ där alla poster är av samma typ.
I
Man kan alltså skriva hela poster på filen!
I
Alla filer utom Input och Output skall deklareras.
I
Exempel på fildeklarationer:
TYPE fil = FILE OF elementtyp;
VAR minFil : fil;
bilregister : FILE OF car;
infil : FILE OF Integer;
utfil : FILE OF studentUppgifter;
txt : TEXT; {Fördefinierad filtyp}
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 2 / 24
Filer Input & Output
Filer . . . filtyper
Filer kan vara
Interna: Filer deklareras och öppnas med Rewrite(filnamn)
Då blocket, där filen öppnades, lämnas går innehållet förlorat.
Externa: Ordnad (efter insättningsordning) lista på sekundärminnet.
Filerna ges som parametrar i programhuvudet och deklareras i deklarationsdelen. Filer öppnas för läsning med
Reset(filnamn) och för skrivning med Rewrite(filnamn)
Filer Input & Output
Filer . . . vanlig utbyggnad för ökad dynamik
Man kan också öppna filer på följande sätt (inte standard):
För läsning: Reset(filnamn, fysisktNamn);
Man får ett fel om filen inte finns.
För skrivning: Rewrite(filnamn,fysisktNamn);
Om filen redan finns så raderas den (töms på sitt innehåll).
Exempel: Reset(minFil,’filnamn.p’);
Filerna stängs då man lämnar det block där de öppnades eller då satsen Close(filnamn) exekveras
(inte standard).
Filer . . . fördefinierade procedurer och funktioner
Fördefinierade procedurer och funktioner:
Infil
ReSet(f) Öppna filen f för läsning Read(f, varlista) läs från filen f
ReadLn(f, varlista) Endast för textfil
Eof(f) TRUE om sista item har lästs EoLn(f) Endast för textfil
Utfil
ReWrite(f) Öppna filen f för skrivning Write(f, varlista) Skriv på filen f
WriteLn(f, varlista) Endast för textfil
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 5 / 24
Filer . . . filbufferten
Varje fil har ett minnesutrymme som rymmer exakt en post, minnesutrymmet kallas filbuffert.
Man kan komma åt innehållet i filbufferten med f^
Write(f, p1);
Är ekvivalent med:
f^ := p1; {kopiera p1 till filbufferten}
Put(f); {skriv buffertens innehåll på filen}
Read(f, p1);
Är ekvivalent med:
p1 := f^; {kopiera filbufferten till p1}
Get(f); {hämta nästa post till filbuff}
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 6 / 24
Filer Input & Output
Filer . . . filbufferten (2)
Ex: Operativsystemet hanterar filerna i block (eller sidor) med en storlek av tex 2048 byte.
Då man läser från filen är den minsta enheten ett block. Blocket läses till en area i primärminnet och från denna till pascals filbuffert.
Filbufferten i pascal rymmer exakt en post av filtypen. Då en fil har ”öppnats”
har vi följande situation:
fil
programvariabel filbuffert
OS−buffert
Filer Input & Output
Filer . . . filbufferten (3)
Ex: Operativsystemet hanterar filerna i block (eller sidor) med en storlek av tex 2048 byte.
Då man läser från filen är den minsta enheten ett block. Blocket läses till en area i primärminnet och från denna till pascals filbuffert.
Filbufferten i pascal rymmer exakt en post av filtypen. Då en fil har ”öppnats”
har vi följande situation:
Och
fil
programvariabel filbuffert
OS−buffert
efter att Read(fil, programvariabel); utförs
Filer . . . fil med binärt innehåll (skrivning)
PROGRAM storeIntegers (Input, Output, intFile);
TYPE
integerFile = FILE OF Integer;
VAR
intFile : integerFile;
BEGIN
ReWrite(intFile);
WriteLn(’Heltal: (sluta med negativt tal) ’);
REPEAT
Read(intFile^);
IF intFile^ >= 0 THEN Put(intFile);
UNTIL intFile^ < 0;
END.
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 9 / 24
Filer . . . fil med binärt innehåll (läsning)
PROGRAM sumInt(Input,Output,intFile);
TYPE
integerFile = FILE OF Integer;
VAR
intFile : integerFile;
sum, tmp : Integer;
BEGIN
Reset(intFile);
sum := 0;
WHILE NOT EoF(intFile) DO BEGIN Read(intFile, tmp);
sum := sum + tmp END;
Writeln(’Summan=’, sum) END.
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 10 / 24
Filer Input & Output
Filer . . . fil med läsbart innehåll (läsning)
PROGRAM sumInt(Input, Output, intFile);
VAR
intFile : TEXT;
sum, tmp : Integer;
BEGIN
Reset(intFile);
sum := 0;
WHILE NOT EoF(intFile) DO BEGIN Read(intFile, tmp);
sum := sum + tmp END;
Writeln(’Summan=’, sum) END.
Filer Input & Output
Filer . . . fil med läsbart innehåll (2)
Vi kan skriva filen intfile med hjälp av Emacs.
Problem: Om det efter sista heltalet finns ett radbyte eller något annat tecken kommer vi att försöka läsa ett heltal. Eftersom det man hittar på filen inte är en siffra kommer det att bli felavbrott! Lösning på problemet:
PROGRAM sumInt(Input, Output, intFile);
VAR
tal, sum : Integer;
intFile : TEXT;
PROCEDURE skipUntilNextDigit(VAR aFile : TEXT);
BEGIN
IF NOT EoF(aFile) THEN
IF NOT (aFile^ IN [’0’..’9’]) THEN BEGIN Get(aFile);
skipUntilNextDigit(aFile) END;
END;
Filer . . . fil med läsbart innehåll (3)
BEGIN
Reset(intFile);
sum := 0;
skipUntilNextDigit(intFile);
WHILE NOT EoF(intFile) DO BEGIN Read(intFile, tmp);
sum := sum + tmp;
skipUntilNextDigit(intFile) END;
Writeln(’Summan=’, sum) END.
Get , Read och ReadLn läser även EoLn -”markeringar”.
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 13 / 24
Filer . . . interna filer
En intern fil fungerar som en extern fil förutom att innehållet försvinner då filen stängs (då blocket, där den öppnades, lämnas) samt att den inte skall
specificeras som programparameter då ju programparametrarna utgör kommunikation mellan program och yttre enheter.
Ex: Gör ett program som i en text byter alla förekomster av { mot (* och alla } mot *) .
Spar texten på en intern fil med alla byten utförda. Överför sedan den interna filen till den externa filen. Utbytet görs genom satserna
IF fromFile^=’{’ THEN Write(toFile, ’(*’) ELSE IF fromFile^=’}’ THEN
Write(toFile, ’*)’) ELSE
Write(toFile, fromFile^);
Get(fromFile);
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 14 / 24
Filer Input & Output
Filer . . . interna filer (2)
PROGRAM ex(fil);
VAR fil, tmp: TEXT;
PROCEDURE copyFile(VAR fromFile, toFile: TEXT);
BEGIN
WHILE NOT EoF(fromFile) DO BEGIN
IF EoLN(fromFile) THEN WriteLn(toFile);
IF fromFile^=’{’ THEN Write(toFile, ’(*’) ELSE IF fromFile^=’}’ THEN Write(toFile, ’*)’) ELSE Write(toFile, fromFile^);
Get(fromFile) END
END;
BEGIN
ReSet(fil);
ReWrite(tmp);
copyFile(fil, tmp);
ReSet(tmp);
ReWrite(fil);
copyFile(tmp, fil);
END.
Filer Input & Output
Filer . . . dynamiska variabler / pekare
Då dynamiska variabler skrivs till en fil spars även pekare.
Då posterna läses från filen till programmet hamnar posterna inte säkert på samma ställe i minnet där de fanns innan de sparades på filen.
Därför måste pekare alltid återställas efter inläsning från fil.
Ex.:
Då ett program terminerar spars en lista på en fil och då programmet
återstartas läser man in elementen från filen och återskapar listan.
Filer . . . dynamiska variabler / pekare (2)
PROGRAM ex(inPut, outPut, elementFile);
TYPE elementPtr = ^element;
element = RECORD
info : < user defined >;
next : elementPtr;
END;
listPtr = ^list;
list = RECORD
first : elementPtr;
END;
elFile = FILE OF element;
VAR theList : listPtr;
listFile : elFile;
< diverse procedurer och funktioner >
BEGIN
theList := newList;
readListFromFile(theList, listFile);
run;
saveListOnFile(theList, listFile);
END.
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 17 / 24
Filer . . . dynamiska variabler / pekare (3)
PROCEDURE readListFromFile(aList: listPtr; VAR aFile:elFile);
PROCEDURE readEl(VAR elPtr: elementPtr);
BEGIN
IF EoF(aFile) THEN elPtr := NIL ELSE BEGIN
NEW(elPtr);
Read(aFile, elPtr^);
readEl(elPtr^.next) END
END;
BEGIN
ReSet(aFile);
readEl(aList^.first) END;
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 18 / 24
Filer Input & Output
Filer . . . dynamiska variabler / pekare (4)
PROCEDURE saveListOnFile(aList: listPtr; VAR aFile:elFile);
VAR elPtr: elementPtr;
BEGIN
elPtr := aList^.first;
WHILE elPtr <> NIL DO BEGIN Write(aFile, elPtr^);
elPtr := elPtr^.next END
END;
Filer Input & Output
Filer . . . dynamiska variabler / pekare (5)
PROCEDURE run;
BEGIN
< fråga efter kommando >
IF valid(kommando) THEN
IF kommando = < första alt > THEN exec1stCommand ELSE ...
ELSE error;
IF kommando <> exit THEN run;
END;
Eftersom pekarnas värden inte är meningsfulla efter inläsning kan man
utelämna dessa då posterna spars.
Filer . . . dynamiska variabler / pekare (6)
TYPE
elementPtr = ^element;
item = RECORD
< user defined >
END;
element = RECORD info : item;
next : elementPtr;
END;
listPtr = ^list;
list = RECORD
first : elementPtr;
END;
elFile = FILE OF item;
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 21 / 24
Filer . . . dynamiska variabler / pekare (7)
PROCEDURE readListFromFile(aList: listPtr;
VAR aFile: elFile);
PROCEDURE readEl(VAR elPtr: elementPtr);
BEGIN
IF EoF(aFile) THEN elPtr := NIL ELSE BEGIN
NEW(elPtr);
Read(aFile, elPtr^.info);
readEl(elPtr^.next) END
END;
BEGIN
ReSet(aFile);
readEl(aList^.first) END;
DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 22 / 24
Filer Input & Output
Filer . . . dynamiska variabler / pekare (8)
PROCEDURE saveListOnFile(aList: listPtr;
VAR aFile: elFile);
PROCEDURE writeEl(elPtr:elementPtr);
BEGIN
IF elPtr <> NIL THEN BEGIN Write(aFile, elPtr^.info);
writeEl(elPtr^.next) END
END;
BEGIN
ReWrite(aFile);
writeEl(aList^.first);
END;
Filer Input & Output
Filer . . . dynamiska variabler / pekare (9)
Obs att elementens minnesutrymme måste avallokeras om programmet inte terminerar.
PROCEDURE saveListOnFile(aList: listPtr;
VAR aFile: elFile);
PROCEDURE writeEl(elPtr:elementPtr);
BEGIN
IF elPtr <> NIL THEN BEGIN Write(aFile, elPtr^.info);
writeEl(elPtr^.next);
Dispose(elPtr) END
END;
BEGIN
ReWrite(aFile);
writeEl(aList^.first);
END;