Opgave

Structuur van Computerprogramma’s II: Week 7
Dries Harnie, Coen De Roover
28 oktober 2014
Een eenvoudige tracer
Bij het verlaten van een functie wordt de destructor van alle lokale variabelen opgeroepen. Je kan deze gebruiken om “tracer” code te schrijven die de control flow van je
code volgt. Stel dat je volgende code hebt geschreven:
void g() {
Tracer t("Functie g");
cout << "world!" << endl;
}
void f() {
Tracer t("Functie f");
cout << "Hello" << endl;
g();
}
dan zou de output er als volgt kunnen uit zien1 :
>>> Functie
Hello
>>> Functie
world!
<<< Functie
<<< Functie
f
g
g
f
Implementeer de Tracer klasse. Voeg tevens een eenvoudig timing mechanisme toe
dat bij het verlaten van de functie aangeeft hoelang deze geduurd heeft. Je kan hiervoor de clock() functie gebruiken uit <time.h>, deze functie geeft een stijgende
waarde in microseconden terug.
1 rood
is output op de standaard error stream
1
Dimensies
In de wetenschappen werkt men meestal met gedimensioneerde getallen: dit zijn waarden die bestaan uit een getal en een bijhorende eenheid, bvb. 1 meter, 5 kilogram, 15
meter per seconde. Deze eenheid bestaat op zich uit het product van zowel positieve
als negatieve machten van basiseenheden. Voor deze oefening beschouwen we meter (m), kilogram (kg) en seconde (s) als basiseenheden. De voorbeeldjes hierboven
kan je dus schrijven als 1 ∗ m1 , 5 ∗ kg1 , en 15 ∗ m1 ∗ s−1 .
1. Definieer de Dim klasse die een gedimensioneerd getal voorstelt. Om het product
van machten voor te stellen kan je bijvoorbeeld een std::map<std::string, int>
gebruiken: dit is een dictionary die std::strings op ints mapt. Voeg een constructor toe voor een getal en een dimensie, en voeg een constructor toe voor
niet-gedimensioneerde getallen (waarbij je eenheid gewoon een lege std::map
is). Gebruik deze om de variabelen m, kg en s te definiëren, die overeenkomen
met één eenheid van elk. Definieer ook variabelen voor de afgeleide eenheden
mm (millimeter) en h (uur).
2. Implementeer een correcte overload voor de << operator, zodanig dat je gedimensioneerde getallen kan printen zoals hierboven. Je kan volgende code gebruiken om door de std::map te lopen:
std::map<std::string, int>::iterator it;
for (it = eenheden.begin(); it != eenheden.end(); ++it) {
const std::string & eenheid = it->first;
int aantal = it->second;
// doe iets met eenheid en aantal
}
3. Implementeer de correcte overload voor operator * zodanig dat je gedimensioneerde getallen kan schalen. Doe hetzelfde voor operator /, maar merk op
dat 1 s / 1 == 1 s, terwijl 1 / 1 s = 1 s^-1.
4. Implementeer operator *, operator / nu ook voor gedimensioneerde getallen. Bij het vermenigvuldigen moet je de aantallen optellen, bij delen aftrekken.
Merk op dat deze operaties kunnen leiden naar een gedimensioneerd getal voor
eenheden met macht nul, probeer dit te voorkomen.
5. Implementeer tenslotte de operator + en operator - voor gedimensioneerde
getallen. Om te voorkomen dat de gebruiker twee getallen optelt van verschillende dimensies kan je bijvoorbeeld de assert functie gebruiken uit de <cassert>
header. Deze sluit het programma af met een foutmelding als haar argument onwaar is.
2