C++ Primer(5e)第7章习题

7.1

#include<iostream>
#include<string>

using namespace std;

struct  Sales_data
{
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

int main()
{
	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)
			{
				total.units_sold += trans.units_sold;
				total.revenue += trans.revenue;
			}
			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;
		return -1;
	}
	return 0;
}

7.2

struct  Sales_data
{
	std::string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

Sales_data& Sales_data::combine(const Sales_data &rhs)
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	return *this;
}

7.3

#include<iostream>
#include<string>

using namespace std;

struct  Sales_data
{
	std::string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

Sales_data& Sales_data::combine(const Sales_data &rhs)
{
	units_sold += rhs.units_sold;
	revenue += rhs.revenue;
	return *this;
}

int main()
{
	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())
				total.combine(trans);
			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;
		return -1;
	}
	return 0;
}

7.4

struct Person
{
	std::string name;
	std::string address;
};

7.5

struct Person
{
	std::string isname() const { return name; }
	std::string isaddr() const { return address; }
	std::string name;
	std::string address;
};

应该是const,因为我们只读取,不修改。

7.6

/* 书上的就挺好用的,敲一遍也是累积代码量嘛~ */
struct Sales_data
{
	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;
};

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;
}

istream &read(istream &is, Sales_data &item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}

ostream &print(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;
}

7.7

#include<iostream>
#include<string>

using namespace std;

struct Sales_data
{
	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;
};

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;
}

istream &read(istream &is, Sales_data &item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}

ostream &print(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;
}

int main()
{
	Sales_data total;
	if (read(cin, total))
	{
		Sales_data trans;
		while (read(cin, trans))
		{
			if (total.isbn() == trans.isbn())
				total = add(total, trans);
			else
			{
				print(cout, total) << endl;;
				total = trans;
			}
		}
		print(cout, total) << endl;
	}
	else
	{
		cout << "No data?!" << endl;
		return -1;
	}
	return 0;
}

7.8

因为read函数在读取数据的时候会修改数据;而print函数只读取不修改。

7.9

struct Person
{
	std::string isname() const { return name; }
	std::string isaddr() const { return address; }
	std::string name;
	std::string address;
};

istream &read(istream &is, Person &item)
{
	is >> item.name >> item.address;
	return is;
}

ostream &print(ostream &os, Person &item)
{
	os << item.isname() << item.isaddr();
	return os;
}

7.10

if (read(read(cin, data1), data2)
判断data1,data2是否成功写入数据

7.11

/* 太懒了,程序就不编了。。。*/
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(n * p) { }
	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;
};

7.12

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(n * p) { }
	Sales_data(std::istream &is) { read(is, *this); }
	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;
};

7.13

#include<iostream>
#include<string>

using namespace std;

struct Sales_data
{
	Sales_data(std::istream &is);
	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;
};

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;
}

istream &read(istream &is, Sales_data &item)
{
	double price = 0;
	is >> item.bookNo >> item.units_sold >> price;
	item.revenue = price * item.units_sold;
	return is;
}

ostream &print(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);
}

int main()
{
	Sales_data total(cin);
	if (!total.isbn().empty())
	{
		Sales_data trans(cin);
		if (total.isbn() == trans.isbn())
			total = add(total, trans);
		else
		{
			print(cout, total);
			total = trans;
		}
		print(cout, total);
	}
	else
	{
		cerr << "No data?!" << endl;
		return -1;
	}
	return 0;
}

7.14

Sales_data(const std::string &s) : bookNo(s), units_sold(0), revenue(0) { }

7.15

struct Person
{
	Person(const std::string &s1, const std::string &s2) :
		name(s1), address(s2) { }
	std::string isname() const { return name; }
	std::string isaddr() const { return address; }
	std::string name;
	std::string address;
};

7.16

一个类可以包含0个或多个访问说明符,而且对于某个访问说明符能出现多少次也没有严格限定。
定义在public说明符之后的成员在整个程序内可被访问;定义在private说明符之后的成员可以被类的成员函数访问。

7.17

当我们希望定义的类的所有成员是public的时,使用struct;反之,如果希望成员是private的,使用class

7.18

封装:使用户不能到达对象的内部并且无法控制它的具体实现细节。
优点:1.确保用户代码不会无意间破坏封装对象的状态。2.被封装的类的具体实现可以随时改变,而无须调整用户级别的代码。

7.19

class Person
{
public:
	Person(const std::string &s1, const std::string &s2) :
		name(s1), address(s2) { }
	std::string isname() const { return name; }
	std::string isaddr() const { return address; }

private:
	std::string name;
	std::string address;
};

7.20

