Standardfilerna Input och Output... Standardfilerna Input och Output är textfiler av typen TEXT (som bara finns för filer). Innehållet är av typen Char och filerna är strukturerade i form av rader. En sådan fil kan läsas på vanligt sätt (med Emacs, more,... ) I standard Pascal skall programhuvudet, i program som använder in- och utmatning, innehålla PROGRAM test(input, Output); na 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 En fil är en strukturerad typ där alla poster är av samma typ. Man kan alltså skriva hela poster på filen! Alla filer utom Input och Output skall deklareras. Exempel på fildeklarationer: TYPE fil = FILE OF elementtyp; 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 1 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 2 / 24... filtyper... vanlig utbyggnad för ökad dynamik kan vara Interna: 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. na ges som parametrar i programhuvudet och deklareras i deklarationsdelen. öppnas för läsning med Reset(filnamn) och för skrivning med Rewrite(filnamn) 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 ); na stängs då man lämnar det block där de öppnades eller då satsen Close(filnamn) exekveras (inte standard). DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 3 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 4 / 24
... fördefinierade procedurer och funktioner... filbufferten Fördefinierade procedurer och funktioner: Infil Utfil ReSet(f) Read(f, varlista) ReadLn(f, varlista) Eof(f) EoLn(f) ReWrite(f) Write(f, varlista) WriteLn(f, varlista) Öppna filen f för läsning läs från filen f Endast för textfil TRUE om sista item har lästs Endast för textfil Öppna filen f för skrivning Skriv på filen f Endast för textfil 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 5 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 6 / 24... filbufferten (2)... 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: 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 fil OS buffert filbuffert programvariabel OS buffert filbuffert programvariabel efter att Read(fil, programvariabel); utförs DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 7 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 8 / 24
... fil med binärt innehåll (skrivning)... fil med binärt innehåll (läsning) PROGRAM storeintegers (Input, Output, intfile); TYPE integerfile = FILE OF Integer; intfile : integerfile; ReWrite(intFile); WriteLn( Heltal: (sluta med negativt tal) ); REPEAT Read(intFile^); IF intfile^ >= 0 THEN Put(intFile); UNTIL intfile^ < 0;. PROGRAM sumint(input,output,intfile); TYPE integerfile = FILE OF Integer; intfile : integerfile; sum, tmp : Integer; Reset(intFile); sum := 0; WHILE NOT EoF(intFile) DO Read(intFile, tmp); sum := sum + tmp Writeln( Summan=, sum). DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 9 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 10 / 24... fil med läsbart innehåll (läsning)... fil med läsbart innehåll (2) PROGRAM sumint(input, Output, intfile); intfile : TEXT; sum, tmp : Integer; Reset(intFile); sum := 0; WHILE NOT EoF(intFile) DO Read(intFile, tmp); sum := sum + tmp Writeln( Summan=, sum). 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); tal, sum : Integer; intfile : TEXT; PROCEDURE skipuntilnextdigit( afile : TEXT); IF NOT EoF(aFile) THEN IF NOT (afile^ IN [ 0.. 9 ]) THEN Get(aFile); skipuntilnextdigit(afile) DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 11 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 12 / 24
... fil med läsbart innehåll (3)... interna filer Reset(intFile); sum := 0; skipuntilnextdigit(intfile); WHILE NOT EoF(intFile) DO Read(intFile, tmp); sum := sum + tmp; skipuntilnextdigit(intfile) Writeln( Summan=, sum). Get, Read och ReadLn läser även EoLn- markeringar. 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 13 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 14 / 24... interna filer (2)... dynamiska variabler / pekare PROGRAM ex(fil); fil, tmp: TEXT; PROCEDURE copyfile( fromfile, tofile: TEXT); WHILE NOT EoF(fromFile) DO IF EoLN(fromFile) THEN WriteLn(toFile); IF fromfile^= { THEN Write(toFile, (* ) ELSE IF fromfile^= } THEN Write(toFile, *) ) ELSE Write(toFile, fromfile^); Get(fromFile) ReSet(fil); ReWrite(tmp); copyfile(fil, tmp); ReSet(tmp); ReWrite(fil); copyfile(tmp, fil);. 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. DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 15 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 16 / 24
... dynamiska variabler / pekare (2)... dynamiska variabler / pekare (3) PROGRAM ex(input, output, elementfile); TYPE elementptr = ^element; element = RECORD info : < user defined >; next : elementptr; listptr = ^list; list = RECORD first : elementptr; elfile = FILE OF element; thelist : listptr; listfile : elfile; < diverse procedurer och funktioner > thelist := newlist; readlistfromfile(thelist, listfile); run; savelistonfile(thelist, listfile);. PROCEDURE readlistfromfile(alist: listptr; afile:elfile); PROCEDURE readel( elptr: elementptr); IF EoF(aFile) THEN elptr := NIL ELSE NEW(elPtr); Read(aFile, elptr^); readel(elptr^.next) ReSet(aFile); readel(alist^.first) DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 17 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 18 / 24... dynamiska variabler / pekare (4)... dynamiska variabler / pekare (5) PROCEDURE savelistonfile(alist: listptr; afile:elfile); elptr: elementptr; elptr := alist^.first; WHILE elptr <> NIL DO Write(aFile, elptr^); elptr := elptr^.next PROCEDURE run; < fråga efter kommando > IF valid(kommando) THEN IF kommando = < första alt > THEN exec1stcommand ELSE... ELSE error; IF kommando <> exit THEN run; Eftersom pekarnas värden inte är meningsfulla efter inläsning kan man utelämna dessa då posterna spars. DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 19 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 20 / 24
... dynamiska variabler / pekare (6)... dynamiska variabler / pekare (7) TYPE elementptr = ^element; item = RECORD < user defined > element = RECORD info : item; next : elementptr; listptr = ^list; list = RECORD first : elementptr; elfile = FILE OF item; PROCEDURE readlistfromfile(alist: listptr; afile: elfile); PROCEDURE readel( elptr: elementptr); IF EoF(aFile) THEN elptr := NIL ELSE NEW(elPtr); Read(aFile, elptr^.info); readel(elptr^.next) ReSet(aFile); readel(alist^.first) DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 21 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 22 / 24... dynamiska variabler / pekare (8)... dynamiska variabler / pekare (9) Obs att elementens minnesutrymme måste avallokeras om programmet inte terminerar. PROCEDURE savelistonfile(alist: listptr; afile: elfile); PROCEDURE writeel(elptr:elementptr); IF elptr <> NIL THEN Write(aFile, elptr^.info); writeel(elptr^.next) ReWrite(aFile); writeel(alist^.first); PROCEDURE savelistonfile(alist: listptr; afile: elfile); PROCEDURE writeel(elptr:elementptr); IF elptr <> NIL THEN Write(aFile, elptr^.info); writeel(elptr^.next); Dispose(elPtr) ReWrite(aFile); writeel(alist^.first); DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 23 / 24 DA2001 (Föreläsning 19) Datalogi 1 Hösten 2010 24 / 24