Opdracht 2: Abstract Data Type.

© Harry Broeders.

Deze opdracht bestaat uit de deelopdrachten 2a t/m 2d. Alle deelopdrachten moet je laten aftekenen door de docent.

In het dictaat staat een C programma waarin gebruik wordt gemaakt van variabelen waarin een tijdsduur in uren en minuten kan worden opgeslagen. Je hebt bij C programmeren geleerd dat een tijdsduur door middel van een struct weergegeven kan worden. In de theorielessen is er besproken dat deze manier van werken programma’s oplevert die niet goed onderhoudbaar, uitbreidbaar en herbruikbaar zijn. Je kunt een tijdsduur beter als ADT definiëren.

We willen nu dus een ADT (Abstract Data Type) , ook wel zelfgedefinieerd datatype genoemd, maken waarin een tijdsduur in uren en minuten kan worden opgeslagen. We noemen dit zelf gedefinieerde datatype Tijdsduur.

Het ADT Tijdsduur kan in C++ als volgt gedeclareerd, gedefinieerd en gebruikt worden (tijd1.cpp De link voor dit plaatje verwijst naar een C++ file getest met Borland C++ 5.02.):

#include <iostream>        // nodig voor cout (schrijven naar scherm)
#include <iomanip>         // nodig voor setw (veldbreedte definiëren)
using namespace std;

// De declaratie van de ADT Tijdsduur:

class Tijdsduur {
public:
//...
    void eraf(Tijdsduur t);
//...
private:
    int min;
//...
};

// De definities van de memberfunctie van de ADT Tijdsduur, oftewel: de implementatie van de ADT Tijdsduur:

void Tijdsduur::eraf(Tijdsduur t) {
    min -= t.min;
//... 
}

//...

int main() {
    Tijdsduur t1(3, 50);        // t1 is 3 uur en 50 minuten
    cout << "t1 = "; t1.print(); cout << endl;
    const Tijdsduur kw(15);     // kw is 15 minuten
    cout << "kw = "; kw.print(); cout << endl;
    t1.erbij(kw);               // Tel kw bij t1 op
    cout << "t1 = "; t1.print(); cout << endl;
    Tijdsduur t2(t1);           // t2 is een kopie van t1
    t2.eraf(kw);                // Trek kw van t2 af
    cout << "t2 = "; t2.print(); cout << endl;
    t2.maal(7);                 // Vermenigvuldig t2 met 7
    cout << "t2 = "; t2.print(); cout << endl;
    Tijdsduur t3(3, -122);      // t3 is 3 uur minus 122 minuten
    cout << "t3 = "; t3.print(); cout << endl;
    Tijdsduur t4(3, 122);       // t4 is 3 uur plus 122 minuten
    cout << "t4 = "; t4.print(); cout << endl;
    cout << "Druk op de return-toets." << endl;
    cin.get();
    return 0;
}

De uitvoer moet dan zijn:
t1 =  3 uur en 50 minuten
kw =           15 minuten
t1 =  4 uur en  5 minuten
t2 =  3 uur en 50 minuten
t2 = 26 uur en 50 minuten
t3 =           58 minuten
t4 =  5 uur en  2 minuten

Opdracht 2a.

Vul de declaratie en de implementatie van de ADT genaamd Tijdsduur verder in. Zorg ervoor dat het bovenstaande programma tijd1.cpp De link voor dit plaatje verwijst naar een C++ file getest met Borland C++ 5.02. zonder warnings compileert en de gewenste uitvoer produceert. Zoek (indien nodig) inspiratie bij de in de les behandelde class Breuk.

Tip: Je kunt het beste eerst alle regels van main behalve de laatste 3 commentaar maken en dan regel voor regel het commentaar verwijderen en de class Tijdsduur aanpassen zodat het programma correct werkt. Dus: om de eerste regel van main te laten werken moet je in de class Tijdsduur een constructor declareren en die constructor moet je ook implementeren. Daarna kun je de tweede regel van main laten werken door in de class Tijdsduur een memberfunctie print te declareren en te implementeren. Enz.

Tip: Zorg ervoor dat de opgeslagen minuten altijd >=0 en <60 zijn.

Het ADT Tijdsduur kan veel eenvoudiger gebruikt worden als we ervoor zorgen dat een variabele van het zelfgemaakte type Tijdsduur gebruikt kan worden op dezelfde wijze als een variabele van het standaard type int. Dit kan door gebruik te maken van operator overloading.

