练习7.1
使用2.6.1节定义的Sales_data类为1.6节的交易处理程序编写一个新版本。
见习题2.41。
练习7.2
曾在2.6.2节的练习中编写了一个Sales_data类,请向这个类添加combine函数和isbn成员。
#ifndef SALES_DATA_H_
#define SALES_DATA_H_
#include <string>
#include <iostream>
struct Sales_data
{
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
std::string isbn() const {
return bookNo;}
Sales_data& combine(const Sales_data&);
};
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
#endif
练习7.3
修改7.1.1节的交易处理程序,令其使用这些成员。
#include <iostream>
#include <string>
#include "Sales_data.h"
int main()
{
Sales_data total;
double totalPrice;
if (std::cin >> total.bookNo >> total.units_sold >> totalPrice)
{
total.revenue = total.units_sold * totalPrice;
Sales_data trans;
double transPrice;
while (std::cin >> trans.bookNo >> trans.units_sold >> transPrice)
{
trans.revenue = trans.units_sold * transPrice;
if (total.isbn() == trans.isbn())
{
total.combine(trans);
}
else
{
std::cout << total.bookNo << " " << total.units_sold << " " << total.revenue << " ";
if (total.units_sold != 0)
std::cout << total.revenue / total.units_sold << std::endl;
else
std::cout << "(no sales)" << std::endl;
total = trans;
}
}
std::cout << total.bookNo << " " << total.units_sold << " " << total.revenue << " ";
if (total.units_sold != 0)
std::cout << total.revenue / total.units_sold << std::endl;
else
std::cout << "(no sales)" << std::endl;
return 0;
}
else
{
std::cerr << "No data?!" << std::endl;
return -1; // indicate failure
}
}
练习7.4
编写一个名为Person的类,使其表示人员的姓名和地址。使用string对象存放这些元素,接下来的练习将不断充实这个类的其他特征。
#ifndef PERSON_H_
#define PERSON_H_
#include <string>
struct Person
{
std::string name;
std::string address;
};
#endif
练习7.5
在你的Person类中提供一些操作使其能够返回姓名和地址。这些函数是否应该是const的呢?解释原因。
应该是const,这两个成员函数只需读取成员对象,无需改变成员对象。
#ifndef PERSON_H_
#define PERSON_H_
#include <string>
struct Person
{
std::string name;
std::string address;
std::string get_name() const{
return name;}
std::string get_address() const{
return address;}
};
#endif
练习7.6
对于函数add、read和print,定义你自己的版本。
#ifndef SALES_DATA_H_
#define SALES_DATA_H_
#include <string>
#include <iostream>
struct Sales_data
{
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
std::string isbn() const {
return bookNo;}
Sales_data& combine(const Sales_data&);
double avg_price() const;
};
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
double Sales_data::avg_price() const
{
if(units_sold)
return revenue / units_sold;
else
return 0;
}
std::istream &read(std::istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
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;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
#endif
练习7.7
使用这些新函数重写7.1.2节练习中的程序。
#include <iostream>
#include <string>
#include "Sales_data_ex06.h"
int main()
{
Sales_data total;
if (read(std::cin, total))
{
Sales_data trans;
while (read(std::cin, trans))
{
if (total.isbn() == trans.isbn())
{
total.combine(trans);
}
else
{
print(std::cout, total);
std::cout << std::endl;
total = trans;
}
}
print(std::cout, total);
std::cout << std::endl;
return 0;
}
else
{
std::cerr << "No data?!" << std::endl;
return -1; // indicate failure
}
}
练习7.8
为什么read函数将其Sales_data参数定义成普通的引用,而print函数将其参数定义成常量引用?
因为read函数需要改变成员对象;而print只需读取成员对象。
练习7.9
对于7.1.2节练习中代码,添加读取和打印Person对象的操作。
#ifndef PERSON_H_
#define PERSON_H_
#include <string>
struct Person
{
std::string name;
std::string address;
std::string get_name() const{
return name;}
std::string get_address() const{
return address;}
};
std::istream &read(std::istream &is, Person &item)
{
return is >> item.name >> item.address;
}
std::ostream &print(std::ostream &os, const Person &item)
{
return os << item.name << " " << item.address;
}
#endif
练习7.10
在下面这条if语句中,条件部分的作用是什么?
if (read(read(cin, data1), data2))
读入data1和data2,并判断返回是否为真。
练习7.11
在你的Sales_data类中添加构造函数,然后编写一段程序令其用到每个构造函数。
Sales_data_ex11.h
#ifndef SALES_DATA_H_
#define SALES_DATA_H_
#include <string>
#include <iostream>
struct Sales_data
{
Sales_data() = default;
Sales_data(const std::string &s) : bookNo(s){
}
Sales_data(const std::string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n){
}
Sales_data(std::istream &);
std::string isbn() const {
return bookNo;}
Sales_data& combine(const Sales_data&);
double avg_price() const;
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
double Sales_data::avg_price() const
{
if(units_sold)
return revenue / units_sold;
else
return 0;
}
std::istream &read(std::istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
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;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
Sales_data::Sales_data(std::istream &is)
{
read(is, *this);
}
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
#endif
ex11.cpp
#include <string>
#include <iostream>
#include "Sales_data_ex11.h"
int main()
{
Sales_data sales_data1;
print(std::cout, sales_data1) << std::endl;
Sales_data sales_data2("1-01");
print(std::cout, sales_data2) << std::endl;
Sales_data sales_data3("1-01", 1, 100);
print(std::cout, sales_data3) << std::endl;
Sales_data sales_data4(std::cin);
print(std::cout, sales_data4) << std::endl;
// Sales_data sales_data5();
// print(std::cout, sales_data5) << std::endl;
return 0;
}
练习7.12
把只接受一个istream 作为参数的构造函数移到类的内部。
Sales_data_ex12.h
#ifndef SALES_DATA_H_
#define SALES_DATA_H_
#include <string>
#include <iostream>
struct Sales_data;
std::istream &read(std::istream &is, Sales_data &item);
std::ostream &print(std::ostream &os, const Sales_data &item);
Sales_data add(const Sales_data &lhs, const Sales_data &rhs);
struct Sales_data
{
Sales_data() = default;
Sales_data(const std::string &s) : bookNo(s){
}
Sales_data(const std::string &s, unsigned n, double p) :