C++Primer第五版 第7章 类 7.1 定义抽象数据类型 练习

C++Primer第五版 第7章 类 练习

7.1 定义抽象数据类型

练习7.1.1

练习7.1.1:使用2.6.1节练习定义的Sales_data类为1.6节(第21页)的交易处理程序编写一个新版本。

#include <iostream>
#include <string>
using namespace std;
struct Sales_data{
	string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};
void test(){
	Sales_data total; // 保存当前求和结果的变量
	if (cin >> total.bookNo >> total.units_sold >> total.revenue) { // 读入第一笔交易
		 Sales_data trans; // 保存下一条交易数据的变量
		 while(cin >> trans.bookNo >> trans.units_sold >> trans.revenue) { // 读入剩余的交易
			if (total.bookNo == trans.bookNo){ // 检查isbn
				total.units_sold += trans.units_sold;
                total.revenue += trans.revenue; // 更新变量total当前的值
			}else {
				cout << total.bookNo << " " << total.units_sold << " " << total.revenue << endl;	// 输出结果
                total = trans; // 处理下一本书
			} 
		 }
		 cout << total.bookNo << " " << total.units_sold << " " << total.revenue << endl; // 输出最后的一条交易
	} else { //没有输入任何信息
		cerr << "No data?!" << endl; // 通知用户
	}
}

int main(){	
	test();
	system("pause");
    return 0;
}
练习7.1.2

练习7.2:曾在2.6.2节练习(第67页)中编写了一个Sales_data类,请向这个类添加combine和isbn成员。

//一个定义了Sales_data类的头文件Sales_data.h
#include <iostream>
#include <string>
using namespace std;
struct Sales_data{
	//关于Sales_data对象的操作
	string isbn() const {return this->bookNo;}//返回对象的isbn编号
	Sales_data& combine(const Sales_data&);//将一个Sales_data对象加到另一个对象上
	double avg_price() const;//返回售出书籍的平均价格
	
	string bookNo;	//表示isbn编号
	unsigned units_sold = 0;	//书的销量
	double revenue = 0.0;	//书的总销售收入
};
double Sales_data::avg_price()const{//常量成员函数,不会改变Sales_data对象的值
	if(units_sold)
		return revenue/units_sold;
	else
		return 0;
}
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
	 units_sold += rhs.units_sold; //把rhs的成员加到this对象的成员上
	 revenue += rhs.revenue; 
	 return *this; //返回调用该函数的对象
}

练习7.3:修改7.1.1节(第229页)的交易处理程序,令其使用这些成员。

#include <iostream>
#include <string>
#include "Sales_data.h"
using namespace std;

void test(){
	Sales_data total; // 保存当前求和结果的变量
	if (cin >> total.bookNo >> total.units_sold >> total.revenue) { // 读入第一笔交易
		 Sales_data trans; // 保存下一条交易数据的变量
		 while(cin >> trans.bookNo >> trans.units_sold >> trans.revenue) { // 读入剩余的交易
			if (total.isbn() == trans.isbn()){ // 检查isbn
				total.combine(trans);// 更新变量total当前的值
			}else {
				cout << total.bookNo << " " << total.units_sold << " " << total.revenue << endl;	// 输出结果
                total = trans; // 处理下一本书
			} 
		 }
		 cout << total.bookNo << " " << total.units_sold << " " << total.revenue << endl; // 输出最后的一条交易
	} else { //没有输入任何信息
		cerr << "No data?!" << endl; // 通知用户
	}
}

int main(){
	test();
	system("pause");
    return 0;	
}

练习7.4:编写一个名为Person的类,使其表示人员的姓名和地址。使用string对象存放这些元素,接下来的练习将不断充实这个类的其他特征。

#include <iostream>
#include <string>
using namespace std;

class Person{
public:
	string mName;//人员姓名
	string mAddress;//人员地址
};