类可以允许其他类或者函数访问它的非公有成员,方法是令其他类或者函数称为它的友元。
利:允许其他类或者函数访问它的非公有成员
弊:如果我们希望类的用户能够调用某个友元函数,那么我们就必须在友元声明之外再专门对函数进行一次声明。

7.21

/* 创建一个头文件Sales_data.h,然后将下面代码放入其中 */
#ifndef HEAD_H
#define HEAD_H
#include<iostream>
#include<string>


class Sales_data
{
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::istream &read(std::istream &, Sales_data&);
friend std::ostream &print(std::ostream &, const Sales_data&);
public:
	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(n * p) { }
	Sales_data(std::istream &is) { read(is, *this); }
	std::string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);

private:
	double avg_price() const;
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

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.22

/* 创建一个Person.h头文件,将下面代码放入其中 */
#ifndef PERSON_H
#define PERSON_H
#include<iostream>
#include<string>

class Person
{
	friend std::istream &read(std::istream &, Person &);
	friend std::ostream &print(std::ostream &, Person &);
public:
	std::string isname() const { return name; }
	std::string isaddr() const { return address; }

private:
	std::string name;
	std::string address;
};

std::istream &read(std::istream &is, Person &item)
{
	is >> item.name >> item.address;
	return is;
}

std::ostream &print(std::ostream &os, Person &item)
{
	os << item.isname() << item.isaddr();
	return os;
}
#endif

7.23

class Screen
{
public:
	using pos = std::string::size_type;
	Screen() = default;
	Screen(pos ht, pos wd, char c) : height(ht), width(wd),
		contents(ht * wd, c) { }
	char get() const
	{
		return contents[cursor];
	}
	inline char get(pos ht, pos wd) const;
	Screen &move(pos r, pos c);
private:
	pos cursor = 0;
	pos height = 0, width = 0;
	std::string contents;
};

inline
Screen &Screen::move(pos r, pos c)
{
	pos row = r * width;
	cursor = row + c;
	return *this;
}

char Screen::get(pos r, pos c) const
{
	pos row = r * width;
	return contents[row + c];
}

7.24

class Screen
{
public:
	typedef std::string::size_type pos;
	Screen() = default;
	Screen(pos ht, pos wd) : height(ht), width(wd) { }
	Screen(pos ht, pos wd, char c) : height(ht), width(wd),
		contents(ht * wd, c) { }
	char get() const
	{
		return contents[cursor];
	}
	inline char get(pos ht, pos wd) const;
	Screen &move(pos r, pos c);
private:
	pos cursor = 0;
	pos height = 0, width = 0;
	std::string contents;
};

inline
Screen &Screen::move(pos r, pos c)
{
	pos row = r * width;
	cursor = row + c;
	return *this;
}

char Screen::get(pos r, pos c) const
{
	pos row = r * width;
	return contents[row + c];
}

7.25

可以,因为Screen类的数据成员都是带有赋值和拷贝函数的类型

7.26

/* 只截取一部分 */
class Sales_data
{
	friend Sales_data add(const Sales_data&, const Sales_data&);
	friend std::istream &read(std::istream &, Sales_data&);
	friend std::ostream &print(std::ostream &, const Sales_data&);
public:
	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(n * p) { }
	Sales_data(std::istream &is) { read(is, *this); }
	std::string isbn() const { return bookNo; }
	Sales_data& combine(const Sales_data&);

private:
	inline double avg_price() const;   // 嘿,内联
	std::string bookNo;
	unsigned units_sold = 0;
	double revenue = 0.0;
};

7.27

#include<iostream>
#include<string>
#include<vector>

using namespace std;

class Screen
{
public:
	using pos = std::string::size_type;
	Screen() = default;
	Screen(pos ht, pos wd) : height(ht), width(wd) { }
	Screen(pos ht, pos wd, char c) : height(ht), width(wd),
		contents(ht * wd, c) { }
	char get() const
	{
		return contents[cursor];
	}
	inline char get(pos ht, pos wd) const;
	Screen &move(pos r, pos c);
	Screen &set(char);
	Screen &set(pos, pos, char);
	Screen &display(std::ostream &os)
	{
		do_display(os); return *this;
	}
	const Screen &display(std::ostream &os) const
	{
		do_display(os); return *this;
	}
private:
	pos cursor = 0;
	pos height = 0, width = 0;
	std::string contents;
	void do_display(std::ostream &os) const { os << contents; }
};

inline
Screen &Screen::move(pos r, pos c)
{
	pos row = r * width;
	cursor = row + c;
	return *this;
}

char Screen::get(pos r, pos c) const
{
	pos row = r * width;
	return contents[row + c];
}

