Uhrzeit: Die Klasse Time

1. Aufgabe

Entwerfen Sie für Objekte, die eine Uhrzeit mit Stunden-, Minuten- und Sekundenanteil repräsentieren, eine geeignete Klasse Time. Die Stunde kann Werte zwischen 0 und 23 einnehmen, die Minuten und Sekunden Werte zwischen 0 und 59. Weitere Hinweise zur Spezifikation einer Klasse Time finden Sie in Tabelle 1 vor:

Methode

Beschreibung

Konstruktoren

Time ();
Time (int seconds, int minutes, int hours);
Time (int seconds);
Time (char*);

Neben dem Standardkonstruktur besitzt die Klasse mehrere benutzerdefinierte Konstruktoren. Mit ihnen kann man ein Time-Objekt mit drei Werten seconds, minutes und hours vorbelegen oder man gibt nur einen Sekundenwert – im Bereich von 0 bis 86400 – vor. Alternativ lässt sich eine Uhrzeit auch durch eine Zeichenkette des Formats "hh:mm:ss" spezifizieren.

Methoden

void Reset ();
void Add (const Time&);
void Sub (const Time&);
Time Diff (const Time&) const;
void Increment ();
void Decrement ();

Mit Add und Sub lassen sich zwei Uhrzeiten addieren bzw. subtrahieren. Ein eventueller Über- bzw. Unterlauf ist zu berücksichtigen. Die Diff-Methode berechnet die Differenz zweier Uhrzeiten und stellt das Ergebnis wieder in einem Time-Objekt bereit. Mit der Reset-Methode werden alle drei Werte einer Uhrzeit auf 0 gestellt, zum Addieren oder Subtrahieren einer einzelnen Sekunde gibt es die zwei Methoden Increment bzw. Decrement.

Arithmetische Operatoren

// arithmetic operators
Time operator+ (const Time&) const;
Time operator- (const Time&) const;

// arithmetic-assignment operators
Time operator+= (const Time&);
Time operator-= (const Time&);
Time operator+= (int seconds);
Time operator-= (int seconds);

// increment / decrement operators
friend Time& operator++ (Time&);           // prefix increment
friend const Time operator++ (Time&, int); // postfix increment
friend Time& operator-- (Time&);           // prefix decrement
friend const Time operator-- (Time&, int); // postfix decrement

Die Funktionsweise der Operatoren ist weitestgehend selbsterklärend – die beiden Operatoren ++ und -- arbeiten analog wie Increment bzw. Decrement.

Vergleichsoperatoren

friend bool operator== (const Time&, const Time&);
friend bool operator!= (const Time&, const Time&);
friend bool operator<= (const Time&, const Time&);
friend bool operator<  (const Time&, const Time&);
friend bool operator>= (const Time&, const Time&);
friend bool operator>  (const Time&, const Time&);

Vergleich zweier Uhrzeiten.

Konvertierungsoperator

operator int();

Für die Umwandlung einer Uhrzeit in ihre Anzahl Sekunden legen wir die Operatorenschreibweise zu Grunde.

Ein- und Ausgabe

friend ostream& operator<< (ostream&, const Time&);
friend istream& operator>> (istream&, Time&);

Ein- und Ausgabe eines Time-Objekts in C++-Manier. Die Ausgabe sollte sich am Format "hh:mm:ss" orientieren, bei einstelligen Werten ist eine führende Null voranzustellen.

Tabelle 1. Methoden der Klasse Time.


Es folgen einige Beispiele, um die Umsetzung der einzelnen Klassenelemente aus Tabelle 1 besser zu veranschaulichen. Wir beginnen mit den Konstruktoren:

// testing c'tors
Time t1;
cout << t1 << endl;
Time t2 (0, 30, 12);
cout << t2 << endl;
Time t3 ("09:30:00");
cout << t3 << endl;
Time t4 (24*60*60 - 1);
cout << t4 << endl;

Ausgabe:

00:00:00
12:30:00
09:30:00
23:59:59

Codefragment zum Testen der Add-Methode:

// testing 'Add'
Time t1 (0, 0, 12);
Time t2 (33, 33, 3);
for (int i = 0; i < 5; i ++)
{
    t1.Add (t2);
    cout << t1 << endl;
}

Ausgabe:

15:33:33
19:07:06
22:40:39
02:14:12
05:47:45

Codefragment zum Testen der Increment-Methode:

// testing 'Increment'
Time t (55, 59, 23);
for (int i = 0; i < 8; i ++)
{
    t.Increment ();
    cout << t << endl;
}

Ausgabe:

23:59:56
23:59:57
23:59:58
23:59:59
00:00:00
00:00:01
00:00:02
00:00:03

Codefragment zum Testen der Diff-Methode:

// testing 'Diff'
Time t1;
Time t2("23:59:59");
Time t3 = t1.Diff(t2);
cout << t3 << endl;
t3 =  t2.Diff(t1);
cout << t3 << endl;

Ausgabe:

23:59:59
23:59:59

Codefragment zum Testen der arithmetischen Operatoren:

// testing operators
Time t1 (15, 30, 6);
Time t2 = t1 + t1;
cout << t2 << endl;
t2 += t1;
cout << t2 << endl;
t2 -= 120;
cout << t2 << endl;
t2 -= t1;
cout << t2 << endl;

Ausgabe:

13:00:30
19:30:45
19:28:45
12:58:30

Codefragment zum Testen des Inkrement- und Dekrement-Operators:

// testing increment/decrement operator
Time t1 (0, 0, 12);
Time t2 = t1++;
cout << t2 << endl;
t2 = ++t1;
cout << t2 << endl;
t2 = t1--;
cout << t2 << endl;
t2 = --t1;
cout << t2 << endl;

Ausgabe:

12:00:00
12:00:02
12:00:02
12:00:00

Codefragment zum Testen des int-Konvertierungsoperators:

// testing conversion operator
Time t;
t = 60*60 + 60 + 1;
cout << "Time:    " << t << endl;
cout << "Seconds: " << (int) t << endl;

Ausgabe:

Time:    01:01:01
Seconds: 3661

Codefragment zum Testen der Ein- und Ausgabe (Konsoleneingaben fett gedruckt):

Time t;
cin >> t;
cout << t << endl;

Ausgabe:

Hours [hh]: 12
Minutes [mm]: 34
Seconds [ss]: 56
12:34:56

2. Lösung

01: class Time
02: {
03: private:
04:     int m_seconds;
05:     int m_minutes;
06:     int m_hours;
07: 
08: public:
09:     // c'tors
10:     Time ();
11:     Time (int seconds, int minutes, int hours);
12:     Time (int seconds);  // conversion c'tor
13:     Time (char*);        // conversion c'tor
14: 
15:     // getter // setter
16:     int GetSeconds () const { return m_seconds; };
17:     int GetMinutes () const { return m_minutes; };
18:     int GetHours () const { return m_hours; };
19:     void SetSeconds (int seconds);
20:     void SetMinutes (int minutes);
21:     void SetHours (int hours);
22: 
23:     // public interface
24:     void Reset ();
25:     void Add (const Time&);
26:     void Sub (const Time&);
27:     Time Diff (const Time&) const;
28:     void Increment ();
29:     void Decrement ();
30: 
31:     // arithmetic operators
32:     Time operator+ (const Time&) const;
33:     Time operator- (const Time&) const;
34: 
35:     // arithmetic-assignment operators
36:     Time operator+= (const Time&);
37:     Time operator-= (const Time&);
38:     Time operator+= (int seconds);
39:     Time operator-= (int seconds);
40: 
41:     // increment/decrement operators (prefix/postfix version)
42:     friend Time& operator++ (Time&);           // prefix increment
43:     friend const Time operator++ (Time&, int); // postfix increment
44:     friend Time& operator-- (Time&);           // prefix decrement
45:     friend const Time operator-- (Time&, int); // postfix decrement
46: 
47:     // comparison operators
48:     friend bool operator== (const Time&, const Time&);
49:     friend bool operator!= (const Time&, const Time&);
50:     friend bool operator<= (const Time&, const Time&);
51:     friend bool operator<  (const Time&, const Time&);
52:     friend bool operator>= (const Time&, const Time&);
53:     friend bool operator>  (const Time&, const Time&);
54: 
55:     // conversion operator
56:     operator int();
57: 
58:     // input / output
59:     friend ostream& operator<< (ostream&, const Time&);
60:     friend istream& operator>> (istream&, Time&);
61: 
62: private:
63:     // helper methods
64:     int TimeToSeconds ();
65:     void SecondsToTime (int seconds);
66: };

Beispiel 1. Klasse Time: Schnittstelle.