练习7.5:在你的Person类中提供一些操作使其能够返回姓名和住址。这些函数是否应该是
const的呢?解释原因。 答:是const的,原因是这些操作不需要改变对象中成员变量的具体的值,只需要读取成员对象。

练习7.1.3

练习7.6:对于add, read和print,定义你自己的版本。

Sales_data add(const Sales_data& lhs, const Sales_data& rhs){
	Sales_data sum = lhs;
	sum.combine(rhs);
	return sum;
}
ostream &print(ostream& os, const Sales_data& item){
	//将给定对象的内容打印到给定的流当中
	os << item.isbn() << " " << item.units_sold << " " 
	   << item.revenue << " " << item.avg_price(); 
	return os;

}
istream &read(istream& is, Sales_data& item){
	//从给定流中将数据读到给定对象中
	double price = 0.0;//每本书的单价
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}

练习7.7:使用这些新函数重写7.1.2节(第233页)练习中的交易处理程序。

void test(){
	Sales_data total; // 保存当前求和结果的变量
	if (read(cin,total)) { // 读入第一笔交易
		 Sales_data trans; // 保存下一条交易数据的变量
		 while(read(cin,trans)) { // 读入剩余的交易
			if (total.isbn() == trans.isbn()){ // 检查isbn
				total.combine(trans);// 更新变量total当前的值
			}else {
				print(cout,total);	// 输出结果
                total = trans; // 处理下一本书
			} 
		 }
		 print(cout,total); // 输出最后的一条交易
	} else { //没有输入任何信息
		cerr << "No data?!" << endl; // 通知用户
	}
}

练习7.8:为什么read函数将其Sales_data参数定义成普通的引用,而print将其参数定义成常量引用?
答: read函数是从给定流中将数据读到给定对象中,需要对Sales_data对象进行改变,其中成员变量revenue,bookNo等全部被更新;而print函数是将给定对象的内容打印到给定的流当中,不需要对Sales_data对象进行改变,只需要读取成员对象

练习7.9:对于7.1.2节(第233页)练习中的代码,添加读取和打印Person对象的操作。

istream &read(istream &is, Person &person)
{
    return is >> person.mName >> person.mAddress;
}

ostream &print(ostream &os, const Person &person)
{
    return os << person.mName << " " << person.mAddress;
}

练习7.10:在下面这条if语句中,条件部分的作用是什么?
if(read(read(cin,data1),data2))
答:read(cin,data1) ,向data1里输入内容,返回data1;read(read(cin,data1),data2) 即为read(data1,data2),将data1的内容输入到data2;只有当两次读入的内容都不空时,条件为真。

练习7.1.4

练习7.11:在你的Sales_data类中添加构造函数,然后 编写一段程序令其用到没个构造函数

Sales_Data.h
struct Sales_data{
	//构造函数 (在类外实现)
	Sales_data();
	Sales_data(const string &s);
	Sales_data(const string &s, unsigned n, double p);
	Sales_data(istream &);

	//关于Sales_data对象的操作
	string isbn() const {return  bookNo;}//返回对象的isbn编号
	Sales_data& combine(const Sales_data&);//将一个Sales_data对象加到另一个对象上
	double avg_price() const;//返回售出书籍的平均价格
	
	string bookNo;	//表示isbn编号
	unsigned units_sold = 0;	//书的销量
	double revenue = 0.0;	//书的总 销售收入
};
Sales_data.cpp
// Sales_data() = default;
// Sales_data(const string &s): bookNo(s) { } 
// Sales_data(const string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) { }
// // : bookNo(s), units_sold(n), revenue(p*n)  构造函数初始化列表
Sales_data::Sales_data(istream &is){
	read(is, *this); //read函数的作用是从is中读取一条交易信息然后存入this对象中
}
Sales_data::Sales_data(const string &s, unsigned n, double p){ 
	this->bookNo = s;
	this->units_sold = n;
	this->revenue = p*n ;
} 
Sales_data::Sales_data(const string &s) { 
	this->bookNo = s;
} 
// Sales_data::Sales_data(){}
Sales_data::Sales_data() = default;

