forked from jaege/Cpp-Primer-5th-Exercises
-
Notifications
You must be signed in to change notification settings - Fork 0
/
14.21.cpp
164 lines (144 loc) · 4.26 KB
/
14.21.cpp
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
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <fstream>
#define USE_OPERATOR
/* Sales_data.h */
class Sales_data;
std::istream &read(std::istream &, Sales_data &);
class Sales_data {
#ifndef USE_OPERATOR
friend Sales_data add(const Sales_data &, const Sales_data &);
friend std::istream &read(std::istream &, Sales_data &);
friend std::ostream &print(std::ostream &, const Sales_data &);
#else
friend Sales_data operator+(const Sales_data &, const Sales_data &);
friend std::istream &operator>>(std::istream &, Sales_data &);
friend std::ostream &operator<<(std::ostream &, const Sales_data &);
#endif
public:
Sales_data() : Sales_data("", 0, 0.0) {}
explicit Sales_data(const std::string &no) : Sales_data(no, 0, 0.0) {}
Sales_data(const std::string &no, unsigned us, double price)
: bookNo(no), units_sold(us), revenue(price * us) {}
explicit Sales_data(std::istream &is) : Sales_data() { read(is, *this); }
#ifndef USE_OPERATOR
Sales_data &combine(const Sales_data &);
#else
Sales_data &operator+=(const Sales_data &);
#endif
std::string isbn() const { return bookNo; }
private:
double avg_price() const;
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
#ifdef USE_OPERATOR
Sales_data operator+(const Sales_data &, const Sales_data &);
std::istream &operator>>(std::istream &, Sales_data &);
std::ostream &operator<<(std::ostream &, const Sales_data &);
#endif
inline
double Sales_data::avg_price() const {
return units_sold ? revenue / units_sold : 0;
}
/* Sales_data.cpp */
bool compareIsbn(const Sales_data &sd1, const Sales_data &sd2) {
return sd1.isbn() < sd2.isbn();
}
#ifndef USE_OPERATOR
Sales_data &Sales_data::combine(const Sales_data &rhs) {
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs) {
Sales_data sum = lhs; // Use default copy constructor
sum.combine(rhs);
return sum;
}
std::istream &read(std::istream &is, Sales_data &item) {
double price;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = item.units_sold * price;
return is;
}
std::ostream &print(std::ostream &os, const Sales_data &item) {
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
#else
// By using operator+ do the actual addition, the statements in operator+
// remain same. But in operator+=, we will create a temporary object and call
// assignment operator, which leads to much more work than the other version.
Sales_data &Sales_data::operator+=(const Sales_data &rhs) {
*this = *this + rhs;
return *this;
}
Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs) {
Sales_data sum = lhs;
sum.units_sold += rhs.units_sold;
sum.revenue += rhs.revenue;
return sum;
}
std::istream &operator>>(std::istream &is, Sales_data &item) {
double price;
is >> item.bookNo >> item.units_sold >> price;
if (is)
item.revenue = item.units_sold * price;
else
item = Sales_data();
return is;
}
std::ostream &operator<<(std::ostream &os, const Sales_data &item) {
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
#endif
/* Test.cpp */
int main(int argc, char **argv) {
if (argc < 2) {
std::cerr << "Usage: 14.6 <input filename>" << std::endl;
return -1;
}
std::ifstream in(argv[1]);
if (!in) {
std::cerr << "Fail to open file: " << argv[1] << std::endl;
return -2;
}
std::vector<Sales_data> vsd;
#ifndef USE_OPERATOR
for (Sales_data sd; read(in, sd); vsd.push_back(sd)) {}
#else
for (Sales_data sd; in >> sd; vsd.push_back(sd)) {}
#endif
std::cout << "Before sort:\n";
for (const auto &sd : vsd)
#ifndef USE_OPERATOR
print(std::cout, sd) << std::endl;
#else
std::cout << sd << std::endl;
#endif
std::sort(vsd.begin(), vsd.end(), compareIsbn);
std::cout << "\nAfter sort:\n";
for (const auto &sd : vsd)
#ifndef USE_OPERATOR
print(std::cout, sd) << std::endl;
#else
std::cout << sd << std::endl;
#endif
#ifdef USE_OPERATOR
Sales_data s1("book1", 4, 2.5);
Sales_data s2("book1", 10, 1.5);
Sales_data s3;
s3 = s1 + s2;
std::cout << s3 << std::endl;
s3 += s1;
std::cout << s3 << std::endl;
#endif
return 0;
}