001: #include <iostream>
002: #include <iomanip>
003: using namespace std;
004: #include "Time.h"
005: 
006: // c'tors
007: Time::Time () : m_seconds(0), m_minutes(0), m_hours (0) {}  // default c'tor
008: 
009: Time::Time (int seconds, int minutes, int hours)  // user-defined c'tor
010: {
011:     m_seconds = (0 <= seconds && seconds < 60) ? seconds : 0;
012:     m_minutes = (0 <= minutes && minutes < 60) ? minutes : 0;
013:     m_hours = (0 <= hours && hours < 24) ? hours : 0;
014: }
015: 
016: Time::Time (char* s)  // user-defined c'tor
017: {
018:     // expecting format "hh:mm:ss" - don't expect wrong input (!)
019:     int hours = 10 * (s[0] - '0') + (s[1] - '0');
020:     m_hours = (0 <= hours && hours < 24) ? hours : 0;
021:     s += 3;  // skip hours and colon
022:     int minutes = 10 * (s[0] - '0') + (s[1] - '0');
023:     m_minutes = (0 <= minutes && minutes < 60) ? minutes : 0;
024:     s += 3;  // skip minutes and colon
025:     int seconds = 10 * (s[0] - '0') + (s[1] - '0');
026:     m_seconds = (0 <= seconds && seconds < 60) ? seconds : 0;
027: }
028: 
029: Time::Time (int seconds)     // conversion c'tor
030: {
031:     if (0 <= seconds && seconds <= 24 * 60 * 60)
032:     {
033:         SecondsToTime (seconds);
034:     }
035:     else
036:     {
037:         m_seconds = m_minutes = m_hours = 0;
038:     }
039: }
040: 
041: // getter // setter
042: void Time::SetSeconds (int seconds)
043: {
044:     m_seconds = (0 <= seconds && seconds < 60) ? seconds : 0;
045: }
046: 
047: void Time::SetMinutes (int minutes)
048: {
049:     m_minutes = (0 <= minutes && minutes < 60) ? minutes : 0;
050: }
051: 
052: void Time::SetHours (int hours)
053: {
054:     m_hours = (0 <= hours && hours < 24) ? hours : 0;
055: }
056: 
057: // public interface
058: void Time::Reset ()
059: {
060:     m_seconds = 0;
061:     m_minutes = 0;
062:     m_hours = 0;
063: }
064: 
065: void Time::Add (const Time& t)
066: {
067:     m_seconds += t.m_seconds;
068:     m_minutes += t.m_minutes;
069:     m_hours += t.m_hours;
070: 
071:     // normalize object
072:     m_minutes += m_seconds / 60;
073:     m_hours += m_minutes / 60;
074:     m_seconds = m_seconds % 60;
075:     m_minutes = m_minutes % 60;
076:     m_hours = m_hours % 24;
077: }
078: 
079: void Time::Sub (const Time& t)
080: {
081:     int seconds =
082:         (m_hours * 3600 + m_minutes * 60 + m_seconds) -
083:         (t.m_hours * 3600 + t.m_minutes * 60 + t.m_seconds);
084: 
085:     if (seconds < 0)
086:         seconds += 24 * 60 * 60;
087: 
088:     // transform total seconds into hours, minutes and seconds
089:     SecondsToTime (seconds);
090: }
091: 
092: Time Time::Diff (const Time& t) const
093: {
094:     Time tmp;
095:     if (*this <= t)
096:         tmp = t - *this;
097:     else
098:         tmp = *this - t;
099: 
100:     return tmp;
101: }
102: 
103: void Time::Increment ()
104: {
105:     m_seconds ++;
106:     if (m_seconds >= 60)
107:     {
108:         m_seconds = 0;
109:         m_minutes ++;
110:         if (m_minutes >= 60)
111:         {
112:             m_minutes = 0;
113:             m_hours ++;
114:             if (m_hours >= 24)
115:             {
116:                 m_hours = 0;
117:             }
118:         }
119:     }
120: }
121: 
122: void Time::Decrement ()
123: {
124:     m_seconds --;
125:     if (m_seconds < 0)
126:     {
127:         m_seconds = 59;
128:         m_minutes --;
129:         if (m_minutes < 0)
130:         {
131:             m_minutes = 59;
132:             m_hours --;
133:             if (m_hours < 0)
134:             {
135:                 m_hours = 23;
136:             }
137:         }
138:     }
139: }
140: 
141: // arithmetic operators
142: Time Time::operator+ (const Time& t) const
143: {
144:     Time tmp(*this);
145:     tmp.Add(t);
146:     return tmp;
147: }
148: 
149: Time Time::operator- (const Time& t) const
150: {
151:     Time tmp(*this);
152:     tmp.Sub(t);
153:     return tmp;
154: }
155: 
156: Time Time::operator+= (const Time& t)
157: {
158:     Add(t);
159:     return *this;
160: }
161: 
162: Time Time::operator-= (const Time& t)
163: {
164:     Sub(t);
165:     return *this;
166: }
167: 
168: Time Time::operator+= (int seconds)
169: {
170:     for (int i = 0; i < seconds; i ++)
171:         Increment ();
172: 
173:     return *this;
174: }
175: 
176: Time Time::operator-= (int seconds)
177: {
178:     for (int i = 0; i < seconds; i ++)
179:         Decrement ();
180: 
181:     return *this;
182: }
183: 
184: // increment operator: prefix version
185: Time& operator++ (Time& t)
186: {
187:     t += 1;
188:     return t;
189: }
190: 
191: // decrement operator: prefix version
192: Time& operator-- (Time& t)
193: {
194:     t -= 1;
195:     return t;
196: }
197: 
198: // increment operator: postfix version
199: const Time operator++ (Time& t, int)
200: {
201:     Time tmp (t);  // construct a copy
202:     ++ t;          // increment number
203:     return tmp;    // return the copy
204: }
205: 
206: // decrement operator: postfix version
207: const Time operator-- (Time& t, int)
208: {
209:     Time tmp (t);  // construct a copy
210:     -- t;          // decrement number
211:     return tmp;    // return the copy
212: }
213: 
214: // comparison operators
215: bool operator== (const Time& t1, const Time& t2)
216: {
217:     return
218:         t1.m_seconds == t2.m_seconds &&
219:         t1.m_minutes == t2.m_minutes &&
220:         t1.m_hours == t2.m_hours;
221: }
222: 
223: bool operator!= (const Time& t1, const Time& t2)
224: {
225:     return ! (t1 == t2);
226: }
227: 
228: bool operator<= (const Time& t1, const Time& t2)
229: {
230:     return t1 < t2 || t1 == t2;
231: }
232: 
233: bool operator<  (const Time& t1, const Time& t2)
234: {
235:     if (t1.m_hours < t2.m_hours)
236:         return true;
237: 
238:     if (t1.m_hours == t2.m_hours && t1.m_minutes < t2.m_minutes)
239:         return true;
240: 
241:     if (t1.m_hours == t2.m_hours && t1.m_minutes == t2.m_minutes && t1.m_seconds < t2.m_seconds)
242:         return true;
243: 
244:     return false;
245: }
246: 
247: bool operator>= (const Time& t1, const Time& t2)
248: {
249:     return ! (t1 < t2);
250: }
251: 
252: bool operator>  (const Time& t1, const Time& t2)
253: {
254:     return ! (t1 <= t2);
255: }
256: 
257: // conversion operator
258: Time::operator int()
259: {
260:     return TimeToSeconds();
261: }
262: 
263: // input / output
264: istream& operator>> (istream& is, Time& t)
265: {
266:     cout << "Hours [hh]: ";
267:     is >> t.m_hours;
268:     cout << "Minutes [mm]: ";
269:     is >> t.m_minutes;
270:     cout << "Seconds [ss]: ";
271:     is >> t.m_seconds;
272: 
273:     return is;
274: }
275: 
276: ostream& operator<< (ostream& os, const Time& t)
277: {
278:     os << setw(2) << setfill('0') << t.m_hours << ":";
279:     os << setw(2) << setfill('0') << t.m_minutes << ":";
280:     os << setw(2) << setfill('0') << t.m_seconds;
281: 
282:     return os;
283: }
284: 
285: // helper methods
286: int Time::TimeToSeconds ()
287: {
288:     return m_hours * 3600 + m_minutes * 60 + m_seconds;
289: }
290: 
291: void Time::SecondsToTime (int seconds)
292: {
293:     m_hours = seconds / 3600;
294:     seconds = seconds % 3600;
295:     m_minutes = seconds / 60;
296:     m_seconds = seconds % 60;
297: }

Beispiel 2. Klasse Time: Implementierung.