第十二章 12.1.6节练习

练习12.19

定义你自己版本的StrBlobPtr,更新StrBlob类,加入恰当的friend声明及begin和end成员。

解答:

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

using namespace std;

class StrBlobStr;
class StrBlob{
public:
	friend StrBlobStr;
<span style="white-space:pre">	</span>StrBlob* begin(){
<span style="white-space:pre">			</span>return this;
<span style="white-space:pre">		</span>}
<span style="white-space:pre">	</span>StrBlob* end(){
<span style="white-space:pre">			</span>return this + data->size();
<span style="white-space:pre">		</span>}

	typedef vector<string>::size_type size_type;
	StrBlob();
	StrBlob(initializer_list<string> il);
	size_type size() const{ return data->size(); }
	bool empty() const { return data->empty(); }
	void push_back(const string &t)const{ data->push_back(t); }
	void pop_back()const;
	string& front();
	string& back();
private:
	shared_ptr<vector<string>> data;
	void check(size_type i, const string &msg) const;
};

StrBlob::StrBlob() :data(make_shared<vector<string>>()){}
StrBlob::StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)){}
void StrBlob::check(size_type i, const string &msg) const{
	if (i >= data->size()){
		throw out_of_range(msg);
	}
}
string& StrBlob::front(){
	check(0, "front on empty StrBlob");
	return data->front();
}
string& StrBlob::back(){
	check(0, "back on empty StrBlob");
	return data->back();
}
void StrBlob::pop_back()const{
	check(0, "pop_back on empty SteBlob");
	data->pop_back();
}

class StrBlobStr{
public:
	StrBlobStr() :curr(0){}
	StrBlobStr(StrBlob &a, size_t sz = 0) :wptr(a.data), curr(sz){}
	string &deref() const;
	StrBlobStr &incr();

private:
	shared_ptr<vector<string>> check(size_t , const string&) const;
	weak_ptr<vector<string>> wptr;
	size_t curr;
};

shared_ptr<vector<string>> StrBlobStr::check(size_t i, const string& msg) const{
	auto ret = wptr.lock();
	if (!ret){
		throw runtime_error("unbound StrBlobPtr");
	}
	if (i >= ret->size()){
		throw out_of_range(msg);
	}
	return ret;
}

string& StrBlobStr::deref() const{
	auto p = check(curr, "dereference past end");
	return (*p)[curr];
}

StrBlobStr& StrBlobStr::incr(){
	check(curr, "increment past end of StrBlobPtr");
	++curr;
	return *this;
}
继续抄书上的代码,不过书上的代码在编译的时候会报错。

因为StrBolbStr的类型在StrBolb仅仅是声明,所以不能创建对象,只能创建指针(或引用)。

这样的话,begin和end一点存在的意义都没有。


练习12.20

编写程序,逐行读入一个输入文件,将内容存入一个StrBlob中,用一个StrBlobPtr打印出StrBlob中的每个元素。

解答:

#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <fstream>

using namespace std;

class StrBlobStr;

class StrBlob{
public:
	friend StrBlobStr;
	typedef vector<string>::size_type size_type;
	StrBlob();
	StrBlob(initializer_list<string> il);
	size_type size() const{ return data->size(); }
	bool empty() const { return data->empty(); }
	void push_back(const string &t)const{ data->push_back(t); }
	void pop_back()const;
	string& front();
	string& back();
private:
	shared_ptr<vector<string>> data;
	void check(size_type i, const string &msg) const;
};

class StrBlobStr{
public:
	StrBlobStr() :curr(0){}
	StrBlobStr(StrBlob &a, size_t sz = 0) :wptr(a.data), curr(sz){}
	string &deref() const;
	StrBlobStr &incr();

private:
	shared_ptr<vector<string>> check(size_t, const string&) const;
	weak_ptr<vector<string>> wptr;
	size_t curr;
};

StrBlob::StrBlob() :data(make_shared<vector<string>>()){}
StrBlob::StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)){}
void StrBlob::check(size_type i, const string &msg) const{
	if (i >= data->size()){
		throw out_of_range(msg);
	}
}
string& StrBlob::front(){
	check(0, "front on empty StrBlob");
	return data->front();
}
string& StrBlob::back(){
	check(0, "back on empty StrBlob");
	return data->back();
}
void StrBlob::pop_back()const{
	check(0, "pop_back on empty SteBlob");
	data->pop_back();
}



shared_ptr<vector<string>> StrBlobStr::check(size_t i, const string& msg) const{
	auto ret = wptr.lock();
	if (!ret){
		throw runtime_error("unbound StrBlobPtr");
	}
	if (i >= ret->size()){
		throw out_of_range(msg);
	}
	return ret;
}

string& StrBlobStr::deref() const{
	auto p = check(curr, "dereference past end");
	return (*p)[curr];
}

StrBlobStr& StrBlobStr::incr(){
	check(curr, "increment past end of StrBlobPtr");
	++curr;
	return *this;
}

void process(istream& in){
	StrBlob file_content;

	string line;
	while (getline(in, line)){
		file_content.push_back(line);
	}

 	StrBlobStr print_obj(file_content, 0);
	for (int i = 0; i != file_content.size(); i++, print_obj.incr()){
 		cout << print_obj.deref() << endl;
	}

}

int main(){
	ifstream in("test.txt");
	process(in);
}



练习12.21

也可以这样编写StrBlobPtr的deref成员:

std::string& deref() const{
  return (*check(curr, "dereference past end"))[curr];
}

你认为哪个版本更好?为什么?

解答:

这样的确也是可以的,不过这样写对于代码的理解带来了不必要的障碍。

所以还是觉得,还是分开写的版本比较好。


练习12.22

为了能让StrBlobPtr使用const StrBlob,你觉得应该如何修改?

定义一个名为ConstStrBlobPtr的类,使其能够指向const StrBlob。

解答:

对StrBlobPtr的构造函数做点手脚即可。

StrBlobStr(const StrBlob &a, size_t sz = 0) :wptr(a.data), curr(sz){}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值