Fält (listor) Kontinuerliga listor En lista av värden 2 3 4 5 6 7 8 9... kan naturligtvis representeras av tal1, tal2, tal3,... men det finns då ingen möjlighet att välja element utan att explicit ange vilket av talen i programkoden. Man kan t.ex. inte ge i ett värde och sedan skriva Write(tali); En matematiker löser problemet med hjälp av index (tal i ) Man måste kunna skilja på tali där variabeln består av 4 tecken och tali där variabeln består av 3 tecken och det 4:e tecknet, i, är ett index. I har man löst det genom att index anges inom [ och ] Write(tal[i]); Som index kan allt som har diskret värde användas (även uttryck vars värde är diskret). De listor vi hittills tittat på har varit diskontinuerliga homogena listor. Alla element ligger i en följd i datorns minne och index är då ett offset från första komponenten. En sådan struktur kräver att utrymme reserveras då programmet startas och listorna kan alltså inte inte växa dynamiskt. En homogen kontinuerlig lista kallas för fält, vektor, tabell, lista,... Den måste deklareras: Undre gräns för index Övre gräns för index VAR tal : ARRAY [4..27] OF Integer; Variabelnamn Elementtyp DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 1 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 2 / 25 Kontinuerliga listor... Kontinuerliga listor... Vi kan naturligtvis typspecificera allt: TYPE index = 4..27; element = 0..Maxint; vektor = ARRAY [index] OF element; VAR tal: vektor; Om vi skriver : VAR tal: ARRAY[1..20] OF Integer; pos: ARRAY[1..20] OF Integer; så är inte tal och pos av samma typ och man kan inte skriva: tal := pos (vilket man annars kan göra ) men tal[3] := pos[9] går ju bra! Om vi i stället typspecificerar: TYPE vektor = ARRAY[1..20] OF Integer; VAR pos: vektor; tal: vektor; så är tal och pos av samma typ. Man kan också deklarera dem på samma rad VAR tal, pos: ARRAY[1..20] OF Integer; så blir de av samma typ. Detta är en följd av att använder namnekvivalens för typer! Om vi vill ha en kontinuerlig lista som parameter i en funktion måste vi typspecificera annars kan vi inte anropa funktionen! DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 3 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 4 / 25
Kontinuerliga listor... Kontinuerliga listor flerdimensionella fält PROGRAM test; FUNCTION sum(var t:table):item; CONST low = 1; VAR tmpsum:item; high = 10; PROCEDURE additem(var i:item); TYPE index = low..high; natural = 0..Maxint; tmpsum := tmpsum + i item = natural; table = ARRAY [index] OF item; VAR tal : table; tmpsum := 0; PROCEDURE dotoeach(var t:table; dotoeach(t, additem); PROCEDURE todo(var i:item)); sum := tmpsum FOR i := low TO high DO todo(t[i]); Huvudprogram Write( Mata in talen ); PROCEDURE readtable(var t:table); readtable(tal); PROCEDURE readitem(var i:item); Writeln( Summan =,sum(tal)). Read(i) dotoeach(t, readitem) TYPE vektor = ARRAY [1..20] OF Integer; matris = ARRAY [1..10] OF vektor; tensor = ARRAY [5..13] OF matris; VAR a : matris; v : vektor;... a[2] := a[3]; a[5] := v; DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 5 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 6 / 25 Fält/kontinuerliga listor... Räkna olika sorters tecken i löpande text Man kan inte: Skriva hela fält på skärmen, läsa hela fält från tangentbordet eller jämföra hela fält med varandra. Man skulle även kunna deklarera tensor som: TYPE tensor = ARRAY[5..13, 1..10, 1..20] OF Integer; Vilket är ekvivalent med den tidigare specifikationen. En variabel av typen tensor kan indexeras med 1, 2, eller 3 index. Ex: VAR a: tensor;... a[5] := a[8]; a[5, 3] := a[8, 1]; a[5][3] := a[8, 1];... PROGRAM symbolcount; CONST low = A ; high = Z ; TYPE index = low.. high; vowels = ARRAY [index] OF Boolean; natural = 0..MaxInt; VAR v : vowels; nv, nc, ns : natural; i : index; ch : Char; FOR i := low TO high DO v[i] := i IN [ A, E, I, O, U, Y ]; nv := 0; nc := 0; ns := 0; WHILE NOT EoF DO Read(ch); IF (ch >= low) AND (ch <= high) THEN IF v[ch] THEN nv := Succ(nV) nc := Succ(nC) IF ch <> THEN ns := Succ(nS); WriteLn(nV, vokaler,, nc, konsonanter,, ns, specialtecken ). DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 7 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 8 / 25
Representation av textsträngar Representation av textsträngar... (2) PROGRAM txt; CONST strmax = 80; TYPE index = 1..strMax; nchars = 0..strMax; txt = PACKED ARRAY [index] OF Char; string = RECORD contents : txt; length : nchars FUNCTION stringlength(var s: string): nchars; stringlength := s.length PROCEDURE readstring(var s: string); WITH s DO length := 0; WHILE (NOT EoLn) AND (length <= strmax) DO length := Succ(length); Read(contents[length]); PROCEDURE writestring(var s: string); VAR n : nchars; FOR n := 1 TO stringlength(s) DO Write(s.contents[n]); WriteLn DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 9 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 10 / 25 Representation av textsträngar... (3) Representation av textsträngar... (4) Procedur som gör små bokstäver till stora i en sträng: Man kan även arbeta med en variabel av typen PACKED ARRAY [...] OF Char; direkt. Vi kan inte läsa en hel sträng men den går att skriva. Obs! att även tilldelning av en sträng med värdet av en strängkonstant går bra! t := Kalle Anka ; OK om t är av typen PACKED ARRAY [1..10] OF Char; PROCEDURE upcase(var s: string); VAR n: nchars; shift : Integer; shift:= Ord( a ) - Ord( A ); WITH s DO FOR n := 1 TO stringlength(s) DO IF (contents[n] >= a ) AND (contents[n] <= z ) THEN contents[n] := Chr(Ord(contents[n]) - shift) IF contents[n] = å THEN contents[n] := Å IF contents[n] = ä THEN contents[n] := Ä IF contents[n] = ö THEN contents[n] := Ö ; DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 11 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 12 / 25
Flerdimensionella fält i Kontinuerlig lista för att hantera ett register CONST maxindex = 10; TYPE index = 1..maxIndex; matris = ARRAY [index] OF ARRAY [index] OF Integer; PROCEDURE enhetsmatris(var a:matris); VAR row, col : index; FOR row := 1 TO maxindex DO FOR col := 1 TO maxindex DO IF row = col THEN a[row, col] := 1 a[row, col] := 0; TYPE Namn = PACKED ARRAY [1..maxTal] OF Char; sex = (man, kvinna); inskrivnaar = 1970..2000; npoang = 0..300; studentuppgifter = RECORD fnamn : Namn; enamn : Namn; kon : sex; studieresultat = RECORD student : studentuppgifter; inskriven : inskrivnaar; poang : npoang; studielinje = ARRAY[1..90] OF studieresultat; VAR matematiskdatalogisklinje: studielinje; DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 13 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 14 / 25 Kontinuerlig lista för att hantera ett register (2) Kontinuerlig lista för att hantera ett register (3) matematiskdatalogisklinje[3].student.fnamn := Kalle ; Post av typen studieresultat Post av typen studentuppgifter Fält i en post av typen studentuppgifter PROCEDURE readstudent(var s:studentuppgifter); VAR ch: Char; WriteLn( Förnamn ); ReadString(s.fnamn); WriteLn( Efternamn ); ReadString(s.enamn); WriteLn( Ange k för kvinna och m för man ); Readln(ch); IF (ch = K ) OR (ch = k ) THEN s.kon := kvinna IF (ch = M ) OR (ch = m ) THEN s.kon := man DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 15 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 16 / 25
Stackar och köer med kontinuerliga listor (stack 1) Stackar och köer med kontinuerliga listor (stack 2) Stack och elementen i stacken representeras av följande: TYPE item = RECORD <user defined> stack = RECORD top: 0..maxNoOfElements; entry: ARRAY [1..maxNoOfElements] OF item FUNCTION empty(s : stack): Boolean; empty := s.top = 0 FUNCTION full(s : stack): Boolean; full := s.top = maxnoofelements PROCEDURE push(var S:stack; e: item); WITH S DO IF top >= maxnoofelements THEN owerflow top := Succ(top); entry[top] := e PROCEDURE pop(var S: stack;var e: item); WITH S DO IF top < 1 THEN underflow e := entry[top]; top := Pred(top) DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 17 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 18 / 25 Stackar och köer med kontinuerliga listor (kö 1) Stackar och köer med kontinuerliga listor (kö 2) För kö ser posten ut så här: Kön kan betraktas som cirkulär så att efter sista elementet kommer första. index = 1..maxNoOfElements; queue = RECORD front, rear: index; entry: ARRAY [index] OF item; Och procedurerna som arbetar mot kön: PROCEDURE initqueue (VAR q: queue); WITH q DO front := maxnoofelements; rear := 1 FUNCTION inc (i: index): index; IF i = maxnoofelements THEN inc := 1 inc := succ(i) Om kön är tom så är inc(front) = rear och om den är full så är front = rear FUNCTION empty (VAR q: queue): boolean; empty := inc(q.front) = q.rear DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 19 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 20 / 25
Stackar och köer med kontinuerliga listor (kö 3) Lista på en kontinuerlig lista (1) FUNCTION full (VAR q: queue): boolean; full := q.front = q.rear PROCEDURE enqueue (VAR q: queue;i : item); IF full(q) THEN writeln( queue is full! ) WITH q DO entry[rear] := i; rear := inc(rear) PROCEDURE dequeue (VAR q : queue;var i : item); IF empty(q) THEN writeln( q is empty! ) WITH q DO front := inc(front); i := entry[front] En lista baserad på en kontinuerlig lista kan implementeras på följande sätt: CONST maxnoofelements = 10; TYPE item = RECORD tal: Integer lista = RECORD lastelement: 0..maxNoOfElements; cursor: 0..maxNoOfElements; entry: ARRAY [1..maxNoOfElements] OF item PROCEDURE create(var L: lista); cursor := 0; lastelement := 0 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 21 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 22 / 25 Lista på en kontinuerlig lista (2) Lista på en kontinuerlig lista (3) FUNCTION empty(l: lista): Boolean; empty := L.lastElement = 0 FUNCTION full(l: lista): Boolean; full := L.lastElement = maxnoofelements PROCEDURE insert(var L: lista; e: Item); IF NOT full(l) THEN lastelement := lastelement + 1; entry[lastelement] := e PROCEDURE delete(var L: lista); IF (NOT empty(l)) AND (cursor > 0) THEN entry[cursor] := entry[lastelement]; lastelement := lastelement - 1; IF cursor > lastelement THEN cursor := lastelement PROCEDURE next(var L: lista); IF cursor > 0 THEN IF cursor = lastelement THEN cursor := 0 cursor := cursor + 1 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 23 / 25 DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 24 / 25
Lista på en kontinuerlig lista (4) PROCEDURE previous(var L: lista); IF cursor > 0 THEN cursor := cursor - 1 PROCEDURE locatefirst(var L:lista); IF lastelement > 0 THEN cursor := 1 PROCEDURE retrieve(var L: lista; VAR e: item); IF cursor > 0 THEN e := entry[cursor] DA2001 (Föreläsning 18) Datalogi 1 Hösten 2010 25 / 25