Tenta i TDP007 onsdag 18 augusti 2010 kl 14-18 ---------------------------------------------- Uppgift 1: Grundläggande Ruby (6p) ---------------------------------- a) Vad är skillnaden på @var och @@var? (1p) b) Ge exempel på minst tre olika sätt att utöka en array i Ruby! (1p) c) I följande körexempel ser vi hur en hash-tabell används: >> h => {"apa"=>14, "banan"=>27} >> h["apelsin"] => "Finns i sjön!" Förklara hur det kan komma sig att nyckeln "apelsin" ger värdet "Finns i sjön!", utan att detta par finns i hash-tabellen. Visa vilken kod som bör ha körts innan dessa rader. (2p) d) I filen myclass.rb finns defintionen av en klass. Experimentera med klassen och försök förstå vad den gör. Förklara vad man skulle kunna ha klassen till och föreslå bättre namn på själva klassen och det attribut a som klassen innehåller. (2p) Uppgift 2: Reguljära uttryck (3p) --------------------------------- a) (2p) Ett svensk registreringsnummer består av tre bokstäver följt av tre siffror. De tre bokstäverna kommer från intervallet A-Z men kan inte vara I, Q eller V eftersom dessa är lätta att förväxla med andra bokstäver på håll. Din uppgift är att konstruera ett reguljärt uttryck som kan användas för att matcha svenska registreringsnummer. Du ska också baka in detta i en funktion som tar en sträng och returnerar true eller false om strängen är ett korrekt registreringsnummer eller inte. Strängen ska kunna innehålla inledande och avslutande blanktecken som ska tas ignoreras. Exempel: >> regnr "XGT794" => true >> regnr "XQT794" => false >> regnr " XGT794 " => true >> regnr "xgt794" => false b) (1p) Konstruera ett reguljärt uttryck som kan matcha olika stavningar av följande efternamn: Pettersson, Petterson, Petersson, Peterson, Petterzon, Peterzon. Uppgift 3: Enhetstestning samt bearbetning av textfiler (7p) ------------------------------------------------------------ a) (4p) I filen temp.txt finns en tabell med genomsnittliga dygnsmedel- temperaturerna under årets tolv månader för några olika flygplatser. Din uppgift är att skriva ett program som läser in tabellen till ett lämpligt format och därefter beräknar för varje månad vilken flygplats som har den varmaste medeltemperaturen (så att man vet vart man borde åka på semester varje månad hela året). Programmet ska funka ungefär så här: >> my_program("temp.txt") 1: SYD (22.1) 2: SYD (22.0) 3: SYD (20.9) 4: SYD (18.3) 5: FCO (17.8) 6: FCO (21.7) 7: FCO (24.4) 8: FCO (24.1) 9: LAX (21.0) 10: LAX (19.3) 11: SYD (19.4) 12: SYD (21.2) Det exakta utdataformatet är inte så intressant, så länge korrekt information finns med. Programmet ska utformas så generellt att det inte är beroende av att det är exakt fem flygplatser, eller just dessa. b) (3p) Utforma ett antal lämpliga enhetstester för inläsningsdelen av ditt program för uppgift a). Kolla t.ex. att du fått med alla flygplatserna och att temperaturerna för några olika månader är okej. Uppgift 4: XML-parsning (5p) ---------------------------- Sture driver en liten kiosk som heter "Stures kiosk" kort och gott. Stures revisor har flera gånger påpekat att Sture borde göra en uppskattning av hur mycket allt godis i kiosken är värt, åtminstone en gång i veckan. Det skulle vara bra, både för Stures bokföring och för Stures försäkringsbolag. Eftersom det inte riktigt håller att räkna alla grejer vill Sture hitta på ett annat sätt. Han har ett datoriserat kassasystem som kan mata ut en XML-fil med information om hur mycket kassasystemet tror att det finns i kiosken. Det kan duga som underlag. Dock behöver varorna i XML-filen summeras så att man vet vad allt är värt tillsammans. Det är här som du kommer in i bilden. Din uppgift är att skriva ett Ruby-program som kan läsa igenom XML-filen med uppgift om godiset i Stures kiosk och tala om vad allt är värt. Sture är lite petig, så han vill gärna ha en SAX-lösning. Det finns som tur är ett exempel på en sådan parser i filen sax_example.rb, så du har något att utgå från. Tanken är att när allt är klart så ska Sture kunna skriva så här vid Ruby-prompten: >> value("lager.xml") => 2665.0 Svaret innebär alltså att det totala värdet av allt godis som finns i kiosken är 2665 kr. Uppgift 5: Domänspecifika språk (5p) ------------------------------------ Stina och hennes företag Bookshop Solutions Ltd utvecklar programvara som tar hand om all information som en bokhandel behöver hantera: lager, fakturor, beställningar, kassakvitton, etc. Deras programvara är utvecklad i Ruby och för varje installation finns en konfigurationsfil som talar om grundläggande information om det aktuella företaget i form av ett antal strängar. Följande exempel finns även i filen config.rb: store_name "Berras bokhandel" company_name "Bertilssons Bokhandel AB" first_name "Bertil" last_name "Bertilsson" name first_name+" "+last_name receipt_header store_name receipt_footer "Välkommen åter önskar #{first_name}!" invoice_header "Faktura från #{company_name}" Stina vill att du ska betrakta konfigurationsfilen som ett litet domänspecifikt språk och skriva en mycket enkel parser för att läsa in denna information till ett Ruby-objekt, enligt de tekniker vi har gått igenom i kursen. Hon vill alltså att man ska kunna skriva t.ex. så här: >> c=Configuration.load("config.rb") => ... >> c.receipt_footer => "Välkommen åter önskar Bertil!" Implementera klassen Configuration. Uppgift 6: Parsning (6p) ------------------------ Cascading Style Sheets (CSS) är en teknik för att specificera hur en webbsida ska se ut. Tanken är att dokumentets struktur och innehåll ska ligga i en HTML-fil och att utseendet bestäms av en CSS-fil. På så sätt kan man separera innehåll och utseende, vilket ger många fördelar. Lite förenklat kan man säga att en CSS-fil specificerar för varje HTML-tagg hur den ska presenteras på skärmen. Följande korta exempel finns i filen example.css: h1 { font-weight: bold; font-size: 12px } p { font-size: 12px } /* px */ em { color: red } Detta säger att all text som taggas med

...

ska presenteras som fetstil i 12 punkters storlek, etc. CSS-filer kan se lite mer komplicerade ut, men för den här uppgiften utgår vi från att den består av en uppsättning regler som börjar med namnet på en tagg och fortsätter med en egenskapslista, inramad av { ... }. Egenskapslistan består av ett antal egenskaper där namnet skiljs från värdet med ett kolon. Om listan består av flera egenskaper ska det vara ett semikolon mellan egenskaperna, dock inte sist. Förutom detta kan det finnas kommentarer som inramas av /* ... */. Din uppgift är att utgå från den parser som finns i rdparse.rb och bygga en enkel parser som kan läsa in och tolka CSS-filer. Resultatet av parsningen ska vara någon form av datastruktur som innehåller de stilmallar som finns i filen, t.ex. i form av en hashtabell. Du behöver inte hantera mer komplicerade CSS-filer än filen example.css. Följande körexempel visar hur det skulle kunna se ut: irb(main):180:0> cp=CSSParser.new # irb(main):181:0> cp.load "example.css" (-klipp-) {"p"=>{"font-size"=>"12px"}, "em"=>{"color"=>"red"}, "h1"=>{"font-weight"=>"bold", "font-size"=>"12px"}}