Tentamen: Datordel Programmeringsteknik Datum: 2012-02-28 Tid: 12:00-16:00 Sal: Ansvarig: Resultat: Hjälpmedel: Betygsgränser: Ulf Johansson Anslås inom 3 veckor. Inga Sammanlagt 30 p för G, 45 p för VG. Iakttag följande: Arbeta i ett enda projekt och arbeta i de källkodsfiler som finns på tentamenskontot. Observera att den c-kod som lämnas in skall vara körbar, dvs. ni måste kompilera om efter er sista ändring i koden och kontrollera att den slutgiltiga koden inte ger kompileringsfel. Kod som inte fungerar måste därför vara bortkommenterad. Endast det som ligger i respektive projektmapp kommer att bedömas. Lösningarna rättas i befintligt skick. Såväl funktionalitet som struktur bedöms, vilket innebär att: även en lösning som inte är fullständig kan ge poäng poängavdrag kan ges för onödigt komplicerade eller ostrukturerade lösningar. Koden behöver endast kommenteras när det står så i uppgiften. Kommandon från bibliotek (även Roberts) får användas fritt.
1) I denna uppgift utgår vi från ett program i Roberts bok som inplementerar tärningsspelet Craps. Källkodsfilen till programmet ligger på ert tentamenskonto (under namnet uppg1.c). Ni skall i detta program lägga till funktioner för ett nytt tärningsspel. Förutom att funktionerna skall vara korrekta avseende såväl prototyp som logik, läggs särskild vikt på hur er kod integreras i den befintliga koden. Börja alltså med att studera det givna programmet, så att ni förstår dess struktur. Vi börjar med att beskriva det enkla tärningsspelet, kallat Sequence, som skall läggas till. Detta spel spelas också med två tärningar som rullas flera gånger. Man får fortsätta att slå så länge man slår en högre summa än förra gången. Den som har längsta sekvensen vinner, exempelvis om spelare 1 slår 2 5 7 6 och spelare 2 slår 4 6 8 10, så vinner spelare 2. a) Börja med att skapa prototyper och tomma funktioner för följande: giveinstructionssequence playsequencegame Prototyperna skall vara de naturliga, dvs. samma som motsvarande funktioner för Craps. Implementera också funktionen giveinstructionssequence med de instruktioner som finns i körningsexemplet. b) Skapa nu, i main, möjlighet att välja vilket spel man vill spela. Här skall felkontroll ske på inmatat svar. Observera att möjligheten att välja spel kommer efter instruktionerna och att man efter avslutad omgång kan välja spel igen, vilket illustreras i körningsexemplet. c) Implementera nu spelet Sequence, som det är beskrivet ovan. För att göra det lite mer spännande för den mänskliga spelaren, så spelas det mot datorn och man slår varannan gång. En detalj är att man bör ändra outputtexten i RollTwoDice genom att ta bort you, så att det står exempelvis: Rolled 1 and 5 -- that s 6 Om den mänskliga spelaren inte får fortsätta, så skall datorn slå en gång till för att se om den vinner eller om den blir oavgjort. Datorn skall hålla reda på om spelet skall fortsätta, vem som vunnit (eller om det blivit oavgjort) och hur lång vinnarsekvensen var. Tips: Tänk noga igenom kontrollstrukturen för spelet och använd en så enkel struktur som möjligt, dvs. undvik trassliga nästlingar av if-satser och använd så enkla villkor som möjligt för att hålla ordning på spelet. För att åstadkomma Press <Enter> to roll your dice, så använd ett tomt anrop på GetLine(), dvs. utan att tilldela resultatet till en variabel. Körningsexempel: Would you like instructions? yes Welcome to the craps table! To play craps, you start by rolling a pair of dice and looking at the total. If the total is 2, 3, or 12, that's called 'crapping out' and you lose. If you roll a 7 or an 11, that's called a 'natural' and you win. If you roll any other number, that number becomes your 'point' and you keep on rolling until you roll your point again (in which case you win) or a 7 (in which case you lose). Welcome to the sequence game! In this game, you compete against the computer, taking turns to roll your dice. To play, you start by rolling a pair of dice and remembering the total. Then it's the computer's turn, and it does the same. Next, roll your dice again. If you make a higher sum than last time, you can continue. The same applies to the computer player. The player with the longest sequence wins. If both players fail in the same round, it's a draw.
Would you like to play Craps (c) or Sequence (s) c Here we go! Rolled 1 and 4 -- that's 5. Your point is 5. Rolled 3 and 1 -- that's 4. Rolled 4 and 3 -- that's 7. That's a seven. You lose. Would you like to play again? yes Would you like to play Craps (c) or Sequence (s) s Here we go! Rolled 1 and 2 -- that's 3. Rolled 6 and 1 -- that's 7. Rolled 6 and 3 -- that's 9. Rolled 1 and 5 -- that's 6. Computer fails. You win. The game sequence was 2 turns. Would you like to play again? yes Would you like to play Craps (c) or Sequence (s) s Here we go! Rolled 2 and 6 -- that's 8. Rolled 3 and 3 -- that's 6. Rolled 5 and 6 -- that's 11. Rolled 5 and 1 -- that's 6. Rolled 5 and 5 -- that's 10. You fail. Rolled 3 and 5 -- that's 8. You lose. The game sequence was 3 turns. Would you like to play again? no Press any key to continue (15 p)
2) I den här uppgiften skall vi arbeta med vektorer och en berömd algoritm som heter Eratosthenes såll. Algoritmens syfte är att snabbt och effektivt generera alla primtal under ett visst värde. Utgå från källkodsfilen uppg2.c. Som du säkert ser finns det där redan två static-deklarerade variabler arr som är en pekare-till-int och size som är en int. Vi tänker oss här att den här filen egentligen är en del av en modul, varför vi kan använda oss av globala variabler. Men för enkelhets skull så skriver vi ändå nu på tentan all kod (inklusive main) i denna filen, och vi behöver därmed förstås inte ha någon h-fil eller dela upp programmet över flera filer på något annat sätt. a) I första steget skall ni skapa funktionen initarray vilken dynamiskt allokerar en heltalsvektor av rätt storlek. Som synes bestäms storleken av användaren. Notera här att funktionen inte tar något argument eller returnerar någonting utan arbetar direkt med de static-deklarerade variablerna. b) Nästa uppgift är den mest omfattande och innebär att implementera själva sållet. Detta görs i funktionen createsieve. Innan själva algoritmen startar så bör ni i den funktionen fylla alla fack i vektorn med ettor. En etta kommer sedan att betyda att det tal som motsvaras av vektorns index är ett primtal. Det algoritmen nu gör är att markera alla tal (index) som inte är primtal med nollor. Här är själva algoritmen given i pseudokod: Let A be an array of Boolean values, indexed by integers 2 to n, initially all set to 1. for i = 2, 3, 4,..., size/2: if arr[i] == 1: for j = 2i, 3i, 4i,..., size: arr[j] = 0 Now all i such that arr[i] == 1 are prime. En verbal beskrivning av hur algoritmen fungerar är: 1. Gör en lista över alla tal från två till något valbart största tal n. 2. Stryk ut från listan alla jämna tal som är större än två (4, 6, 8 osv.). 3. Listans nästa tal som inte är utstruket är ett primtal. 4. Stryk ut alla tal, som är både större än det primtalet du hittade i föregående steget och multiplar av det. 5. Upprepa stegen 3 och 4 tills du har nått ett nummer som är större än n/2 (det största talet i listan). 6. Alla kvarstående tal i listan är primtal. c) Nu skall ni skriva en funktion printallprimes(int low, int high) som skriver ut alla primtal mellan de båda argumenten (se körningsexempel där low=2 och high=100 nedan). d) I sista steget skall ni skriva en Boolesk funktion isprime(int number) som returnerar sant om argumentet är ett primtal. Körningsexempel: Input largest number> 1000 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 Press any key to continue (15 p)
3) I denna uppgift skall vi tillverka ett enkelt registerprogram för att hålla reda på visningar av fastigheter till försäljning. Eftersom programmet innehåller datum, så skall några existerande datumfunktioner från calender.c utnyttjas. Dessa ligger i en fil på tentamenskontot, som heter uppg3.c och det är också denna fil som ni skall skriva er kod i. Ett hus beskrivs inledningsvis med en post (struct) som innehåller houseid, street, city, type, nrooms, area. En typdefinition för denna struct finns i också i filen uppg3.c Börja med att titta igenom koden ordentligt. Observera att den inte går att köra, eftersom main saknas. I de första uppgifterna skall ni uppdatera typdefinitionen för houset så att den också kan innehålla ett antal visningsdatum. a) Börja med att skapa en typdefinition för en struct datet som innehåller 3 heltalsdelar (year, month, day). b) Skapa en utskriftsfunktion för datum som skriver ut på formatet YYYY-MM-DD, exempelvis 2012-02-28. Observera att det alltså måste läggas till en nolla före månaderna 1-9 för att få en korrekt utskrift. c) Lägg sedan till ett attribut i houset som är en statisk vektor med storlek 6 av elementtypen datet. Storleken skall ges av en konstant MAX_VIEWINGS. Lägg också till ett heltalsattribut i houset som innehåller antal visningar för huset. Det är nu dags att skapa en databastyp för en vektor av fastigheter och ett huvudprogram som initialiserar databasen. d) Ge typdefinitionen för en struct (housedbt) innehållande en dynamisk vektor av fastigheter och två heltal för att hålla reda på vektorns storlek (currsize) och antal utnyttjade celler (currhouses). Structen skall vara av pekartyp. e) Skriv nu ett huvudprogram där ni deklarerar en variabel av den nya databastypen, allokerar minne och initialiserar den. Initial storlek skall vara 20 och ges av en konstant INITIAL_SIZE. Slutligen skall vi skapa lite funktioner för att lägga in och skriva ut data om fastigheter. Ni kan lägga till kod för att testa dessa funktioner i main, men det är inte nödvändigt. f) Skriv en funktion gethousefromuser som låter användaren skriva in alla uppgifter för en fastighet och returnerar en struct innehållande den nya fastigheten. Inmatningen av visningsdatum sker genom att man först får ange antal visningar (mellan 1 och MAX_VIEWINGS med inputkontroll) och sedan mata in rätt antal datum, se körningsexempel. Inputkontroll skall ske avseende att inmatade datum är korrekt. Eventuellt behöver ni skapa några extra funktioner för detta, bemöda er om en god uppdelning här, så att funktionerna kan återanvändas i andra delar av ett större program. g) Skriv en funktion som skriver ut alla uppgifter om en fastighet. Tänk på att välja en så generell prototyp som möjligt! h) Skriv en funktion som skriver ut alla uppgifter om samtliga fastigheter i registret. (15 p)
Följande körningsexempel visar hur uppgifter för två fastigheter matas in och sedan skrivs hela registret ut: Please input house details. House id: AB1 Street: High Street City: Newcastle Type: Flat Number of rooms: 2 Total living area: 52 How many viewings (1-6): 2 Which year? 2012 Which month? 02 Input day: 28 Which year? 2012 Which month? 02 Input day: 30 Please input a day between 1 and 29. Input day: 29 Please input house details. House id: DE Street: Chestnut Street City: Chester Type: House Number of rooms: 4 Total living area: 130 How many viewings (1-6): 1 Which year? 2012 Which month? 03 Input day: 15 Printing all houses... ID: AB1 Street: High Street City: Newcastle Type: Flat Number of rooms: 2 Living area: 52 Viewings: 2012-02-28 2012-02-29 ID: DE Street: Chestnut Street City: Chester Type: House Number of rooms: 4 Living area: 130 Viewings: 2012-03-15