This is a simple class that represents a calendar date. Of particular
interest is: 1) shows how to use static members in a class
and 2) shows how to use string streams to handle multiple forms of user
input gracefully.
1// date.h
2// Author: t a y l o r@msoe.edu and sections 2 and 6 of the
3// MSOE Spring 2001 CS183 course
4// Date: 3-27-2001
5// Purpose: Defines a Date class which represents calendar dates.
6// Modifications:
7// 3-29-2001, t a y l o r@msoe.edu Added postfix increment and decrement,
8// insertion, and extraction operators
9// Changed numDays from a vector to a static array
10// Added monthNames static array
11// Added lastDayOfMonth, niceRead, niceDisplay
12// functions
13// 9-26-2001, t a y l o r@msoe.edu Made leapYear() and valid() functions static
14
15#ifndef DATE_H
16#define DATE_H
17
18#include <fstream>
19using std::ostream;
20using std::istream;
21
22class Date {
23public:
24 // Default constructor
25 Date();
26
27 // Constructor that is passed the month, day, and year
28 // Assigns default date if passed an invalid date [9-26-01-CCT]
29 Date(unsigned int mn, unsigned int day, int yr);
30
31 // Copy constructor
32 Date(const Date& rhs);
33
34 // Assignment operator
35 Date& operator=(const Date& rhs);
36
37 // Destructor
38 ~Date();
39
40 // Accessors to get the month, day, and year
41 unsigned int getMonth() const;
42 unsigned int getDay() const;
43 int getYear() const;
44
45 // Mutator to set the month, day, and year of the call date object
46 // Does not modify the date if an invalid date is passed [9-26-01-CCT]
47 bool setDate(unsigned int mn, unsigned int dy, int yr);
48
49 // Prefix increment operator that advances the date by one day
50 Date& operator++();
51
52 // Postfix increment operator that advances the date by one day
53 Date operator++(int); // [3-29-01-CCT]
54
55 // Prefix decrement operator that advances the date by one day
56 Date& operator--();
57
58 // Postfix decrement operator that advances the date by one day
59 Date operator--(int); // [3-29-01-CCT]
60
61 // Sends object data to the output stream in the following format:
62 // 11-23-2000
63 void display(ostream& os) const;
64
65 // Sends object data to the output stream in the following format:
66 // November 23, 2000
67 void niceDisplay(ostream& os) const; // [3-29-01-CCT]
68
69 // Reads a date from the input stream. The date must be in the following
70 // form: mm?dd?yyyy where mm is the month, dd is the day, and yyyy is the
71 // year. The ? can be any character.
72 bool read(istream& is);
73
74 // Reads a date from the input stream. The date must be in either of
75 // the following forms: 11?23?2000
76 // or November 23? 2000 where ? can be any character
77 bool niceRead(istream& is); // [3-29-01-CCT]
78
79private:
80 unsigned int month;
81 unsigned int day;
82 int year;
83 static const unsigned int numDays[]; // [3-29-01-CCT]
84
85 static const char* monthNames[]; // [3-29-01-CCT]
86
87 // Returns true if the date occurs in a leap year
88 static bool leapYear(int yr); // [9-26-01-CCT]
89
90 // Returns true if the date is a valid date
91 static bool valid(unsigned int mn, unsigned int dy, int yr); // [9-26-01-CCT]
92
93 // Returns true if the date is on the last day of the month
94 bool lastDayOfMonth() const; // [3-29-01-CCT]
95};
96
97// Stream insertion and extraction operators
98ostream& operator<<(ostream& os, const Date& date);// [3-29-01-CCT]
99istream& operator>>(istream& is, Date& date); // [3-29-01-CCT]
100
101#endif
1// date.cpp
2// Author: t a y l o r@msoe.edu and sections 2 and 6 of the
3// MSOE Spring 2001 CS183 course
4// Date: 3-27-2001
5// Purpose: Defines a Date class which represents calendar dates.
6// Modifications:
7// 3-29-2001, t a y l o r@msoe.edu Added postfix increment and decrement,
8// insertion, and extraction operators
9// Changed numDays from a vector to a static array
10// Added monthNames static array
11// Added lastDayOfMonth, niceRead, niceDisplay
12// functions
13// 9-26-2001, t a y l o r@msoe.edu Made leapYear() and valid() functions static
14// Changed error handling for incorrect date
15// assignment so that it retains its old date
16// instead of "assert"ing
17// Removed implemenation of decrement operators
18// 10-15-2002, t a y l o r@msoe.edu Added self-assignment check to operator=
19
20#include "date.h"
21#include <string>
22#include <cassert>
23#include <iostream>
24using std::cout;
25using std::endl;
26using std::string;
27
28// Initialize and set value for the numDays and monthName arrays
29// Notice that this is done in the date.cpp file outside of any
30// functions.
31const unsigned int Date::numDays[] = {0, 31, 28, 31, 30, 31, 30,
32 31, 31, 30, 31, 30, 31};
33const char* Date::monthNames[] = {"", "January", "February", "March",
34 "April", "May", "June", "July",
35 "August", "September", "October",
36 "November", "December"};
37
38
39// t a y l o r@msoe.edu and CS183 class, 3-27-01
40// Modified 3-29-01, t a y l o r@msoe.edu: Used initializer list, removed numDays
41// vector stuff
42// Modified 9-26-01, t a y l o r@mose.edu: Now creates a default value when
43// an invalid date is entered
44Date::Date(unsigned int mn, unsigned int dy, int yr) : month(mn), day(dy),
45 year(yr)
46{
47 if(!valid(mn, dy, yr)) {
48 Date temp;
49 *this = temp;
50 }
51}
52
53
54// t a y l o r@msoe.edu and CS183 class, 3-27-01
55// Modified 3-29-01, used initializer list, removed numDays vector stuff
56Date::Date() : month(1), day(1), year(2001)
57{
58 // Nothing else to do
59}
60
61
62// t a y l o r@msoe.edu and CS183 class, 3-27-01
63// Modified 3-29-01, t a y l o r@msoe.edu: Used initializer list, removed
64// numDays vector stuff
65Date::Date(const Date& rhs) : month(rhs.month), day(rhs.day),
66 year(rhs.year)
67{
68 // Nothing else to do
69}
70
71// t a y l o r@msoe.edu, 3-27-01
72Date::~Date()
73{
74 // Nothing to do
75}
76
77
78// t a y l o r@msoe.edu and CS183 class, 3-27-01
79// Modified 10-15-02, t a y l o r@msoe.edu: added self-assignment check
80Date& Date::operator=(const Date& rhs)
81{
82 if(this!=&rhs) {
83 month = rhs.month;
84 day = rhs.day;
85 year = rhs.year;
86 }
87 return *this;
88}
89
90
91// t a y l o r@msoe.edu and CS183 class, 3-27-01
92unsigned int Date::getMonth() const
93{
94 return month;
95}
96
97
98// t a y l o r@msoe.edu and CS183 class, 3-27-01
99unsigned int Date::getDay() const
100{
101 return day;
102}
103
104
105// t a y l o r@msoe.edu and CS183 class, 3-27-01
106int Date::getYear() const
107{
108 return year;
109}
110
111
112// t a y l o r@msoe.edu, 3-27-01
113// Modified: 9-26-01, t a y l o r@msoe.edu: Rewrote using new valid() function
114bool Date::setDate(unsigned int mn, unsigned int dy, int yr)
115{
116 bool successful = valid(mn, dy, yr);
117 if(successful) {
118 month = mn;
119 day = dy;
120 year = yr;
121 }
122 return successful;
123}
124
125
126// t a y l o r@msoe.edu and CS183 class, 3-29-01
127Date& Date::operator++()
128{
129 if(lastDayOfMonth()) {
130 if(12==month) {
131 ++year;
132 month=1;
133 } else {
134 ++month;
135 }
136 day=1;
137 } else {
138 ++day;
139 }
140 return *this;
141}
Suppose today is a Date object
containing March 29, 2001. If I were to execute the following
line of code:
cout << ++today;
I would expect that March 30, 2001 would be sent to the console
output stream and that today would now contain
March 30, 2001. In order for March 30, 2001
to be sent to the console output stream, ++today must
evaluate to (i.e., return) a Date object with the value
of March 30, 2001. Basically, we want to return the new
value of today. We do this by making use of the
this pointer.
The this pointer is a pointer that points to the
object that called the member function that we are in (in this case,
operator++()). We want to return the object (not a
pointer to the object) that called operator++(), so
we need to dereference the pointer. Hence, we return
*this.
|
142
143
144
145// t a y l o r@msoe.edu, 3-29-01
146Date Date::operator++(int)
147{
148 Date temp=*this;
149 ++(*this);
150 return temp;
151}
152
153
154// t a y l o r@msoe.edu and CS183 class, 3-29-01
155// Modified: 9-26-01, t a y l o r@msoe.edu: removed implementation
156Date& Date::operator--()
157{
158 // This function doesn't work correctly
159 std::cerr << "Decrement is broken" << std::endl;
160 return *this;
161}
162
163
164// t a y l o r@msoe.edu, 3-29-01
165// Modified: 9-26-01, t a y l o r@msoe.edu: removed implementation
166Date Date::operator--(int)
167{
168 std::cerr << "Decrement is broken" << std::endl;
169 return *this;
170}
171
172
173// t a y l o r@msoe.edu, 3-29-01
174void Date::display(ostream& os) const
175{
176 os << month << '-' << day << '-' << year;
177}
178
179
180// t a y l o r@msoe.edu, 3-29-01
181void Date::niceDisplay(ostream& os) const
182{
183 os << monthNames[month] << ' ' << day << ", " << year;
184}
185
186
187// t a y l o r@msoe.edu, 3-29-01
188bool Date::read(istream& is)
189{
190 char separator;
191 unsigned int mn;
192 unsigned int dy;
193 int yr;
194 bool successful = false;
195 if(is>>mn>>separator>>dy>>separator>>yr) {
196 successful = setDate(mn,dy,yr);
197 }
198 return successful;
199}
200
201
202// t a y l o r@msoe.edu, 3-29-01
203bool Date::niceRead(istream& is)
204{
205 char separator;
206 string strmn;
207 unsigned int mn;
208 unsigned int dy;
209 int yr;
210 bool successful = false;
211 if(is>>mn) {
212 if(is>>separator>>dy>>separator>>yr) {
213 successful = setDate(mn,dy,yr);
214 }
215 } else {
216 is.clear(); // Clear the error flag in the stream so that it can be read from
217 if(is>>strmn>>dy>>separator>>yr) {
218 // This for loop is a bit strange. Notice that it ends with a semicolon.
219 // so there is no body to the loop. It just keeps looking through the
220 // array of names to see if there is a match with strmn. When it finds
221 // a match, it stops (and i is the correct month). If no match is
222 // found, it ends when i=13 (an invalid value that will make the
223 // setDate function return false.
224 unsigned int i=1;
225 for(; i<=12 && monthNames[i]!=strmn; ++i);
226 successful = setDate(i,dy,yr);
227 }
228 }
229 return successful;
230}
231
232
233// t a y l o r@msoe.edu, 3-29-01
234bool Date::leapYear(int yr)
235{
236 bool isLeap=false;
237 if(0==yr%400 || (0!=yr%100 && 0==yr%4) ) {
238 isLeap = true;
239 }
240 return isLeap;
241}
242
243
244// t a y l o r@msoe.edu, 3-29-01
245bool Date::lastDayOfMonth() const
246{
247 bool isLastDay = (numDays[month]==day);
248 if(month==2 && leapYear(year)) {
249 isLastDay = (29==day);
250 }
251 return isLastDay;
252}
253
254
255// t a y l o r@msoe.edu, 9-26-01
256bool Date::valid(unsigned int mn, unsigned int dy, int yr)
257{
258 bool isValid = false;
259 if(0!=dy && (1<=mn && mn<=12) &&
260 (dy<=numDays[mn] || (2==mn && 29==dy && leapYear(yr)))) {
261 isValid = true;
262 }
263 return isValid;
264}
265
266
267// t a y l o r@msoe.edu, 3-29-01
268ostream& operator<<(ostream& os, const Date& date)
269{
270 date.niceDisplay(os);
271 return os;
272}
273
274
275// t a y l o r@msoe.edu, 3-29-01
276istream& operator>>(istream& is, Date& date)
277{
278 date.niceRead(is);
279 return is;
280}