LINKÖPINGS TEKNISKA HÖGSKOLA Institutionen för datavetenskap Avdelningen för programvara och system Tommy Olsson 2015-05-27 Datortentamen i TDDI14 Objektorienterad programmering Provkod DAT1 Datum 2015-06-01 Klockan 14 19 Jour Tommy Olsson, 28 1954. Jourhavande besöker salarna varje hel timma under skrivtiden. För övrigt ska jourhavande tillkallas endas vid datorsystemproblem. Administratör Anna Grabska Eklund, 28 2362 Hjälpmedel En bok om C++. Det får finnas egna anteckningar i marginalen men ej på helt tomma sidor, ej på lösa eller fastsatta extra blad eller lappar. En svensk-* ordbok får medtagas. Inga andra hjälpmedel, på papper eller elektroniska, förutom kladdpapper och penna, är tillåtna. Betygssättning Totalt kan 18 poäng erhållas (8+6+4). För betyg 3 krävs 8 poäng, för betyg 4 krävs 11 poäng och för betyg 5 krävs 14 poäng. Anvisningar Se anvisningar på separat papper för inloggning till datortentamenssystemet och arbetet i tentakontot. Läs igenom hela uppgiften innan du börjar lösa en uppgift. Skriv ditt namn och personnummer i en kommentar överst i varje fil. Använd exakt de filnamn och andra namn som anges, även med avseende på stora och små bokstäver. Lösningar ska skicka in via Studentklienten, se separat anvisning. Lycka till!
TDDI14 Objektorienterad programmering 2 (5) 1. Kopiera filen uppgift1.cc från filkatalogen given_files. Filen innehåller anvisningar för hur objekt ska hanteras och testas av programmet. Konstruera en polymorf klasshierarki för att representera GPS-navigatorer. Alla klasser ska ha GPS som gemensam abstrakt basklass. GPS ska ha två direkta subklasser, Road och Outdoor. Outdoor ska i sin tur ha en direkt subklass Tracking. Navigatorer av typ Road används i fordon, Outdoor av personer som rör sig till fots och Tracking för att exempelvis spåra en hund. Alla GPS-klasser ska lagra model, t.ex. nüvi 3790T, och skärmstorlek, t.ex. 3.7x2.2, båda typ std::string. Då ett GPS-objekt skapas ska model och skärmstorlek alltid anges och sedan ej ändras. GPS ska ha funktionerna get_model() och get_screen_size() som returnerar respektive värde. Ett Road-objekt ska även lagra om modellen kan ta emot FM-trafikmeddelanden. Informationen, ja eller nej, lagras som bool och initieras då ett Road-objekt skapas, för att sedan ej ändras. Om inget initialvärde anges ska default vara nej (false). Road ska ha funktionen fm_messages(), som returnerar om modellen kan ta emot meddelanden (true) eller ej (false). Ett Outdoor-objekt ska även lagra om modellen är utrustad med en höjdmätare. Informationen, ja eller nej, lagras som bool och initieras då ett Outdoor-objekt skapas för att sedan ej ändras. Om inget initialvärde anges ska default vara nej (false). Outdoor ska funktionen altimeter() som returnerar om modelen är utrustad med höjdmätare (true) eller ej (false). Tracking har inga egenskaper utöver vad Outdoor har men vi vill hantera sådana objekt separat typmässigt, därav klassen Tracking. Alla navigatorklasser ska ha en medlemsfunktion type() som returnerar en sträng som anger vilken typ av navigator objektet ifråga representerar, Väg för Road-objekt, Utomhus för Outdoor-objekt och Spårning för Tracking-objekt. Objekt förutsätts alltid skapas dynamiskt (new) och hanteras via pekare. Tilldelning ska inte vara tillåtet. Det enda sättet att publikt kopiera objekt ska vara med en polymorf kopieringsfunktion clone(), vilken ska använda kopieringskonstruktorn för att skapa kopian. För speciella medlemsfunktioner gäller, för varje klass, att sådana som ska finnas och kan genereras av kompilatorn ska defaultas, sådana som inte ska finnas men kan genereras av kompilator ska deletas, sådana som inte ska finnas och inte genereras av kompilatorn ska inte deklareras. Inga andra funktioner utöver de som anges ovan får införas. Exempel på utskrift från programmet (se den givna koden för mer information): Modell...: nüvi 3790T Typ...: Väg Skärmstorlek..: 3.7x2.2 FM-meddelanden: Ja Höjdmätare...: Nej Modell...: etrex Summit HC Typ...: Utomhus Skärmstorlek..: 1.3x1.7 FM-meddelanden: Nej Höjdmätare...: Ja Modell...: Astro Typ...: Spårning Skärmstorlek..: 1.5x2.2 FM-meddelanden: Nej Höjdmätare...: Nej Följ specifikationen noga följ anvisningarna i den givna filen noga utnyttja C++ väl!
TDDI14 Objektorienterad programmering 3 (5) 2. Kopiera filen uppgift2.cc till din arbetskatalog. Filen innehåller ett testprogram. Standardcontainern vector är en sekvenscontainer. Du kan stega igenom elementen i en vector, från det första till det sista, med hjälp av antingen indexering, operator[], eller med en vectoriterator, eller med intervallstyrd for-sats. För att kunna stega igenom elementen i en vector cykliskt från det sista elementet ska du alltså stega till det första ska du konstruera en komponent med namn Cycler Konstruera en klassmall Cycler, som ska kunna användas på följande sätt: vector<int> v; // v fylls på med värden Cycler<int> cycler{ v }; // vector v som vi vill stega runt i // ett Cycler-objekt cycler binds till vectorn v for (int i = 0; i < 2 * cycler.size(); ++i) // vi tar två varv i vectorn v cout << cycler.next() << \n ; Cycler ska ha en malltypparameter som ange den typ av element som vectorn ifråga ska innehålla, int i exemplet ovan. Då ett Cycler-objekt skapas ska det bindas till ett vector-objekt, som v i exemplet ovan. Cycler<int> cycler{ v }; Det ska inte skapas en kopia av v i cycler. Då exempelvis medlemsfunktionen next(), se nedan, används ska det innebära att operationen utförs på ett element i v. Det finns två alternativ för att åstadkomma detta med pekare eller med referens. Om vectorn är tom ska konstruktorn för Cycler kasta ett undantag cycler_error, som du ska härleda från någon lämplig standardundantagsklass. Cycler ska ha en medlemsfunktion size() som returnerar storleken på vectorn. cycler.size() // returnerar storleken för v Cycler-objektet ska hålla reda på det aktuella elementet i vectorn. Initalt ska det aktuella elementet vara det första elementet i vectorn. Cycler ska ha en medlemsfunktion reset() som återställer det aktuella elementet till det första elementet i vectorn. cycler.reset() // aktuellt element kommer att vara det första i v Cycler ska ha en medlemsfunktion next() som ska ge åtkomst till det aktuella elementet i vectorn, så att elementets värde kan användas eller ändras. next() ska även flytta fram den aktuella positionen ett steg. Följande uttryck ska ge det aktuell elementet i vectorn cycler.next() och nästa gång next() anropas ska nästa element i vectorn erhållas (cykliskt). Följande uttryck ska stega upp värdet på det aktuella elementet i vectorn (postfix ++ fungerar ju eftersom v innehåller int-värden) cycler.next()++ Det som next() returnerar ska alltså ge åtkomst till det aktuella elementet på ett sätt som gör det möjligt att ändra på elementets värde om man så önskar. Det ska inte vara tillåtet att kopiera eller tilldela Cycler-objekt. Fortsättning nästa sida!
TDDI14 Objektorienterad programmering 4 (5) Det givna testprogrammet ska ge följande utskrift då Cycler och cycler_error konstruerats: 1 2 2 3 4 5 6 3 4 5 6 7 4 5 6 7 8 5 6 7 8 9 Cyclerfel: tom vector Meddelandet "tom vector" som what() skriver ut har alltså skickats med då cycler_error kastades. Tips: Om du använder en iterator, vector<t>::iterator, för att implementera Cycler får du problem med något som kallas beroende namn ( dependent name ), eftersomdet inte är självklart att iterator i vector<t>::iterator anger en typ. Du måste därför tala om det för kompilatorn genom att specificera med typename, dvs använda typename vector<t>::iterator då du vill deklarera en iterator.
TDDI14 Objektorienterad programmering 5 (5) 3. Kopiera filen uppgift3.cc från mappen given_files. Filen innehåller ett testprogram i main() och följande definition för att lagra en artikel i ett artikelregister (ingår inte i uppgiften): struct Item { string name; double price{}; }; // artikelnamn // artikelpris I ett program som ska hantera sådana poster ska indata kunna läsas från en inström med operator>> och utdata ska kunna skrivas på en utström med operator<<. Exempel på användning: Item x; while (cin >> x) { cout << x << \n ; } // läser in på formen artikel; pris // skriver ut på formen artikel; pris och ny rad Indata för en artikel ska ges på en rad, med artikelnamnet först, sedan ett semikolon och sist priset. Artikelnamn kan bestå av flera delar (några fler finns i den givna filen items.txt). Exempel: Hålfotsinlägg, stl. 45; 107.50 Bollplank; 254.00 Kanelbullar, 10 st; 25.90 Överlagra operator<< och operator>> för att kunna skriva ut respektive läsa in en artikel. operator<< ska inte generera ny rad efter att artikelns pris har skrivits ut. Önskas ny rad ska det program som skriver ut göra detta, som i exemplet ovan. Om det uppstår något fel när operator>> ska läsa det kan inträffa om ett otillåtet värde för priset dyker upp ska variabeln som inläsningen görs till (x) behålla sitt gamla värde. Endast om både artikelnamn och pris kan läsas utan problem ska variabeln erhålla de inlästa värdena. Vid fel får testprogrammet avslutas.