DSV SU/KTH sid 1 (5) SP:PROG3 SP:PROG3 HT12 Tenta 2013-01-19 Tentan består av tre uppgifter. Max poäng är 30. För betyget E (godkänd) krävs minst 18 poäng och minst en poäng på varje uppgift. Betygskriteria finns i Daisy och återges på omstående sida. Hjälpmedel: Tillåtna hjälpmedel är medhavda böcker om C/C++. Anvisningar: Skriv endast på ena sidan av bladen. Påbörja varje ny uppgift på nytt blad. Skriv tydligt - oläsbara svar beaktas inte. Även icke fullständiga lösningar beaktas. Kommentera gärna era lösningar. Lösningsförslag kommer att presenteras i DSVs FirstClass-system i konferensen PROG3 Dokumentation, mappen Tentor. Lycka till!
DSV SU/KTH sid 2 SP:PROG3 Tentan betygsätts i A/B/C/D/E/Fx/F-skalan enligt följande kriteria: A - Samtliga lösningar är felfria (förutom uppenbara små misstag), fullständiga, genomförda med användning av vanliga C/C++-idiom och lämpliga funktioner ur C/C++ standardbibliotek (t.ex. utan onödig egen programmering där standardfunktioner kunde ha använts). Lösningarna tar hänsyn till alla i uppgiftstextexten angivna situationer och innehåller alla i uppgiftstexten begärda felkontroller. Däremot behöver de inte innehålla andra felkontroller eller ta hänsyn till andra situationer än de som angetts i uppgiftstexten. B - Som för betyget A utom att någon eller ett par lösningar kan innehålla något grövre misstag eller underlåta att ta hänsyn till någon enstaka angiven situation eller någon enstaka begärd felkontroll. C - Lösningarna är i princip korrekta men kan vara behäftade med fel och/eller underlåta att ta hänsyn till någon enstaka angiven situation eller begärd felkontroll. Lösningarna kan vara mer omständiga än nödvändigt (t.ex. skrivna med egen kod där standardfunktioner kunde ha använts). D - Som för betyget C utom att någon eller ett par lösningar kan innehålla grövre fel av principiell karaktär (t.ex. underlåta att allokera minne, tillåta minnesläckage o.s.v.). Lösningarna kan även innehålla grövre syntaktiska misstag (t.ex. sammanblandning med andra språk med liknande syntax). E - Som för betyget D utom att de flesta eller alla lösningar är behäftade med grövre fel av principiell karaktär. Icke desto mindre måste lösningarna visa grundläggande förståelse för problemet och åtminstone en ansats till korrekt lösning. Fx - Som för E ovan utom att någon lösning är helt felaktig eller saknas. F - Flera lösningar är helt felaktiga eller saknas. Betyget Fx innebär att studenten kan komplettera examinationen med en extra inlämningsuppgift för att få godkänt på aktuell tentamen (E men ej högre betyg). Kompletteringsuppgiften måste lämnas in enligt angiven deadline och kan endast användas för att få betyget E på den aktuella tentan.
DSV SU/KTH sid 3 SP:PROG3 Uppgift 1 (10 poäng) I ett C++-program används ett grafik-bibliotek där bilder representeras med följande struct: struct BIB_Image{ int count; char* pixels; ; pixels är en pekare till bilddata, count kan användas som en räknare som anger hur många Sprites som använder bilden. I biblioteket finns det även en funktion char* BIB_loadPixels(std::string filnamn); som allokerar utrymme till pixels och läser in bilden från en fil med det angivna namnet. I programmet har man gjort en klass Sprite som just nu ser ut så här: class Sprite{ Sprite(std::string filnamn); BIB_Image* image; ; Sprite::Sprite(std::string filnamn){ image = new BIB_Image(); image->pixels = BIB_loadPixels(filnamn); image->count = 1; Man vill att objekt av klassen Sprite ska kunna kopieras och tilldelas, varvid Spriteobjekten ska dela på samma BIB_Image-objekt: Sprite 1 Två Sprites använder detta image BIB_Image-objekt just nu BIB Image count Sprite 2 2 pixels image När man kopierar en Sprite ska alltså bl.a. räknaren i BIB_Image-objektet ökas med 1. När en Sprite försvinner så minskas räknaren i det utpekade BIB_Image-objektet med 1 och om räknaren blivit noll så tar man bort pixlarna och BIB_Image-objektet. Och när man tilldelar en Sprite så måste båda operationerna göras: först minskas räknaren i det BIB_Image-objektet Spriten hittills pekade på (och minnet städas om räknaren blivit noll) och sedan sätts den egna image-pekaren att peka på den andra Spritens image och dess räknare ökas. Komplettera klassen Sprite ovan så att dessa operationer fungerar på avsett sätt. Du behöver inte tänka på kontroll av att Sprite-objekten skapas dynamiskt.
DSV SU/KTH sid 4 SP:PROG3 Uppgift 2 (10 poäng) Skriv klasser som representerar följande scenario. Använd gärna std::vector<> där det behövs datasamlingar. Se till att tillämpningar inte kan skapa objekt av basklassen i hierarkin medan objekt av subklasserna endast kan skapas dynamiskt. Se också till att värdesemantik är förbjuden för objekt av dessa klasser. Du får definiera icke-statiska medlemsfunktioner i klassdefinitionerna i denna uppgift. Uppgiften handlar om olika typer av texter som ska översättas till svenska från andra språk samt två olika typer av översättare. Varje text är skriven på ett visst språk (representerat som en sträng t ex engelska ) samt ger ett visst arvode till den som översätter texten. Texterna kan vara av följande typer: Serietidning: representeras av hur många bilder den har (en int), arvodet blir 20 :- per bild. Sida (ett dokument): har antalet ord som sidan innehåller samt hur många av dessa ord som har fler än 7 bokstäver (två intar). Själva texten bortser vi från. Arvodet blir 4 kronor per ord + ytterliggare 3 kronor för varje ord med fler än 7 bokstäver. Bok: består av ett antal sidor enligt ovan (i en lämplig samling). En bok skall kunna utökas med ett antal sidor. Arvodet blir 90 % av summan av varje sidas arvode. Det finns även översättare som kan översätta texter. Varje översättare behärskar ett antal olika språk (representerat som en samling av strängar t ex engelska, franska, spanska ). En översättare skall kunna lära sig ett nytt språk, det nya språket (en sträng alltså) läggs då till samlingen av språk som översättaren behärskar. En översättare kan endast översätta texter skrivna på ett av de språk som hon behärskar. I övrigt skall en översättare bara ha en medlemsfunktion i vilken hon väljer ut en text att översätta ur en samling med blandade texter (textsamlingen kommer som ett argument till metoden). Vilken av texterna i samlingen man väljer beror på vilken sorts översättare man är. En folklig översättare väljer den texten som ger bäst betalt alltså texten med högst arvode (av de texter skrivna på ett språk som översättaren behärskar). En intellektuell översättare översätter endast böcker. Hon väljer den bok som har flest antal sidor (av de böcker som är skrivna på ett språk som behärskas). Den text som valts tas bort ur samlingen och lagras hos översättaren som aktuell text (den text som översättaren håller på med). Om ingen lämplig text fanns i samlingen händer ingenting.
DSV SU/KTH sid 5 SP:PROG3 Uppgift 3 (10 poäng) Denna uppgift handlar om att representera en mängd av små heltal med en bitvektor och använda bitmanipuleringsoperationer för att hantera denna. Detta ska tillämpas för att skriva ut alla primtal mellan 2 och något visst givet heltal N, med en algoritm som kallas Eratosthenes såll. Ett primtal är som bekant ett heltal >= 2, som bara är delbart med 1 och sig självt. Ett sätt hitta alla primtal som är mindre än ett visst N är följande (Eratosthenes såll): skapa en mängd innehållande alla heltal mellan 2 och N for(i=2; i < N; i++) if (i är fortfarande kvar i mängden) for(j=2; i*j<n; j++) /* Tar bort alla multiplar av i från mängden */ ta bort i*j ur mängden; skriv ut de heltal som är kvar i mängden (de är primtal) För att mängdoperationer ska vara snabba brukar man i sådana tillämpningar representera heltalsmängden så att man har en bit reserverad för varje möjligt heltal, där 0 betyder att heltalet inte är med i mängden och 1 betyder att heltalet är med i mängden. T.ex. för att representera en mängd som kan innehålla värden mellan 0 och 511 behöver man 512 bitar, alltså 512/(sizeof(int)*8) heltal (= 16 heltal om sizeof(int) är 4 obs att sizeof ger storleken i bytes, inte i bits). Man skulle alltså allokera en array av 16 heltal av typen unsigned int. När man ska göra någon operation på ett tal i mängden räknar man först ut vilket element i arrayen talet ligger i (genom heltalsdivision: tal/(sizeof(int)*8) ) och sedan vilken bitposition i detta element talet har (genom rest-vid-division: tal % (sizeof(int)*8). Sedan kan man använda de vanliga bitmanipuleringsoperationer på detta element i arrayen och denna bitposition för att kolla om talet är med i mängden (bitpositionen är 1), addera talet till mängden (sätta en 1:a på platsen), ta bort talet från mängden (sätta en 0:a på platsen) o.s.v. Skriv en funktion void Eratosthenes(int n) som implementerar ovanstående algoritm. Argumentet n motsvarar talet N ovan, du kan anta att n är en multipel av sizeof(int), dvs att alla bitar i den allokerade arrayen motsvarar tal som ska undersökas och ev. skrivas ut. Obs! att den första operationen efter allokering av arrayen är att fylla den med binära 1:or (så att alla talen är med i mängden från början). Detta görs bekvämast genom att sätta alla element i arrayen till -1. -1 representeras nämligen i 2-komplementsmetoden som idel 1:or.
SP:PROG3 HT2012 Lösningsförslag tenta 2013-01-19 Uppgift 1 class Sprite{ Sprite(std::string filnamn); Sprite(const Sprite& other); ~Sprite(); const Sprite& operator=(const Sprite& rhs); BIB_Image* image; ; Sprite::Sprite(std::string filnamn){ image = new BIB_Image(); image->pixels = BIB_loadPixels(filnamn); image->count = 1; Sprite::Sprite(const Sprite& other) : image(other.image){ image->count++; Sprite:: ~Sprite(){ if (--image->count == 0){ delete [] image->pixels; delete image; const Sprite& Sprite::operator=(const Sprite& rhs){ if (image!= rhs.image){ if (--image->count == 0){ delete [] image->pixels; delete image; image = rhs.image; image->count++; return *this;
SP:PROG3 HT2012 Lösningsförslag tenta 2013-01-19 Uppgift 2 class Text{ virtual int arvode() const = 0; virtual ~Text(){ std::string getlang() const { return lang; Text(const std::string lan):lang(lan){ std::string lang; Text(const Text&); const Text& operator=(const Text&); ; class Serie : public Text{ int arvode() const { return bilder * 20; static Serie* getinstance(const std::string lang, int b); Serie(const std::string lang, int b):text(lang), bilder(b){ int bilder; ; Serie* Serie::getInstance(const std::string lang, int b){ return new Serie(lang,b); class Sida : public Text{ int arvode() const { return ord * 4 + langa * 3; static Sida* getinstance(const std::string lang, int o, int lo); Sida(const std::string lang, int o, int lo):text(lang), ord(o), langa(lo){ int ord, langa; ; Sida* Sida::getInstance(const std::string lang, int o, int lo){ return new Sida(lang,o,lo); class Bok : public Text{ int arvode() const { int arvo = 0; for(int i=0; i<sidor.size(); i++) arvo += sidor[i]->arvode(); return arvo * 0.9; void add(std::vector<sida*>& sids){ for(int i=0; i<sids.size(); i++) sidor.push_back(sids[i]); int antalsidor() const { return sidor.size(); static Bok* getinstance(const std::string lang); Bok(const std::string lang):text(lang){ std::vector<sida*> sidor; ; Bok* Bok::getInstance(const std::string lang){ return new Bok(lang);
SP:PROG3 HT2012 Lösningsförslag tenta 2013-01-19 class Tolk{ void learnsalang(std::string lang){ langs.insert(lang); void select(std::vector<text*>& texts){ int vald = -1; Text* valdtext = NULL; for(int i=0; i<texts.size(); i++) if (langs.count(texts[i]->getlang()) && hellre(texts[i], valdtext)){ vald = i; valdtext = texts[vald]; if (vald!= -1){ aktuell = valdtext; texts.erase(texts.begin() + vald); virtual ~Tolk(){ Text* get() const { return aktuell; Tolk():aktuell(NULL){ virtual bool hellre(const Text* t1, const Text* t2) const = 0; std::set<std::string> langs; Text* aktuell; Tolk(const Tolk&); const Tolk& operator=(const Tolk&); ; class FolkTolk : public Tolk{ static FolkTolk* getinstance(); FolkTolk(){ bool hellre(const Text* t1, const Text* t2) const{ if (t2 == NULL) return true; return t1->arvode() > t2->arvode(); ; FolkTolk* FolkTolk::getInstance(){ return new FolkTolk(); class IntellekTolk : public Tolk{ static IntellekTolk* getinstance(); IntellekTolk(){ bool hellre(const Text* t1, const Text* t2) const{ if (const Bok* b1 = dynamic_cast<const Bok*>(t1)){ if (const Bok* b2 = dynamic_cast<const Bok*>(t2)) return b1->antalsidor() > b2->antalsidor(); else return true; else return false; ; IntellekTolk* IntellekTolk::getInstance(){ return new IntellekTolk();
SP:PROG3 HT2012 Lösningsförslag tenta 2013-01-19 Uppgift 3 void Eratosthenes(int n){ const int bitsperint = sizeof(int)*8; const int noofints = n/bitsperint; unsigned int* set = new unsigned int[noofints]; for(int i = 0; i < noofints; i++) set[i] = -1; for(int i = 2; i < n; i++) if (set[i / bitsperint] & 1UL << i % bitsperint) for(int j = 2; i * j < n; j++) set[(i*j) / bitsperint] &= ~(1UL << (i*j) % bitsperint); for(int i = 2; i < n; i++) if (set[i / bitsperint] & 1UL << i % bitsperint) std::cout << i << " "; std::cout << std::endl; delete [] set;