void test(){
	Sales_data total01;
	print(cout,total01);	
	cout << endl;
	
    Sales_data total02("1234");
	print(cout,total02);	
	cout << endl;
	
	Sales_data total03("1200",3,3.59);
	print(cout,total03);	
	cout << endl;
	
	Sales_data total04(cin);
	print(cout,total04);
}

在这里插入图片描述

练习7.12:把只接受一个istream作为参数的构造函数定义到类的内部。

Sales_Data.h
struct Sales_data{

	friend istream &read(istream&, Sales_data&);//read函数做友元
	
	//构造函数 
	Sales_data(istream &is){
		read(is, *this); //read函数的作用是从is中读取一条交易信息然后存入this对象中
	}
	
	//关于Sales_data对象的操作
	string isbn() const {return  bookNo;}//返回对象的isbn编号
	Sales_data& combine(const Sales_data&);//将一个Sales_data对象加到另一个对象上
	double avg_price() const;//返回售出书籍的平均价格

	string bookNo;	//表示isbn编号
	unsigned units_sold = 0;	//书的销量
	double revenue = 0.0;	//书的总 销售收入
};

练习7.13:使用istream构造函数重写第229页程序。

Sales_Data.h
struct Sales_data;
istream &read(std::istream&, Sales_data&);

struct Sales_data{	
	//构造函数 
	Sales_data();
	// Sales_data() = default;
	Sales_data(const string &s);
	Sales_data(const string &s, unsigned n, double p);
	Sales_data(istream &is){
		read(is, *this); //read函数的作用是从is中读取一条交易信息然后存入this对象中
	}

	//关于Sales_data对象的操作
	string isbn() const {return  bookNo;}//返回对象的isbn编号
	Sales_data& combine(const Sales_data&);//将一个Sales_data对象加到另一个对象上
	double avg_price() const;//返回售出书籍的平均价格
	
	string bookNo;	//表示isbn编号
	unsigned units_sold = 0;	//书的销量
	double revenue = 0.0;	//书的总 销售收入
};

//Sales_data的非成员接口函数
Sales_data add(const Sales_data&, const Sales_data&);
ostream &print(ostream&, const Sales_data&);

练习7.14:编写一个构造函数,令其用我们提供的类内初始值显示地初始化成员

void test(){
	Sales_data total(cin); // 读入第一笔交易
	if (!total.isbn().empty()) {  
		 istream &is = cin;// 读入剩余的交易
		 while(is) { 
			Sales_data trans(is);// 保存下一条交易数据的变量
            if (!is) break;//剩余交易没有输入,中止输入
			if (total.isbn() == trans.isbn()){ // 检查isbn
				total.combine(trans);// 更新变量total当前的值
			}else {
				print(cout,total)<<endl;// 输出结果
                total = trans; // 处理下一本书
			} 
		 }
		 print(cout,total)<<endl; // 输出最后的一条交易
	} else { //没有输入任何信息
		cerr << "No data?!" << endl; // 通知用户
	}
}

练习7.15:为你的Person类添加正确的构造函数

Person.h
class Person{
public:
	friend istream &read(istream &, Person &);
	
	Person(){}
	Person(string name,string address):mName(name), mAddress(address){}
	Person(istream& is){
		read(is,*this);
	}
	string mName;//人员姓名
	string mAddress;//人员地址
	
};
// istream &read(istream &, Person &);
ostream &print(ostream &, const Person &);
Person.cpp
istream &read(istream &is, Person &person)
{
    return is >> person.mName >> person.mAddress;
}

ostream &print(ostream &os, const Person &person)
{
    return os << person.mName << " " << person.mAddress;
}
int main(){
	Person p1;
	print(cout,p1) << endl;
	
	Person p2("张三","北京市海淀区");
	print(cout,p2) << endl;
	
	Person p3(cin);
	print(cout,p3) << endl;
	
	system("pause");
    return 0;
}
练习7.1.5

无练习

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值