update to Exercise 7.15.
This commit is contained in:
@@ -65,7 +65,7 @@ Because in `read`, the `Sales_data` object will be modified. While in `print`, t
|
||||
|
||||
> Exercise 7.9: Add operations to `read` and `print` Person objects to the code you wrote for the exercises in § 7.1.2 (p. 260).
|
||||
|
||||
```
|
||||
```cpp
|
||||
istream& read(istream &is, Person &person){
|
||||
is >> person.name >> person.address;
|
||||
return is;
|
||||
@@ -81,3 +81,92 @@ ostream& print(ostream &os, Person const &person){
|
||||
`if (read(read(cin, data1), data2))`
|
||||
|
||||
Take in two objects(data1 and data2) at the same time, and step into the `if` block only when both objects are valid.
|
||||
|
||||
> Exercise 7.11: Add constructors to your Sales_data class and write a program to use each of the constructors.
|
||||
|
||||
[exercise7_11.h](exercise7_11.h)
|
||||
[exercise7_11.cpp](exercise7_11.cpp)
|
||||
|
||||
> Exercise 7.12: Move the definition of the Sales_data constructor that takes an istream into the body of the Sales_data class.
|
||||
|
||||
```cpp
|
||||
struct Sales_data {
|
||||
string bookNo;
|
||||
unsigned units_sold = 0;
|
||||
double revenue = 0.0;
|
||||
|
||||
//constructors
|
||||
Sales_data() = default;
|
||||
Sales_data(istream &is){
|
||||
double price;
|
||||
is << bookNo << units_sold << price;
|
||||
revenue = price * units_sold;
|
||||
}
|
||||
Sales_data(string isbn) : bookNo(isbn) {};
|
||||
Sales_data(string isbn, unsigned n, double price) : bookNo(isbn), units_sold(n), revenue(n * price) {};
|
||||
|
||||
string isbn() const { return bookNo; }
|
||||
double avg_price() const { return revenue / units_sold; }
|
||||
Sales_data& combine(Sales_data const &data); //behave same as the `+=` operator, thus return a left-value
|
||||
};
|
||||
```
|
||||
|
||||
> Exercise 7.13: Rewrite the program from page 255 to use the istream constructor.
|
||||
|
||||
```cpp
|
||||
int main(){
|
||||
Sales_data total(cin); // variable to hold the running sum
|
||||
if (cin) { // read the first transaction
|
||||
Sales_data trans(cin); // variable to hold data for the next transaction
|
||||
while (cin) { // read the remaining transactions
|
||||
if (total.isbn() == trans.isbn()) // check the isbns
|
||||
total.combine(trans); // update the running total
|
||||
else {
|
||||
print(cout, total) << endl; // print the results
|
||||
total = trans; // process the next book
|
||||
}
|
||||
trans = Sales_data(cin);
|
||||
}
|
||||
print(cout, total) << endl; // print the last transaction
|
||||
}
|
||||
else { // there was no input
|
||||
cerr << "No data?!" << endl; // notify the user
|
||||
}
|
||||
|
||||
system("pause");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
This can be weird, for the `cin` operation is seperated from the `if-condition`.
|
||||
|
||||
> Exercise 7.14: Write a version of the default constructor that explicitly initializes the members to the values we have provided as in-class initializers.
|
||||
|
||||
```cpp
|
||||
struct Sales_data {
|
||||
string bookNo;
|
||||
unsigned units_sold;
|
||||
double revenue;
|
||||
|
||||
//constructors
|
||||
Sales_data(){units_sold = 0, revenue = 0.0;}
|
||||
Sales_data(istream &is){
|
||||
double price;
|
||||
is << bookNo << units_sold << price;
|
||||
revenue = price * units_sold;
|
||||
}
|
||||
Sales_data(string isbn) : bookNo(isbn) {};
|
||||
Sales_data(string isbn, unsigned n, double price) : bookNo(isbn), units_sold(n), revenue(n * price) {};
|
||||
|
||||
string isbn() const { return bookNo; }
|
||||
double avg_price() const { return revenue / units_sold; }
|
||||
Sales_data& combine(Sales_data const &data); //behave same as the `+=` operator, thus return a left-value
|
||||
};
|
||||
```
|
||||
|
||||
But there's a drawback in this manner. For example, in constructor3, `Sales_data(string isbn)`, we also have to explicitly initializes all the members, which causes redundance.
|
||||
|
||||
> Exercise 7.15: Add appropriate constructors to your Person class.
|
||||
|
||||
[exercise7_15.h](exercise7_15.h)
|
||||
[exercise7_15.cpp](exercise7_15.cpp)
|
||||
|
||||
43
c++ note/chp7/exercise7_11.cpp
Normal file
43
c++ note/chp7/exercise7_11.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
//test constructors
|
||||
#include "exercise7_11.h"
|
||||
#include <cassert>
|
||||
|
||||
using std::cin;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
|
||||
void test_constructor();
|
||||
|
||||
int main(){
|
||||
test_constructor();
|
||||
|
||||
system("pause");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_constructor(){
|
||||
//test default constructor
|
||||
Sales_data data1;
|
||||
assert(data1.units_sold == 0);
|
||||
assert(data1.revenue == 0.0);
|
||||
|
||||
//test constructor2
|
||||
Sales_data data2(cin); // cin >> 123456789 2 20.5
|
||||
assert(data2.bookNo == "123456789");
|
||||
assert(data2.revenue == 41.0);
|
||||
assert(data2.units_sold == 2);
|
||||
|
||||
//test constructor3
|
||||
Sales_data data3("123456789");
|
||||
assert(data3.bookNo == "123456789");
|
||||
assert(data3.revenue == 0.0);
|
||||
assert(data3.units_sold == 0);
|
||||
|
||||
//test constructor4
|
||||
Sales_data data4("123456789", 2, 20.5);
|
||||
assert(data4.bookNo == "123456789");
|
||||
assert(data4.revenue == 41.0);
|
||||
assert(data4.units_sold == 2);
|
||||
|
||||
cout << "All tests passed." << endl;
|
||||
}
|
||||
61
c++ note/chp7/exercise7_11.h
Normal file
61
c++ note/chp7/exercise7_11.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef EXERCISE7_11_H_
|
||||
#define EXERCISE7_11_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
|
||||
struct Sales_data {
|
||||
string bookNo;
|
||||
unsigned units_sold;
|
||||
double revenue;
|
||||
|
||||
//constructors
|
||||
Sales_data() { units_sold = 0, revenue = 0.0; }
|
||||
Sales_data(istream &is);
|
||||
Sales_data(string isbn) : bookNo(isbn) {};
|
||||
Sales_data(string isbn, unsigned n, double price) : bookNo(isbn), units_sold(n), revenue(n * price) {};
|
||||
|
||||
string isbn() const { return bookNo; }
|
||||
double avg_price() const { return revenue / units_sold; }
|
||||
Sales_data& combine(Sales_data const &data); //behave same as the `+=` operator, thus return a left-value
|
||||
};
|
||||
|
||||
//constructors
|
||||
Sales_data::Sales_data(istream &is){
|
||||
double price;
|
||||
is >> bookNo >> units_sold >> price;
|
||||
revenue = price * units_sold;
|
||||
}
|
||||
|
||||
Sales_data& Sales_data::combine(Sales_data const &data) {
|
||||
units_sold += data.units_sold;
|
||||
revenue += data.revenue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Sales_data add(Sales_data const &one, Sales_data const &two) {
|
||||
Sales_data res = one;
|
||||
return res.combine(two);
|
||||
}
|
||||
|
||||
istream& read(istream &is, Sales_data &data) {
|
||||
is >> data.bookNo;
|
||||
is >> data.units_sold;
|
||||
is >> data.revenue;
|
||||
return is;
|
||||
}
|
||||
|
||||
ostream& print(ostream &os, Sales_data const data) {
|
||||
os << "book number: " << data.bookNo << endl;
|
||||
os << "units sold: " << data.units_sold << endl;
|
||||
os << "total revenue: " << data.revenue << endl;
|
||||
os << "averge price: " << data.avg_price(); // no endl at the end
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif
|
||||
28
c++ note/chp7/exercise7_15.cpp
Normal file
28
c++ note/chp7/exercise7_15.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
// test construtors
|
||||
#include "exercise7_15.h"
|
||||
#include <cassert>
|
||||
|
||||
using std::cout;
|
||||
using std::cin;
|
||||
using std::endl;
|
||||
|
||||
int main(){
|
||||
//test constructorss
|
||||
Person person1;
|
||||
// here we see non-builtin type(such as string) would not have undefined value
|
||||
assert(person1.getAddr() == string());
|
||||
assert(person1.getName() == string());
|
||||
|
||||
Person person2("shine", "shanghai");
|
||||
// and string can directly be compare with literal character string
|
||||
assert(person2.getName() == "shine");
|
||||
assert(person2.getAddr() == string("shanghai"));
|
||||
|
||||
Person person3(cin); // cin >> shine >> shanghai;
|
||||
assert(person2.getName() == "shine");
|
||||
assert(person2.getAddr() == string("shanghai"));
|
||||
|
||||
cout << "All tests passed." << endl;
|
||||
system("pause");
|
||||
return 0;
|
||||
}
|
||||
38
c++ note/chp7/exercise7_15.h
Normal file
38
c++ note/chp7/exercise7_15.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef EXERCISE7_15_H_
|
||||
#define EXERCISE7_15_H_
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
using std::string;
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
|
||||
struct Person;
|
||||
|
||||
istream& read(istream &is, Person &person);
|
||||
ostream& print(ostream &os, Person const &person);
|
||||
|
||||
struct Person {
|
||||
string name;
|
||||
string address;
|
||||
|
||||
//construtors
|
||||
Person() = default;
|
||||
Person(istream& is) { read(is, *this); }
|
||||
Person(string name, string address) : name(name), address(address) {};
|
||||
|
||||
string getName() const { return name; }
|
||||
string getAddr() const { return address; }
|
||||
};
|
||||
|
||||
istream& read(istream &is, Person &person) {
|
||||
is >> person.name >> person.address;
|
||||
return is;
|
||||
}
|
||||
|
||||
ostream& print(ostream &os, Person const &person) {
|
||||
os << person.name << ' ' << person.address;
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user