inline Screen &Screen::set(char c)
{
	contents[cursor] = c;
	return *this;
}

inline Screen &Screen::set(pos r, pos col, char ch)
{
	contents[r * width + col] = ch;
	return *this;
}

int main()
{
	Screen myScreen(5, 5, 'X');
	myScreen.move(4, 0).set('#').display(cout);
	cout << "\n";
	myScreen.display(cout);
	cout << " \n";
	return 0;
}

7.28 7.29

第二个display将会打印一连串X,没有#。
返回类型为引用:
在这里插入图片描述

返回类型不是引用:
在这里插入图片描述

7.30

优点:可以明确地指出访问的是调用该函数的对象的成员,且可以在成员函数中使用与数据成员同名的形参
缺点:多余

7.31

class X
{
	Y *ptr;
};

class Y
{
	X val;
};

7.32 - 7.46(血的教训)

下午去上课,电脑睡眠,自动断WIFI,我又没保存,想哭。。。
仅以此希望大家一定要记得保存,记得保存,记得保存~

7.47

应该是explicit的,这样做可以自己弄一个构造函数,进行类型类型转换,节省工作量;缺点就是只能用该种类型,太狭窄。

7.48

string null_isbn("9-999-99999-9");
Sales_data item1(null_isbn);
Sales_data item2("9-999-99999-9");

不是explicit时,全部都是正确的;是explicit时,item2是错误的。

7.49

 // string 转换为Sales_data,Sales_data构造一个临时变量
Sales_data &combine(Sales_data); 
// string 转换为Sales_data, Sales_data初始化引用这个值(可改变)
Sales_data &combine(Sales_data&); 
// string 转换为Sales_data, Sales_data初始化const引用这个值(不可改变)
Sales_data &combine(const Sales_data&) const; // string转换为Sales_data, 

7.50

class Person
{
	friend std::istream &read(std::istream &, Person &);
	friend std::ostream &print(std::ostream &, Person &);
public:
	Person() { }
	Person(std::string s1, std::string s2) : name(s1), address(s2) { }
	explicit Person(std::istream &is) { read(is, *this); }  // 唯一一个
	std::string isname() const { return name; } 
	std::string isaddr() const { return address; }

private:
	std::string name;
	std::string address;
};

std::istream &read(std::istream &is, Person &item)
{
	is >> item.name >> item.address;
	return is;
}

std::ostream &print(std::ostream &os, Person &item)
{
	os << item.isname() << item.isaddr();
	return os;
}

7.51

因为vector的参数都为同一类型,不存在类型转换的问题,故定义成explicit;而string的参数类型则不单一,需要进行隐式类型转换,故不能定义成explicit

7.52

978-0590353403为string类型bookNo
25为unsigned类型units_sold
15.99为double类型revenue

7.53

class Debug {
public:
	constexpr Debug(bool b = true) : hw(b), io(b), other(b) { }
	constexpr Debug(bool h, bool i, bool o) : 
		hw(h), io(i), other(o) { }
	constexpr bool any() { return hw || io || other; }
	void set_io(bool b) { io = b; }
	void set_hw(bool b) { hw = b; }
	void set_other(bool b) { hw = b; }
private:
	bool hw;
	bool io;
	bool other;
};

7.54

不应该,因为constexpr需要一个返回值

7.55

是的,因为数据成员都是字面值类型

7.56

静态成员:与类本身直接相关,而不是与类的各个对象保持关联。
优点:静态成员不必实例化就能直接使用
区别:静态数据成员的类型可以就是它所属的类类型,而普通成员只能声明它所属类的指针或引用;
可以使用静态成员作为默认实参,而普通成员不行。

7.57

class Account {
public:
	void calculate() { amount += amount * interestRate; }
	static double rate() { return interestRate; }
	static void rate(double);
private:
	std::string owner;
	double amount;
	static double interestRate;
	static double initRate();  // 不太清楚这个要干吗~
};

void Account::rate(double newRate)
{
	interestRate = newRate;
}

7.58

// example.h
class Example {
public:
	static double rate = 6.5;    // 错误,带初始值的不能是static 
	static const int vecSize = 20;
	static vector<double> vec(vecSize);  // 错误,带初始值的不能是static 
};
// example.C
#include "example.h"
double Example::rate;
vector<double> Example::vec;

修改:

// example.h
class Example {
public:
	static constexpr double rate = 6.5;    // 错误,带初始值的不能是static 
	static const int vecSize = 20;
	static vector<double> vec;  // 错误,带初始值的不能是static 
};
// example.C
#include "example.h"
double Example::rate;
vector<double> Example::vec(Example::vecSize);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值