forked from pezy/CppPrimer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ex14_24.h
190 lines (172 loc) · 5.8 KB
/
ex14_24.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
/***************************************************************************
* @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.
//!
#ifndef DATE_H
#define DATE_H
#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif
#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);
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