Door de operator << te overloaden kun je de objecten van de class Tijdsduur afdrukken op dezelfde manier als je een integer kunt afdrukken. (Dit wordt in de theorie les nog uitgebreid besproken.)

Zorg er met behulp van operator overloading voor dat het ADT Tijdsduur eenvoudig als volgt gebruikt kan worden (tijd2.cpp De link voor dit plaatje verwijst naar een C++ file getest met Borland C++ 5.02.):

#include <iostream>           // nodig voor cout (schrijven naar scherm)
#include <iomanip>            // nodig voor setw (veldbreedte definiëren)
using namespace std;

// De declaratie van de ADT Tijdsduur:

class Tijdsduur {
public:
//...
    void print(ostream& o) const;
private:
//...
};

ostream& operator<<(ostream& left, const Tijdsduur& right);

// De implementatie van de ADT Tijdsduur:

//...

void Tijdsduur::print(ostream& o) const {
    // Deze functie moet de Tijdsduur wegschrijven naar de uitvoer genaamd "o"
    o << //.. 
}

// Deze operator hoef je nu nog niet te begrijpen
// In les 7 wordt dit uitgelegd
ostream& operator<<(ostream& left, const Tijdsduur& right) {
    right.print(left);
    return left;
}

int main() {
    Tijdsduur t1(3, 50);        // t1 is 3 uur en 50 minuten
    cout << "t1 = " << t1 << endl;
    const Tijdsduur kw(15);     // kw is 15 minuten
    cout << "kw = " << kw << endl;
    t1 += kw;                   // Tel kw bij t1 op
    cout << "t1 = " << t1 << endl;
    Tijdsduur t2(t1 - kw);      // t2 is t1 min kw
    cout << "t2 = " << t2 << endl;
    t2 *= 7;                    // Vermenigvuldig t2 met 7
    cout << "t2 = " << t2 << endl;
    Tijdsduur t3(t2 - 122);     // t3 is t2 minus 122 minuten
    cout << "t3 = " << t3 << endl;
    Tijdsduur t4(722 - t1);     // t4 is 722 minuten minus t1
    cout << "t4 = " << t4 << endl;
    if (t3 != t4)
        cout << "t3 is ongelijk aan t4." << endl;
    if (t3 > t4)
        cout << "t3 is groter dan t4." << endl;
    cin.get();
    return 0;
}

De uitvoer moet dan zijn:
t1 =  3 uur en 50 minuten
kw =           15 minuten
t1 =  4 uur en  5 minuten
t2 =  3 uur en 50 minuten
t2 = 26 uur en 50 minuten
t3 = 24 uur en 48 minuten
t4 =  7 uur en 57 minuten
t3 is ongelijk aan t4.
t3 is groter dan t4.

Opdracht 2b.

Zorg ervoor dat het bovenstaande programma tijd2.cpp De link voor dit plaatje verwijst naar een C++ file getest met Borland C++ 5.02. zonder warnings compileert en de gewenste uitvoer produceert. Zoek (indien nodig) inspiratie bij de in de les behandelde class Breuk.

Een slimme programmeur bedenkt dat het veel handiger is om een tijdsduur (alleen) als een aantal minuten op te slaan. Bij het afdrukken kan dit aantal minuten dan worden omgezet naar een aantal uren en een resterend aantal minuten (kleiner dan 60). Dit heeft twee voordelen:

De programmeurs die het ADT Tijdsduur gebruiken mogen natuurlijk niets merken van deze aanpassing. De programma's die gebruik maken van dit ADT moeten natuurlijk wel opnieuw gecompileerd worden.

Opdracht 2c.

Pas het ADT Tijdsduur uit opdracht 2b aan zodat dit type nog slechts één private datamember van het type int heeft (de tijdsduur uitgedrukt in minuten). Zorg ervoor dat het bovenstaande programma tijd2.cpp De link voor dit plaatje verwijst naar een C++ file getest met Borland C++ 5.02. zonder warnings compileert en nog steeds de gewenste uitvoer produceert.

Opdracht 2d.

Splits het programma uit opdracht 2c in 2 source files main.cpp en tijdsduur.cpp en 1 header file tijdsduur.h. Zie paragraaf 2.29 in het dictaat.

Je kunt in Microsoft Visual C++ verschillende source files combineren tot 1 executable door meerdere files toe te voegen aan een project met behulp van de knop op de knoppenbalk of met de sneltoets Ctrl+Shift+A. Je ziet de verschillende source files in het mapje "Source Files" onder het project in de "Solution Explorer".

verder met opdracht 3 ...