forked from jaege/Cpp-Primer-5th-Exercises
-
Notifications
You must be signed in to change notification settings - Fork 0
/
14.9.cpp
139 lines (122 loc) · 3.57 KB
/
14.9.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
#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 {
friend Sales_data add(const Sales_data &, const Sales_data &);
#ifndef USE_OPERATOR
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); }
Sales_data &combine(const Sales_data &);
#ifndef USE_OPERATOR
#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();
}
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;
}
#ifndef USE_OPERATOR
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
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
return 0;
}