Datalogi, grundkurs 1 Lösningsförslag till tentamen 6 maj 2000
1. För att proceduren sortera ska fungera som tänkt kan den se ut på följande sätt: const min = 1; max = 3; type tal = integer; index = min..max; vector = array [index] of tal; var v:vector; procedure sortera (var v : vector); var tmp:tal; begin while not ((v[1]<=v[2]) and (v[2]<=v[3])) do begin if v[1] > v[2] then begin tmp:=v[1]; v[1]:=v[2]; v[2]:=tmp; if v[2] > v[3] then begin tmp:=v[2]; v[2]:=v[3]; v[3]:=tmp; { sortera } a. (2p) De fel som finns i den ursprungliga koden är: i. I procedurhuvudet: v måste referensanropas om sorteringen ska ge resultat utanför proceduren. ii. I procedurhuvudet: v kan inte typdeklareras som föreslaget p.g.a. att när vi anropar sortera med ett argument, v1 kan v1 INTE vara av samma typ som den formella parametern, v i procedurhuvudet. iii. I båda IF-satserna finns samma typ avproblem: Det måste finnas en temporär variabel som tillfälligtvis lagrar ett värde. iv. Slutligen kan inte en procedur tilldelas ett värde, det är endast funktioner som kan tilldelas ett värde. Att ändra proceduren sortera till en funktion är inte att rekommendera eftersom en tilldelning till funktionen måste göras. Typen vector är en sammansatt typ och kan inte returneras ty det går inte att returnera annat än atomiska värden till en funktion. Den bästa och enklaste lösningen på detta problem är helt enkelt att ta bort raden sortera := v; och låta referensanropa vektorn som ska sorteras, se under punkt i. 1
b. (2p) De sätt vi lärt oss är glassbox, blackbox och tickingbox. i. Glassbox. Man vet hur koden ser ut och väljer testdata så att alla möjliga vägar genomlöps. Provkör därefter programmet med vald testdata för att se att det förväntade resultatet erhålls.. ii. Blackbox. Man ska välja testdata utifrån vetskapen om vad programmet ska göra inte hur koden ser ut. Testdata är en vektor med t.ex. 1) de olika permutationerna av 1, 2 och 3. 2) några eller alla tal lika t.ex. 1, 1 och 2. 3) extrema värden t.ex. MaxInt samt 4) felaktiga värden t.ex. a, hej och 3.14. iii. Tickingbox. Inget test utförs, först när det blir fel åtgärdas det (förhoppningsvis). 2. a. (1p) Operativsystemets uppgifter: organisera det interna arbetet, assistera program, effektivisera användningen av datorns resurser. b. (1p) Med virtuellt minne håller man endast en del av varje program i primärminnet och resten ligger på sekundärminnet och hämtas in vid behov, varvid den nyss aktuella delen av programmet kan flyttas till sekundärminnet om det inte längre får plats i primärminnet. c. (2p) Både stack och kö är en speciell typ avliststruktur. En lista där operationer endast sker i en ände avlistan kallas stack, dvs elementen sätts in och tas bort från samma ände. Detta kallas också LIFO, Last In First Out. Listor där man opererar på elementen i den ordning som de sätts in kallas för köer, dvs elementen sätts in i ena änden och tas bort från den andra änden i listan. Detta kallas också FIFO, First In First Out. d. (3p) En kontinuerlig lista är en liststruktur där posterna i listan ligger i en följd i minnet. (En kontinuerlig lista är indexerbar och motsvaras av ARRAY i Pascal. När en kontinuerlig lista skapas reserveras plats till hela listan i minnet.) En diskontinuerlig lista är en liststruktur där posterna i listan läggs där minnesutrymme finns och läggs in först när ett NEW-kommando ges. (I Pascal byggs en sådan struktur upp med hjälp avpekare och poster.) En diskontinuerlig listas fördelar framför en kontinuerlig listas är: listan har en flexibel längd, lätt att sätta in och ta bort element inuti en lista samt strukturera om i en lista. 2
3. a. (3p) Konstruktor sätter samman komponenter till ett objekt. Selektor väljer ut en komponent från ett objekt. Predikat utför något slags test, resultatet är ett sanningsvärde. Följande kan vara bra att ha: Konstruktorer: (define (makeaktie namn datum start) (list namn datum start)) (define (makeport) (list)) Selektorer: (define (picknamn aktiepost) (car aktiepost)) (define (pickdatum aktiepost) (cadr aktiepost)) (define (pickstart aktiepost) (caddr aktiepost)) (define (firstaktie port) (car port)) (define (restaktier port) (cdr port)) Predikat: (define (empty? port) (null? port)) b. (2p) (define (insert aktiepost port) (cons aktiepost port)) c. (4p) (define (searchaktienamn port) (cond ((empty? port) port) ((eq? aktienamn (picknamn (firstaktie port))) (insert (firstaktie port) (searchaktienamn (restaktier port)))) (else (searchaktienamn (restaktier port))))) 3
4. a. (2p) Typdeklarationen för min kö är: CONST min = 1; max = 50; TYPE string = PACKED ARRAY [min..max] OF Char; personptr = ^person; person = RECORD namn : string; persnummer : integer; size : integer; next : personptr; queueptr = ^queue; queue = RECORD first,last : personptr; Jag väljer en diskontinuerlig lista eftersom jag inte vet hur många element som kommer att finnas i kön. Kön har ett huvud vilket underlättar behandlingen av kön. b. (3+3p) PROCEDURE enqueue (p:personptr; q : queueptr); BEGIN IF full(q) THEN WriteLn( Kön är full, kan ej lägga till ett element ) ELSE IF empty(q) THEN BEGIN q^.first:=p; q^.last:=p; END ELSE BEGIN q^.last^.next:=p; q^.last:=p; { enqueue } FUNCTION dequeue (q : queueptr):personptr; VAR tmp: personptr; BEGIN dequeue:=nil; IF NOT empty(q) THEN BEGIN tmp:=q^.first; q^.first:=q^.first^.next; tmp^.next:=nil; dequeue:=tmp; { dequeue } c. (2p) De funktioner som behövs till ovanstående är full och empty. FUNCTION empty (q :queueptr) : Boolean; Previllkor: Kön q har skapats Postvillkor: Om kön, q är tom returneras true annars false. FUNCTION full (q : queueptr): Boolean; Previllkor: Kön q har skapats Postvillkor: Om kön, q är full returneras true annars false. 4
5. (6p) program removedate(personal); Var personal, tmp : TEXT; begin reset(personal); rewrite(tmp); while not eof(personal) do if eoln(personal) then begin writeln(tmp); get(personal); end else if personal^ in [ 0.. 9 ] then get(personal) else begin write(tmp,personal^); get(personal); reset(tmp); rewrite(personal); while not eof(tmp) do if eoln(tmp) then begin writeln(personal); get(tmp); end else begin write(personal,tmp^); get(tmp); end. 6. a. (2p) Den angivna proceduren är inte svansrekursiv eftersom cons börjar operera på sina argument först efter det att de rekursiva anropen är klara. b. (4p) (define (derivera poly) (define (inner poly potens res) (if (null? poly) res (inner (cdr poly) (+ potens 1) (append res (list (* potens (car poly))))))) (if (null? poly) () (inner (cdr poly) 1 ()))) 5