《C++ Primer》第14章 操作重载与类型转换
14.2节 输入和输出运算符 习题答案
练习14.6:为你的Sales_data类定义输出运算符。
【出题思路】
本题练习实现输出运算符。
【解答】
输出运算符将Sales_data的数据成员依次写到指定输出流中即可。
#ifndef SALES_DATA14_06_H
#define SALES_DATA14_06_H
#include <iostream>
#include <string>
class Sales_data
{
friend std::istream& operator>>(std::istream&, Sales_data&);
friend std::ostream& operator<<(std::ostream&, const Sales_data&);
friend bool operator<(const Sales_data&, const Sales_data&);
friend bool operator==(const Sales_data&, const Sales_data&);
public:
Sales_data() = default;
Sales_data(const std::string &book): bookNo(book) { }
Sales_data(std::istream &is) { is >> *this; }
public:
Sales_data& operator+=(const Sales_data&);
std::string isbn() const { return bookNo; }
double avg_price() const;
private:
std::string bookNo; //书号
unsigned units_sold = 0; //出售册数
double revenue = 0.0; //收入
};
inline bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
return lhs.isbn() == rhs.isbn();
}
Sales_data operator+(const Sales_data&, const Sales_data&);
inline bool operator==(const Sales_data &lhs, const Sales_data &rhs)
{
return (lhs.units_sold == rhs.units_sold) &&
(lhs.revenue == rhs.revenue) &&
(lhs.isbn() == rhs.isbn());
}
inline bool operator !=(const Sales_data &lhs, const Sales_data &rhs)
{
return !(lhs == rhs);
}
Sales_data& Sales_data::operator +=(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
Sales_data operator +(const Sales_data& lhs, const Sales_data& rhs)
{
Sales_data ret(lhs);
ret += rhs;
return ret;
}
std::istream& operator>>(std::istream& in, Sales_data& s)
{
double price;
in >> s.bookNo >> s.units_sold >> price;
if(in)
s.revenue = s.units_sold * price;
else
s = Sales_data();
return in;
}
std::ostream& operator <<(std::ostream& out, const Sales_data& s)
{
const char sep = '\t';
out << "\n\t" << s.isbn() << sep << s.units_sold << sep
<< s.revenue << sep << s.avg_price();
return out;
}
double Sales_data::avg_price() const
{
if(units_sold)
return revenue / units_sold;
else
return 0;
}
#endif // SALES_DATA14_06_H
#include "Sales_data14_06.h"
#include <iostream>
using namespace std;
int main()
{
Sales_data trans1, trans2;
std::cout << "请输入两条ISBN相同的销售记录:" << std::endl;
std::cin >> trans1 >> trans2;
if(compareIsbn(trans1, trans2))
std::cout << "汇总信息:ISBN,售出本数,销售额和平均售价为: " << trans1 + trans2 << std::endl;
else
std::cout << "两条销售记录的ISBN不同" << std::endl;
cout << "Hello World!" << endl;
return 0;
}
运行结果:
练习14.7:你在13.5节的练习(第470页)中曾经编写了一个String类,为它定义一个输出运算符。
【出题思路】
本题练习实现输出运算符。
【解答】
将字符指针成员写入输入流即可,默认的char *的输出运算符会打印保存其中的C风格字符串。
#include <iostream>
using namespace std;
class String
{
friend ostream& operator<<(ostream &os, const String &Str);
public:
String() { }
String(char *cStr):str(cStr)
{
}
private:
char *str;
};
ostream& operator<<(ostream &os, const String &Str)
{
std::cout << Str.str;
return os;
}
int main()
{
char temp[] = "字符串测试========";
String sStr(temp);
cout << sStr << endl;
return 0;
}
运行结果:字符串测试========
练习14.8:你在7.5.1节的练习7.40(第261页)中曾经选择并编写了一个类,为它定义一个输出运算符。
【解答】
#include <iostream>
#include <string>
using namespace std;
class Employee
{
friend ostream& operator<<(ostream &os, const Employee &emp);
public:
Employee();
Employee(string name, int age, string sex)
{
m_name = name;
m_age = age;
m_sex = sex;
}
private:
string m_name;
int m_age;
string m_sex;
};
std::ostream& operator<<(ostream& os, const Employee& emp)
{
const char sep = '\t';
os << "姓名:" << emp.m_name << sep << "年龄:" << emp.m_age << sep << "性别:" << emp.m_sex << endl;
return os;
}
int main()
{
Employee employee("天山云海路", 28, "男");
cout << "employee==========" << employee << endl;
return 0;
}
运行结果:
employee==========姓名:天山云海路 年龄:28 性别:男
练习14.9:为你的Sales_data类定义输入运算符。
【出题思路】
本题练习实现输入运算符。
【解答】
输入运算符从给定输入流读取对应类型的对象,存入Sales_data的数据成员中。与输出不同,输入通常要进行一些正确性的判定,并进行相应处理。
#ifndef SALES_DATA14_09_H
#define SALES_DATA14_09_H
#include <iostream>
#include <string>
class Sales_data
{
friend std::istream& operator>>(std::istream&, Sales_data&);
friend std::ostream& operator<<(std::ostream&, const Sales_data&);
friend bool operator<(const Sales_data&, const Sales_data&);
friend bool operator==(const Sales_data&, const Sales_data&);
public:
Sales_data() = default;
Sales_data(const std::string &book): bookNo(book) { }
Sales_data(std::istream &is) { is >> *this; }
public:
Sales_data& operator+=(const Sales_data&);
std::string isbn() const { return bookNo; }
double avg_price() const;
private:
std::string bookNo; //书号
unsigned units_sold = 0; //出售册数
double revenue = 0.0; //收入
};
inline bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)
{
return lhs.isbn() == rhs.isbn();
}
Sales_data operator+(const Sales_data&, const Sales_data&);
inline bool operator==(const Sales_data &lhs, const Sales_data &rhs)
{
return (lhs.units_sold == rhs.units_sold) &&
(lhs.revenue == rhs.revenue) &&
(lhs.isbn() == rhs.isbn());
}
inline bool operator !=(const Sales_data &lhs, const Sales_data &rhs)
{
return !(lhs == rhs);
}
Sales_data& Sales_data::operator +=(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
Sales_data operator +(const Sales_data& lhs, const Sales_data& rhs)
{
Sales_data ret(lhs);
ret += rhs;
return ret;
}
std::istream& operator>>(std::istream& in, Sales_data& item)
{
double price;
in >> item.bookNo >> item.units_sold >> price;
if(in)
item.revenue = item.units_sold * price;
else
item = Sales_data();
return in;
}
std::ostream& operator <<(std::ostream& out, const Sales_data& s)
{
const char sep = '\t';
out << "\n\t" << s.isbn() << sep << s.units_sold << sep
<< s.revenue << sep << s.avg_price();
return out;
}
double Sales_data::avg_price() const
{
if(units_sold)
return revenue / units_sold;
else
return 0;
}
#endif // SALES_DATA14_09_H
#include "Sales_data14_09.h"
#include <iostream>
using namespace std;
int main()
{
Sales_data trans;
std::cout << "请输入1条销售记录:" << std::endl;
std::cin >> trans;
std::cout << "销售记录:" << trans << std::endl;
cout << "Hello World!" << endl;
return 0;
}
运行结果:
练习14.10:对于Sales_data的输入运算符来说,如果给定了下面的输入将发生什么情况?
(a) 0-201-99999-9 10 24.95 (b) 10 24.95 0-210-99999-9
【出题思路】
理解重载运算符的工作过程。
【解答】
(a)参数中传入的Sales_data对象将会得到输入的值,其中bookNo、units_sold、price的值分别是:0-201-99999-9、10、24.95,同时revenue的值是249.5。
(b)输入错误,参数中传入的Sales_data对象将会得到默认值。
练习14.11:下面的Sales_data输入运算符存在错误吗?如果有,请指出来。对于这个输入运算符如果仍然给定上一个练习的输入将发生什么情况?
istream& operator>>(istream& in, Sales_data& s)
{
double price;
in >> s.bookNo >> s.units_sold >> price;
s.revenue = s.units_sold * price;
return in;
}
【出题思路】
理解输入运算符通常要判断输入数据的正确性。
【解答】
这个实现没有判断输入数据的正确性,是错误的。
(a)如果输入的是0-201-99999-9 10 24.95,程序将会正常执行,Sales_data对象得到正确的值。
(b)如果输入的是10 24.95 0-210-99999-9,bookNo、units_sold、price将会得到错误的值,分别是:10,24,0.95,而revenue的值是:24 * 0.95 =22.8。这显然跟我们的预期结果是不一样的。
练习14.12:你在7.5.1节的练习7.40(第261页)中曾经选择并编写了一个类,为它定义一个输入运算符并确保该运算符可以处理输入错误。
【出题思路】
本题练习判断输入数据的正确性。
【解答】
#include <iostream>
using namespace std;
class Date
{
friend std::istream& operator>>(std::istream&, Date&);
friend ostream& operator<<(ostream &os, const Date &dt);
public:
Date()
{
}
Date(int y, int m, int d)
{
year = y;
month = m;
day = d;
}
private:
int year;
int month;
int day;
};
istream& operator>>(std::istream& is, Date& inDt)
{
is >> inDt.year >> inDt.month >> inDt.day;
if(!is)
{
inDt = Date(0, 0, 0);
cout << "input data error====================" << endl;
}
return is;
}
ostream& operator<<(ostream& os, const Date& d)
{
const char sep = '\t';
os << "year:" << d.year << sep << "month:" << d.month << sep << "day:" << d.day << endl;
return os;
}
int main()
{
Date date;
std::cin >> date;
cout << "date==========" << date << endl;
cout << "Hello World!" << endl;
return 0;
}
运行结果: