2.5 自定义数据结构
练习39:编译下面的程序观察其运行结果,注意,如果忘记写类定义体后面的分号会发生什么情况?记录下相关信息,以后可能会有用。
struct Foo {/*此处为空*} //注意:没有分号
int main()
{
return 0;
}
【解答】
该程序无法编译通过,原因是缺少一个分号。因为类体后面可以紧跟变量名以示对该类型对象的定义,所以在类体右侧表示结束
的花括号后必须写一个分号。稍作修改,该程序就可以编译通过 了。
struct Foo {/*此处为空*};
int main()
{
return 0;
}
练习40:根据自已的理解写出Sales_data类,最好与书中的例子有所区别。
【解答】
原书中的程序包含3个数据成员,分别是bookNo(书籍编号)、units_sold(销售量)、revenue(销售收入),新设计的
Sales_data类细化了销售收入的计算方式,在保留bookNo和units_sold的基础上,新增了sellingprice(零售价、原价)、
saleprice(实售价、折扣价)、discount(折扣),其中discount=saleprice/sellingprice。
struct Sales_data{
std::string bookNo; //书籍编号
unsigned units_sold = 0; //销售量
double sellingprice = 0.0; //零售价
double saleprice = 0.0; //实售价
double discount = 0.0 //折扣
};
练习41:使用你自己的Sales_data类重写1.5.1节(第20页)、1.5.2节(第21页)和1.6节(第22页)的练习。眼下先把Sales_data类的定义和main函数放在同一个文件里。
#include <iostream>
#include <string>
using namespace std;
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: //构造函数的3种形式
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;
}
private:
std::string bookNo; //书籍编号,隐式初始化为空串
unsigned units_sold = 0; //销售量,显示初始化为0
double sellingprice = 0.0; //原始价格,显示初始化为0.0
double saleprice = 0.0; //实售价格,显示初始化为0.0
double discount = 0.0; //折扣,显示初始化为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.sellingprice == rhs.sellingprice && \
lhs.saleprice == rhs.saleprice && \
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;
saleprice = (rhs.saleprice * rhs.units_sold + saleprice * units_sold) \
/ (rhs.units_sold + units_sold);
if(sellingprice != 0)
discount = saleprice / sellingprice;
return *this;
}
Sales_data operator + (const Sales_data& lhs, const Sales_data& rhs)
{
Sales_data ret(lhs); //把lhs的内容拷贝到临时变量ret中,这种做法便于运算
ret += rhs; //把rhs的内容加入其中
return ret; //返回ret
}
std::istream& operator >> (std::istream& in, Sales_data& s)
{
in >> s.bookNo >> s.units_sold >> s.sellingprice >> s.saleprice;
if((in && s.sellingprice) != 0)
s.discount = s.saleprice / s.sellingprice;
else
s = Sales_data(); //输入错误,重置输入的数据
return in;
}
std::ostream& operator << (std::ostream& out, const Sales_data& s)
{
out << s.isbn() << " " << s.units_sold << " " << s.sellingprice \
<< " " << s.saleprice << " " << s.discount;
return out;
}
int main()
{
Sales_data book;
std::cout << "请输入销售记录:" << std::endl;
while(std::cin >> book)
{
std::cout << " ISBN,售出本数,原始价格,实售价格,折扣为" << book << std::endl;
}
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;
Sales_data total, trans;
std::cout << "请输入几条ISBN相同的销售记录:" << std::endl;
if(std::cin >> trans)
{
while(std::cin >> trans)
if(compareIsbn(total, trans)) //ISBN相同
{
total = total + trans;
}
else //ISBN不同
{
std::cout << "当前书籍ISBN不同" << std::endl;
break;
}
}
else
{
std::cout << "没有数据" << std::endl;
return -1;
}
int num = 1; //记录当前书籍的销售记录总数
std::cout << "请输入若干销售记录:" << std::endl;
if(std::cin >> trans1)
{
while(std::cin >> trans2)
if(compareIsbn(trans1, trans2)) //ISBN相同
{
num++;
}
else //ISBN不同
{
std::cout << trans1.isbn() << "共有" << num << "条销售记录" << std::endl;
trans1 = trans2;
num = 1;
}
std::cout << trans1.isbn() << "共有" << num << "条销售记录" << std::endl;
}
else
{
std::cout << "没有数据" << std::endl;
return -1;
}
return 0;
}