TDP004 - Datortenta (DAT2) 2013-08-27 Regler All kod som skickas in för rättning skall kompilera och vara väl testad. Inga elektroniska hjälpmedel får medtas. Mobiltelefon ska vara avstängd och ligga i jacka eller väska. Inga ytterkläder eller väskor vid skrivplatsen. Student får lämna salen tidigast en timme efter tentamens start. Vid toalettbesök eller rökpaus ska pauslista utanför salen fyllas i. All form av kontakt mellan studenter under tentans gång är strängt förbjuden. Böcker och anteckningssidor kan komma att granskas av tentamensvakt i samband med tentans start samt under tentans gång. Frågor om specifika uppgifter eller om tentamen i stort ska ställas via tentasystemets kommunikationsklient. Systemfrågor kan ställas till assistent i sal genom att räcka upp handen. Endast uppgifter inskickade före tentatidens slut rättas. Ingen uppgift kan kompletteras under tentamens sista kvart. En praktisk uppgift kan kompletteras för högre poäng tills den är poängsatt med Klar. Klar sätts vid bedömningen att ingen nämnvärd förbättring skett sedan tidigare inskickning. En teoretisk uppgift kan inte kompletteras. Undantagsvis kan examinator be om förtydligande av ett svar. Kompilerande kod är ett grundkrav för poängsättning. Kod som inte kompilerar skall beskrivas och kommenteras ut före inskickning. Antal uppgifter 8 Totalt antal poäng 20 Hjälpmedel En C++-bok (t.ex. C++ Primer 5th ed.) En A4-sida med egna anteckningar i
Betygssättning Tentamen är uppdelad i två delar, en teoretisk och en praktisk. Delarna är värda 5 respektive 15 poäng och för godkänt betyg krävs minst 11 poäng totalt. Poäng som krävs för de olika betygen kan ses i tabell 1. Poängsumma Betyg 0 10 U 11 14 3 15 17 4 18 20 5 Tabell 1: Poängfördelning för betygssättning Information Inloggning Logga in på tentamenskontot med följande användaruppgifter: Användarnamn: examx Lösenord: kluring1 Följ menyvalen så långt det går tills du ska mata in ett engångslösenord. Tag fram ditt LiU-kort och visa det för tentamensvakten för att få detta lösenord. När du är inloggad är det viktigt att du startar tentaklienten genom att högerklicka på bakgrunden och välja tentaklient i menyn. Avslutning Tryck på knappen märkt exit i menyn längst nere på skärmen och välj ok. Vänta ett tag och tryck sedan på knappen Avsluta tentamen när det är möjligt. När detta är gjort är det omöjligt att logga in igen. Lämna inte datorn förrän du ser den vanliga inloggningsskärmen.
Teoretisk del Dessa uppgifter kan INTE kompletteras. Skriv ditt svar på en fil med namnet teorin.txt (där N är uppgiftsnumret) och skicka in filen för rättning. En fil och en inskickning för varje uppgift. 1. Nedan kod definierar en klass för en koordinat och initierar pekaren p. Resultatet är visualicerat i asciifiguren till höger. Ange ett C++-uttryck som ändrar y till 5.2 i objektet p [1 p] refererar till. class coordinate +------+ +---------+ p ------> +------+ public : +------+ x 2.54 double x; +------+ double y; +------+ y 8.9 +------+ coordinate * p = new coordinate 2.54, 8.9 +---------+ (*p).y = 5.2 eller p->y = 5.2 2. Vilken datatyp döljs bakom nyckelordet auto för variabeln x i följande kod? [1 p] vector <pair <int, string >> v... // iterering enligt c ++98 for ( auto i = v. begin (); i!= v. end (); ++i) auto x = (*i); // datatyp på x??... // samma iterering enligt c ++11 for ( auto x : v )... pair<int, string> 3. Deklarera medlemsfunktionen abs i koordinatklassen given i uppgift 1 (du behöver inte [1 p] skriva av klassen, det räcker med den rad du lägger till). Funktionen skall gå att anropa även på konstanta koordinatobjekt. Deklarartionen måste alltså förbjuda ändring av medlemsvariabler (i praktiken alltså deklarera this-pekaren konstant). Om du inte vet hur abs för en koordinat beräknas så påminner jag om att du skall deklarera medlemsfunktionen, inte definiera den. double abs() const;
4. Att skapa en bra objektorienterad programvarustruktur är inte enkelt. Givet att du har en [2 p] kravspecifikation och några scenarion för hur programmet används, beskriv kortfattat hur du kommer fram till dina objekt och medlemsfunktioner. D.v.s. hur objektorienterad analys går till. Identifiera objektkandidater, ansvarsområden, t.ex. substantiv från krav och scenarion. Identifiera tjänster eller operationer, t.ex. verb. Organisera och strukturera objekten, gallra. Testa, utför scenarion på designen. Börja om och förbättra identifierade brister.
Praktisk del En uppgift kan kompletteras tills den är poängsatt som Klar. Poängen inom hakparenteser till höger anger vad maxpoängen för hela uppgiften är värd. Poängen inom vanliga parenteser till vänster anger vad motsvarande speciella krav är värt. Du skall alltid lösa så mycket av uppgiften du vill ha poäng för innan du skickar in första gången för att kunna få full poäng. Kompilering mm Använd aliaset g++11 för att kompilera med C++11-standarden. Använd aliaset w++11 för att även få bra varningar. Använd aliaset g++11filter för att även filtrera med gccfilter. Använd aliaset w++11filter för att få varningar och gccfilter. Använd bcheck./a.out för att leta minnesläckor. 5. Bertram är en figur du kan komma stöta på i kommande operativsystemtentor. Denna uppgift rör dock hans bror Rambert. Han skall skapa en komplicerad pekarstruktur och behöver [3 p] ett sätt att hålla reda på när alla pekare skall tas bort. Till detta har han skapat en klass Pointer Counter som finns i given files/pointer counter.cc samt ett litet testprogram i samma fil. Klassen är tänkt att hålla reda på en specifik pekare tillsammans med en räknare som håller reda på hur många gånger pekaren kopierats och tagits bort. Tanken Rambert har är att automatiskt avallokera pekaren när räknaren blir noll. För att detta skall fungera behöver kopieringskonstruktorn, tilldelningsoperatorn och destruktorn implementeras korrekt. Kopieringskonstruktorn måste göra en kopia av pekaren så att samma pekare finns i både originalet och kopian och pekar ut samma minnesplats. Samtidigt måste både originalet och kopian ha tillgång till samma räknarvärde. Räknarvärdet måste även räknas upp för varje kopia som görs. Tilldelningsoperatorn måste dels se till att räknaren för den kopia som skrivs över räknas ned (med allt det innebär), och dels göra samma jobb som kopieringskonstruktorn. Är det självtilldelning skall inget alls göras. Att skapa en kopia och byta (copy and swap) är som vanligt en smart lösning för tilldelningsoperatorn. Destruktorn måste se till att räknaren för den kopia som förstörs räknas ned, och även avallokera minnet för de pekare som inte längre behövs. (3p) Du har en korrekt implementation där testprogrammet fungerar felfritt utan minnesläckor och utan att andra delar än kopieringskonstruktor, tilldelningsoperator och destruktor är modifierade. Kompilera och kör enligt nedan för att se eventuella minnesläckage. w++11 pointer counter.cc bcheck./a.out
Du visar att du förstår vad en pekare är och skillnaden mellan att kopiera pekaren och det den pekar på. Du visar att du vet när allokerat minne kan avallokeras. Du visar att du förstår kopieringskonstruktorn, tilldelningsoperatorn och destruktorn samt vad självtilldelning är. Pointer_ Counter ::~ Pointer_ Counter () if ( --* counter == 0 ) delete pointer ; delete counter ; Pointer_ Counter :: Pointer_ Counter ( Pointer_ Counter const & pc) pointer = pc. pointer ; counter = pc. counter ; ++* counter ; Pointer_ Counter & Pointer_ Counter :: operator =( Pointer_ Counter const & pc) if ( this!= & pc ) Pointer_ Counter copy ( pc ); swap ( pointer, copy. pointer ); swap ( counter, copy. counter ); return * this ;
6. På siten prisjakt.se finns omdömen och bästa pris på en mängd produkter. Betyg på [4 p] produkterna sätts av besökarna i intervallet 1..10 och visas som ett viktat medelvärde. Ju fler som satt betyg på en produkt, ju närmare det sanna medelvärdet kommer det viktade medelvärdet. Om bara en person satt betyget 10 (medel 10) blir det viktade medelvärdet bara 7.5, men om 5 personer satt betyg 10 och 5 personer betyg 8 (medel 9) så blir det viktade medelvärdet 8.64. Ganska snabbt kan man komma fram till att följande formel används: v = m+((5 m)/(a+1)) där v står för det viktade betyget, m står för medelbetyget och a för antalet satta betyg. Omvänt gäller m = v + (v 5)/a. Du har webscrapat prislistan för mobiltelefoner och fått fram tabellen som återfinns i filen given files/prisjakt mobiltelefoner.txt. Först står telefonens beteckning följt av ett semikolon, sedan priset, antal betyg och sist det viktade betyget (eller - om inga betyg satts). De tre sistnämnda kolumnerna är separerade med ett eller flera mellanslag. Titta i filen så förstår du hur det ser ut. Läs in filen och skriv ut tabellen igen, men lägg till en kolumn för det sanna medelvärdet och ta bort produkter med färre än 4 betyg. Du får utgå från att produktbeteckningen inte är längre än 45 tecken. Utdata från ditt program skall exakt matcha given files/prisjakt facit.txt. Det tre första raderna i filen återges nedan. Samsung Galaxy S4 LTE GT-i9505 16GB 4390:- 85 8.40 8.44 Samsung Galaxy S4 Mini LTE GT-i9195 8GB 2990:- 7 8.47 8.97 Samsung Galaxy S4 Active LTE GT-i9295 16GB 4382:- 6 6.82 7.12... (2p) Fullt fungerande program och korrekt felhanterad filöppning. (1p) Det går att ange indatafil direkt på kommandoraden (felhanterat). (1p) Du håller aldrig mer än en rad från filen i minnet åt gången. Du visar att du kan ta emot indata via kommandoraden och felhantera detta. Du visar att du kan öppna en fil och avgöra om öppningen gick bra, samt stänga filen så snart du är klar. Det är lämpligt att välja en algoritm som inte lagrar hela filen i minnet. Du visar att du behärskar inläsning av ett lite struligare dataformat, samt kan genomföra en enkel matematisk beräkning och presentera utdata snyggt. Se pricehunt.cc. 7. Ibland kan man bli överhopad av arbetsuppgifter och då kan man behöva prioritera för att [4 p] klara av så många uppgifter som möjligt på så kort tid som möjligt. En algoritm som kan användas då är shortest job first. Den går helt enkelt till så att man hela tiden ser till att jobba på den uppgift som behöver minst tid till att bli klar. Låt oss anta att vi räknar tid i hela dagar. Varje dag får du ett antal (noll eller flera) nya uppgifter och uppskattar hur många dagar du behöver för att slutföra varje uppgift. Skriv ett program där du varje dag kan mata in nya uppgifter. En tomrad avbryter uppgiftsinmatningen och programmet skriver omedelbart ut vilken uppgift du ska arbeta med idag. Därpå antar programmet att du jobbar med uppgiften hela dagen (så kvarvarande arbetsmängd på uppgiften minskar med en dag) och frågar efter nästa dags uppgifter.
Programmet väljer hela tiden uppgift enligt shortest job first. Körexemplet visar tre dagars körning av programmet. Komplett indata och körning finns i given files/shortest job.txt. Programmet avslutar först när det inte finns något arbete kvar på kö. Enter new task arriving at day 0: skriva hemtenta Days needed for completion: 9 Enter new task arriving at day 0: Day 0: Today you should work on ==================> skriva hemtenta Enter new task arriving at day 1: C++ lab6 Days needed for completion: 6 Enter new task arriving at day 1: C++ spelprojekt Days needed for completion: 5 Enter new task arriving at day 1: Day 1: Today you should work on ==================> C++ spelprojekt Enter new task arriving at day 2: festförberedelse Days needed for completion: 2 Enter new task arriving at day 2: Day 2: Today you should work on ==================> festförberedelse Enter new task arriving at day 3: pythontenta Days needed for completion: 1 Enter new task arriving at day 3: Day 3: Today you should work on ==================> pythontenta (1p) Fullständig lösning av problemet. (2p) Du skapar en lämplig klass med en konstruktor med initieringslista, medlemsfunktioner och privata medlemmar för att hålla reda på arbetsuppgifter. (1p) Du implementerar jämförelseoperatorer och använder dem för att kunna sortera instanser av din klass med std::sort. Alternativt utför du sorteringen med hjälp av std::sort och ett lambda-uttryck. Du visar att du kan skriva en liten klass med konstruktor, privata medlemmar, get och set funktioner och jämförelseoperatorer. Du kan använda klassen tillsammans med en STL-kontainer för att lösa problemet. Se shortest job.cc. 8. [4 p] Ibland kan man bli glad av siffror. Det kan vara när rätt lottonummer kommer upp, när betyget blir 5 eller när det plötsligt finns 6-siffriga saldon på banken. Det du kanske inte vet är att det också finns glada nummer. För att avgöra om ett nummer är gladlynt tar man helt enkelt varje siffra i numret och kvadrerar. Summan av kvadraterna blir ett nytt nummer. Om proceduren upprepas på det nya numret kommer man så småningom till talet 1. Då är ursprungsnumret (och alla nummer man fick fram på vägen) gladlynt. Det kan också hända att man kommer till något av 4, 16, 37, 58, 89, 145, 42, 20. I så fall är talet ledset, eller i alla fall inte gladlynt. Som du ser bildar sekvensen 4, 16, 37, 58, 89, 145, 42, 20, 4 en cirkulär kedja 4 2 blir 16, 1 2 + 6 2 blir 37 o.s.v, så fort beräkningen kommer in på något av dessa nummer kommer den snurra mellan dessa för evigt (om inte du sätter stopp).
Skriv ett program som avgör om ett tal är gladlynt eller ej. Om talet inte är gladlynt skall du skriva ut vilket tal som upprepas först. Två körexempel är givna nedan: Mata in ett heltal: 4321 Sekvensen upprepas vid 37. Mata in ett heltal: 6543 Det är ett glatt tal! (2p) Korrekt lösning. Avdrag ges om du i koden skriver 8 olika villkor i if eller switch för att avgöra när du skall sluta (fullständig uppräkning). Det är tillåtet att använda en STL-container för att lagra den givna stoppsekvensen, men i denna uppgift ges mer poäng om du låter bli (se nästa punkt). (1p) Din beräkning håller reda på alla tal som förekommit i ett sdt::set och stoppar vid första upprepning. Denna lösning lagrar alltså inte den givna stoppsekvensen från start i programmet, utan avgör ändå när det är dags att avsluta beräkningen. (1p) Du använder minst en STL-container med iterator-iterering i din lösning. Uppgiften täcker in grundläggande STL och lite problemlösning. Ett set är en lämplig datastruktur. Du bör visa att du behärskar funktionsuppdelning, t.ex. en funktion för att beräkna summan av ett tals sifferkvadrater. Du bör visa att du hanterar en STLkontainer och iterering med iteratorer. Se happy number.cc.
Tips: En rudimentär påminnelse till några vanliga saker. Slumptal : C-stil Inkludera <cstdlib> och <ctime>. srand(time(nullptr)) initierar slumpgeneratorn. Se man -s3c rand i övrigt. C++-stil Inkludera <random>. Ett objekt av typen random_device kan skapas och sedan anropas som funktion för att slumpa fram ett tal. STL-containers : vector<value type> En kontinuerlig sekvens. Osorterad. Åtkomst med indexering eller iterering. list<value type> En länkad lista. Osorterad. Åtkomst med iterering. set<key type> En uppsättning (endast nycklar). Sorterad. map<key type, mapped type> En uppsättning nycklar med tillhörande värden. Sorterad. Vanliga STL medlemsfunktioner : pair<iterator,bool> insert (const type& val); Insättning i map eller set. Returnerar iterator och false vid dubblett, annars returneras iterator och true. iterator find (const key type& val); Sökning i map eller set. mapped type& operator[] (const key type& k); Sökning och insättning i map. iterator insert (const iterator position, const value type& val); Insättning i vector eller lista. iterator erase (const iterator position); Borttagning ur vector eller lista. void push back (const value type& val); Insättning sist i vector eller lista. void pop back (); Borttagning sist i vector eller lista. reference back(); Åtkomst av sista element i vector eller lista. STL-algoritmer : sort(begin, end) find(begin, end, värde) returnerar iterator for each(begin, end, lambda) unique(begin, end) returnerar iterator copy(sourcebegin, sourceend, destinationbegin)
Operatorer : Hur en klass A deklarerar några vanliga konstruktorer och operatorer: class A public : A (); A(A const &); ~A (); A& operator =( A const &); bool operator ==( A const &) const ; bool operator <( A const &) const ; A operator +( A const &) const ; A operator *( A const &) const ; ; friend ostream & operator < <( ostream & os, A const &); friend istream & operator > >( istream & os, A &);