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

7.1

#include
#include

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
#include

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
#include

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
#include

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
#include


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
#include

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
#include
#include

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,没有#。
返回类型为引用:
C++ Primer(5e)第7章习题_第1张图片

返回类型不是引用:
C++ Primer(5e)第7章习题_第2张图片

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

你可能感兴趣的:(C++)