forked from jieniyimiao/CppPrimer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ex14_49.h
212 lines (191 loc) · 5.94 KB
/
ex14_49.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
/***************************************************************************
* @file date.h
* @author Alan.W
* @date 15-17 JAN 2014
* @remark
***************************************************************************/
//!
//! Exercise 7.40:
//! Choose one of the following abstractions (or an abstraction of your own choosing).
//! Determine what data are needed in the class. Provide an appropriate set of constructors.
//! Explain your decisions.
//!
//! Exercise 14.5:
//! In exercise 7.40 from § 7.5.1 (p. 291) you wrote a sketch of one of the
//! following classes. Decide what, if any, overloaded operators your class
//! should provide.
// - = < > <= >= ++ -- << >> == != += -=
//! Exercise 14.8:
//! Define an output operator for the class you chose in exercise 7.40 from
//! § 7.5.1 (p. 291).
//!
//! Exercise 14.12:
//! Define an input operator for the class you used in exercise 7.40 from
//! § 7.5.1 (p. 291). Be sure the operator handles input errors.
//!
//! Exercise 14.15:
//! Should the class you chose for exercise 7.40 from § 7.5.1 (p. 291)
//! define any of the arithmetic operators? If so, implement them.
//! If not, explain why not.
//!
// arithmetic operators : all non-members
// + : Date + Size
// - : Date - Size
// - : Date - Date
//!
//! Exercise 14.17:
//! Should the class you chose for exercise 7.40 from § 7.5.1 (p. 291) define
//! the equality operators? If so, implement them. If not, explain why not.
//!
//! Exercise 14.19:
//! Should the class you chose for exercise 7.40 from § 7.5.1 (p. 291) define
//! the relational operators? If so, implement them. If not, explain why not.
//!
//! Exercise 14.25:
//! Implement any other assignment operators your class should define.
//! Explain which types should be used as operands and why.
//!
//! Exercise 14.49:
//! Regardless of whether it is a good idea to do so, define a conversion to bool
//! for the class from the previous exercise.
//!
#ifndef DATE_H
#define DATE_H
#include <iostream>
#include <vector>
class Date
{
friend bool operator ==(const Date& lhs, const Date& rhs);
friend bool operator < (const Date &lhs, const Date &rhs);
friend bool check(const Date &d);
friend std::ostream& operator <<(std::ostream& os, const Date& d);
public:
typedef std::size_t Size;
//! default constructor
Date() = default;
//! constructor taking Size as days
explicit Date(Size days);
//! constructor taking three Size
Date(Size d, Size m, Size y) : day(d), month(m), year(y) { }
//! constructor taking iostream
Date(std::istream &is, std::ostream &os);
//! copy constructor
Date(const Date& d);
//! move constructor
Date(Date&& d) noexcept;
//! copy operator=
Date& operator= (const Date& d);
//! move operator=
Date& operator= (Date&& rhs) noexcept;
//! destructor -- in this case, user-defined destructor is not nessary.
~Date(){ std::cout << "destroying\n"; }
//! members
Size toDays() const; //not implemented yet.
Date& operator +=(Size offset);
Date& operator -=(Size offset);
explicit operator bool() { return (year<4000) ? true : false; }
private:
Size day = 1;
Size month = 1;
Size year = 0;
};
static const Date::Size YtoD_400 = 146097; //365*400 + 400/4 -3 == 146097
static const Date::Size YtoD_100 = 36524; //365*100 + 100/4 -1 == 36524
static const Date::Size YtoD_4 = 1461; //365*4 + 1 == 1461
static const Date::Size YtoD_1 = 365; //365
//! normal year
static const std::vector<Date::Size> monthsVec_n =
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//! leap year
static const std::vector<Date::Size> monthsVec_l =
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
//! non-member operators: << >> - == != < <= > >=
//!
std::ostream&
operator <<(std::ostream& os, const Date& d);
std::istream&
operator >>(std::istream& is, Date& d);
int
operator - (const Date& lhs, const Date& rhs);
bool
operator ==(const Date& lhs, const Date& rhs);
bool
operator !=(const Date& lhs, const Date& rhs);
bool
operator < (const Date& lhs, const Date& rhs);
bool
operator <=(const Date& lhs, const Date& rhs);
bool
operator >(const Date& lhs, const Date& rhs);
bool
operator >=(const Date& lhs, const Date& rhs);
Date
operator - (const Date& lhs, Date::Size rhs);
Date
operator +(const Date& lhs, Date::Size rhs);
//! utillities:
bool check(const Date &d);
inline bool
isLeapYear(Date::Size y);
//! check if the date object passed in is valid
inline bool
check(const Date &d)
{
if(d.month==0 || d.month >12)
return false;
else
{
//! month == 1 3 5 7 8 10 12
if(d.month==1 || d.month==3 || d.month==5 || d.month==7 ||
d.month==8 || d.month==10|| d.month==12)
{
if(d.day==0 || d.day > 31) return false;
else
return true;
}
else
{
//! month == 4 6 9 11
if(d.month==4 || d.month==6 || d.month==9 || d.month==11)
{
if(d.day==0 || d.day > 30) return false;
else
return true;
}
else
{
//! month == 2
if(isLeapYear(d.year))
{
if(d.day==0 || d.day >29) return false;
else
return true;
}
else
{
if(d.day==0 || d.day >28) return false;
else
return true;
}
}
}
}
}
inline bool
isLeapYear(Date::Size y)
{
if (!(y%400))
{
return true;
}
else
{
if(!(y%100))
{
return false;
}
else
return !(y%4);
}
}
#endif // DATE_H