C++程序设计原理与实践 习题答案 第十五章 第15章习题答案

Document 本章的文本编辑器实现,添加了一些功能

欢迎大家来 debug !

Document.h

//Document.h
#include"../../std_lib_facilities.h"

using Line = vector<char>;

template<typename C>
using Iterator = typename C::iterator;

class Text_iterator {
	list<Line>::iterator ln;
	Line::iterator pos;
public:
	Text_iterator(list<Line>::iterator ll, Line::iterator pp)
		:ln{ ll }, pos{ pp }{}

	list<Line>::iterator get_line() { return ln; }
	Line::iterator get_inline_pos() { return pos; }

	char& operator*() { return *pos; }
	bool operator==(const Text_iterator& other)const
	{	return ln == other.ln && pos == other.pos;	}
	bool operator!=(const Text_iterator& other)const
	{	return !(*this == other);	}
	Text_iterator& operator++();	//前缀++
	Text_iterator& operator--();	//前缀--
};



struct Document {
	using size_type = unsigned long;
	
	list<Line>line;
	size_type sz;

	Document() :sz{0} { line.push_back(Line{}); }	//每个Document都以空行结尾(哪怕什么都没有的空Document也是这样),这也是初始化一个空行的原因
	
	Text_iterator begin();
	Text_iterator end();
	size_type size() const;

	Text_iterator insert(Text_iterator pos, const char ch);
	Text_iterator erase(Text_iterator pos);

	Text_iterator break_line(Text_iterator pos);	//从pos位置开始分出新行,并按需在pos处插入换行符,返回指向原来行尾换行符的迭代器
	Text_iterator concat_line(Text_iterator pos);	//从pos位置开始链接到前一行,pos若指向换行符,则先删除,再将pos指向下一行的行首,返回链接成一行后的指向原pos指向字符的迭代器

	//下面这个find_replace()函数是练习15_6的操作
	Text_iterator find_replace(Text_iterator first, Text_iterator last, const string& find_str, const string& repl_str);	//只替换第一个查找到的字符串
	void find_replace_all(Text_iterator first, Text_iterator last, const string& find_str, const string& repl_str);			//替换所有查找到的字符串
};

istream& operator>>(istream& is, Document& d);
void print(Document& d);
void erase_line(Document& d, int n);
Text_iterator find_txt(Text_iterator first, Text_iterator last, const string& s);

//15_8 统计字符总数
int cnt_char(Document& d);
//15_9 统计单词数
int cnt_word_v1(Document& d);	//单词是以空白符分隔的字符序列
int cnt_word_v2(Document& d);	//单词是一个连续的字母序列
//15_10 统计单词数,用户可以指定空白符集合
int cnt_word_v3(Document& d, const vector<char>& space_set);	//单词是以用户指定的空白符分隔的字符序列

template<typename Iter>
void my_advance(Iter& p, int n)
{
	while (n < 0)
	{
		--p;
		++n;
	}
	while (n > 0)
	{
		++p;
		--n;
	}
}

template<typename Iter>
bool match(Iter first, Iter last, const string& s)
{
	if (first == last || s.size() == 0)
		return false;
	size_t i;
	for (i = 0; i<s.size() && first != last; ++i, ++first)
	{
		if (*first != s[i])
			return false;
	}
	if (i == s.size())
		return true;
	else
		return false;
}

Document.cpp

#include "Document.h"

//下面是Text_iterator的成员函数
Text_iterator& Text_iterator::operator++()
{
	++pos;
	if (pos == (*ln).end())
	{
		++ln;
		pos = (*ln).begin();	//如果ln == line.end()则错误,应该尽力避免
	}
	return *this;
}

Text_iterator& Text_iterator::operator--()
{
	if (pos != ln->begin())
		--pos;
	else
	{
		--ln;
		pos = --(ln->end());
	}
	return *this;
}



//下面是Document的成员函数

Text_iterator Document::begin()
{
	return Text_iterator(line.begin(), line.begin()->begin());
}

Text_iterator Document::end()
{
	auto last = line.end();
	--last;		//这里假设文档是不为空的
	return Text_iterator(last, last->end());
}

Document::size_type Document::size() const
{
	return sz;
}

Text_iterator Document::insert(Text_iterator pos, const char ch)
{
	list<Line>::iterator list_it = pos.get_line();
	Line::iterator inline_it = pos.get_inline_pos();
	inline_it = (*list_it).insert(inline_it, ch);
	Text_iterator p{ list_it, inline_it };
	if (ch == '\n')	//如果是换行符,那么设置新行
		p = break_line(p);
	++sz;
	return p;
}

Text_iterator Document::erase(Text_iterator pos)
{
	list<Line>::iterator list_it = pos.get_line();
	Line::iterator inline_it = pos.get_inline_pos();
	if (*inline_it == '\n')	//如果要删除的是行尾的换行符,那么意味着这行和下一行合并
		pos = concat_line(pos);	//合并操作,在这个函数中执行删除操作
	else
	{
		inline_it = (*list_it).erase(inline_it);
		pos = Text_iterator{ list_it, inline_it };
	}
	--sz;
	return pos;
}

Text_iterator Document::break_line(Text_iterator pos)
//从pos位置开始分出新行,并按需在pos处插入换行符,返回指向原来行尾换行符的迭代器
{
	if (*pos != '\n')
		pos = insert(pos, '\n');
	else
	{
		Iterator<list<Line>> curr_line_it = pos.get_line();
		Iterator<Line> inline_it = pos.get_inline_pos() + 1;
		Iterator<list<Line>> next_line_it = curr_line_it;
		advance(next_line_it, 1);
		Line new_line{};
		for (auto p = inline_it; p != curr_line_it->end(); ++p)
			new_line.push_back(*p);
		line.insert(next_line_it, new_line);
		curr_line_it->erase(inline_it, curr_line_it->end());			//删除原行换行符后面的所有字符
	}
	return pos;
}

Text_iterator Document::concat_line(Text_iterator pos)
//接受两种pos位置:1.pos指向第一行的最后一个字符:
//					  1.1.pos指向非换行符, 那么将第二行拼接至第一行的pos之后,返回原pos指向字符的迭代器
//					  1.2.pos指向换行符,那么删除换行符,将第二行拼接至第一行尾,返回指向原第二行行首字符的迭代器
//				   2.pos指向第二行的首字符:
//					  2.1.第一行最后一个字符是非换行符,那么直接拼接上去,返回指向第二行首字符的迭代器
//					  2.2.第一行最后一个字符是换行符,那么删除换行符后再直接拼接上去,返回指向第二行首字符的迭代器
{
	Iterator<list<Line>> curr_line = pos.get_line();
	Iterator<Line> inline_it = pos.get_inline_pos();
	Line::size_type index{ 0 };

	if (inline_it == --(curr_line->end()))
	{
		if (curr_line == --line.end() || curr_line == line.end())	//如果当前行是“最后一行”,那么无法拼接下一行,直接返回
			return pos;
		Iterator<list<Line>> next_line = curr_line;
		advance(next_line, 1);
		index = inline_it - curr_line->begin();
		if (*pos == '\n')
			curr_line->erase(inline_it);	//删除第一行的换行符
		curr_line->insert(curr_line->end(), next_line->begin(), next_line->end());	//先把第二行字符拼接到第一行
		line.erase(next_line);			//再删除第二行
		pos = Text_iterator{ curr_line, curr_line->begin() + index };
	}
	else if (inline_it == curr_line->begin())
	{
		if (curr_line == line.begin())	//如果这行是文档的第一行,那么无法往上拼接了,直接返回
			return pos;
		--pos;
		Iterator<list<Line>> prev_line = pos.get_line();
		index = prev_line->end() - prev_line->begin();
		if (*pos == '\n')
		{
			prev_line->erase(pos.get_inline_pos());	//删除第一行的换行符
			--index;
		}
		prev_line->insert(prev_line->end(), curr_line->begin(), curr_line->end());	//先把第二行字符拼接到第一行
		line.erase(curr_line);			//再删除第二行
		pos = Text_iterator{ prev_line, prev_line->begin() + index };
	}
	return pos;
}

//练习15_6:find_replace()和find_replace_all()函数
Text_iterator Document::find_replace(Text_iterator first, Text_iterator last, const string& find_str, const string& repl_str)
//只替换第一个查找到的字符串
{
	//int rs_sz = repl_str.size();
	Text_iterator pos = find_txt(first, last, find_str);
	if (pos != last)
	{
		string::const_iterator fs_it = find_str.begin();
		string::const_iterator rs_it = repl_str.begin();
		while (fs_it != find_str.end() && rs_it != repl_str.end())
		{
			if (*fs_it != *rs_it)	//如果字符不相等, 则替换
			{
				*pos = *rs_it;
				if (*fs_it == '\n')			//如果被替换的字符是换行符,那么需要将下一行合并上来
					pos = concat_line(pos);
				else if (*rs_it == '\n')	//如果替换的字符是换行符,那么需要将该行的换行符后面所有字符开辟为新行
					pos = break_line(pos);
			}
			++pos;
			++fs_it;
			++rs_it;
		}
		while (fs_it != find_str.end())	//如果被替换的字符比替换字符长,那么需要将剩余被替换字符删除
		{
			pos = erase(pos);
			++fs_it;
		}
		while (rs_it != repl_str.end())	//如果被替换的字符比替换字符短,那么需要将剩余替换字符插入
		{
			pos = insert(pos, *rs_it);
			++pos;
			++rs_it;
		}
	}
	//advance(pos, -rs_sz);	//往前找完成替换操作后的替换字符串首字符
	return pos;
}

void Document::find_replace_all(Text_iterator first, Text_iterator last, const string& find_str, const string& repl_str)
//替换所有查找到的字符串
{
	Text_iterator pos = first;
	do {
		pos = find_replace(pos, last, find_str, repl_str);
	} while (pos != last);
}


//下面是辅助函数

istream& operator>>(istream& is, Document& d)
{
	for (char ch; is.get(ch); )
	{
		d.line.back().push_back(ch);	//添加字符
		++d.sz;
		if (ch == '\n')
			d.line.push_back(Line{});	//添加新的一行
	}
	if (d.line.back().size())
	{
		if (d.line.back().back() != '\n')	//如果读入数据的最后一行的最后并不是以换行符结尾
			d.line.back().push_back('\n');	//那么再最后一行的最后添加换行符
		d.line.push_back(Line{});	//添加最后的空行,注意每个Document都以空行结尾
	}
	return is;
}

void print(Document& d)
{
	for (auto p : d)
		cout << p;
}

void erase_line(Document& d, int n)
//删除第n行,行数从0开始
{
	if (n < 0 || d.line.size() < n)	//注意后面一个条件判断,由于Document都以一个空行结尾,因此行数实际上是多一行的
		return;
	auto p = d.line.begin();
	advance(p, n);
	d.line.erase(p);
}

template<class Iter, class T> Iter find(Iter first, Iter last, const T& val)
{
	Iter p = first;
	while (p != last) {
		if (*p == val) return p;
		++p;
	}
	return p;
}

Text_iterator find_txt(Text_iterator first, Text_iterator last, const string& s)
{
	if (s.size() == 0)	//不能查找一个空字符串
		return last;
	char first_char = s[0];
	while (true)
	{
		auto p = ::find(first, last, first_char);
		if (p == last || match(p, last, s))
			return p;
		first = ++p;
	}
}

//15_8统计字符数
int cnt_char(Document& d)
{
	int cnt = 0;
	for (auto p = d.begin(); p != d.end(); ++p)
		cnt++;
	return cnt;
}

//15_9 统计单词数
int cnt_word_v1(Document& d)
//单词是以空白符分隔的字符序列
{
	int cnt{ 0 };
	bool in_word{ false };
	for (auto p : d)
	{
		if (isspace(p))
		{
			if (in_word)
			{
				in_word = false;
				++cnt;
			}
		}
		else
			in_word = true;
	}
	return cnt;
}

int cnt_word_v2(Document& d)
//单词是一个连续的字母序列
{
	int cnt{ 0 };
	bool in_word{ false };
	for (auto p : d)
	{
		if (!isalpha(p))
		{
			if (in_word)
			{
				in_word = false;
				++cnt;
			}
		}
		else
			in_word = true;
	}
	return cnt;
}

static bool in_space_set(const char ch, const vector<char>& space_set)
{
	for (const char sp : space_set)
		if (sp == ch)
			return true;
	return false;
}

//15_10 统计单词数,用户可以指定空白符集合
int cnt_word_v3(Document& d, const vector<char>& space_set)
//单词是以用户指定的空白符分隔的字符序列
{
	int cnt{ 0 };
	bool in_word{ false };
	for (auto p : d)
	{
		if (in_space_set(p, space_set))
		{
			if (in_word)
			{
				in_word = false;
				++cnt;
			}
		}
		else
			in_word = true;
	}
	return cnt;
}

main.cpp 测试

#include"Document.h"

int main()
try {
	string ifname = "chapter20_ex06_in.txt";
	ifstream ifs(ifname.c_str());
	if (!ifs) error("can't open file ", ifname);
	Document my_doc;
	ifs >> my_doc;
	print(my_doc);
	cout << '\n';

	cout << "Searching for non-existing string 'wrong':\n\n";
	string f_str = "wrong";
	Text_iterator p = find_txt(my_doc.begin(), my_doc.end(), f_str);
	if (p == my_doc.end())
		cout << "not found";
	else
	{
		print(my_doc);
		cout << '\n';
	}

	cout << "\n\nSearching for 'Proin\\neget':\n\n";
	f_str = "Proin\neget";
	p = find_txt(my_doc.begin(), my_doc.end(), f_str);
	if (p == my_doc.end())
		cout << "not found";
	else
	{
		print(my_doc);
		cout << '\n';
	}

	cout << "Replace 'dolor' with 'FRITZLI':\n\n";
	f_str = "dolor";
	string r_str = "FRITZLI";
	my_doc.find_replace_all(my_doc.begin(), my_doc.end(), f_str, r_str);
	print(my_doc);

	cout << "Replace 'est\\nmollis' with 'XYZ\\nABCDEF' (same length, \\n in "
		<< "same place):\n\n";
	f_str = "est\nmollis";
	r_str = "XYZ\nABCDEF";
	my_doc.find_replace_all(my_doc.begin(), my_doc.end(), f_str, r_str);
	print(my_doc);
	cout << '\n';

	cout << "Replace 'Morbi\\ndapibus' with 'MORBI DAPIBUS' (same length, \\n is "
		<< "removed):\n\n";
	f_str = "Morbi\ndapibus";
	r_str = "MORBI DAPIBUS";
	my_doc.find_replace_all(my_doc.begin(), my_doc.end(), f_str, r_str);
	print(my_doc);
	cout << '\n';

	cout << "Replace 'turpis' with 'TU\\nPIS' (same length, \\n is added):\n\n";
	f_str = "turpis";
	r_str = "TU\nPIS";
	my_doc.find_replace_all(my_doc.begin(), my_doc.end(), f_str, r_str);
	print(my_doc);
	cout << '\n';

	cout << "Replace 'Proin\\neget' with 'ABC\\nDEF\\nGHI' (different length, "
		<< "\\n in different places, extra \\n):\n\n";
	f_str = "Proin\neget";
	r_str = "ABC\nDEF\nGHI";
	my_doc.find_replace_all(my_doc.begin(), my_doc.end(), f_str, r_str);
	print(my_doc);
	cout << '\n';

	cout << "Replace complete third line plus word before and after with "
		<< "\\nTHIRDLINE\\n:\n\n";
	f_str = "massa\nposuere lorem, sed placerat orci tortor quis leo.\nDonec ";
	r_str = "\nTHIRDLINE\n";
	my_doc.find_replace_all(my_doc.begin(), my_doc.end(), f_str, r_str);
	print(my_doc);
	cout << '\n';

	cout << "Replace 'et' with 'MARATHON' (multiple occurrences):\n\n";
	f_str = "et";
	r_str = "MARATHON";
	my_doc.find_replace_all(my_doc.begin(), my_doc.end(), f_str, r_str);
	print(my_doc);
	cout << '\n';

	cout << "Number of characters in this document: "
		<< cnt_char(my_doc) << "\n";

	cout << "Number of words (whitespace-separated) in this document: "
		<< cnt_word_v1(my_doc) << "\n";

	cout << "Number of words (sequences of alphabetic characters) in this "
		<< "document: " << cnt_word_v2(my_doc) << "\n";

	vector<char> space_set{ '.', '!', '\'', ' ', '\n' };
	//vector<char> space_set{ '.', '!', '\'', ' ' };
	cout << "Number of words separated by whitespace or \".!'\" in this "
		<< "document: " << cnt_word_v3(my_doc, space_set) << "\n";
}
catch (Range_error& re) {
	cerr << "bad index: " << re.index << "\n";
}
catch (exception& e) {
	cerr << "exception: " << e.what() << endl;
}
catch (...) {
	cerr << "exception\n";
}

List_Circular.h 我自己实现的循环链表

//List_Circular.h

#include<iostream>


template<typename Elem>
struct Link {
	Elem val;
	Link* pred;
	Link* succ;

	Link() :pred{ nullptr }, succ{ nullptr }{}
	Link(const Elem& v) :val{ v }, pred{ nullptr }, succ{ nullptr }{}
};


//双向循环链表,header是链表第一个节点也是最后一个节点的succ指向的节点
template<typename Elem>
class list {
private:
	long sz;
	Link<Elem>* header;

public:
	class out_of_range;
	class iterator;				//成员类型:双向迭代器
	class range_check_iterator;	//成员类型:范围检查双向迭代器

	list() :sz{ 0 }, header{ new Link<Elem>{} }
	{ header->pred = header; header->succ = header; }		//默认构造函数
	~list();

	iterator begin() { return iterator{ header->succ }; }	//指向首元素的迭代器
	iterator end() { return iterator{ header }; }		//指向尾元素之后的迭代器

	iterator insert(iterator p, const Elem& v);		//将 v 插入链表中 p 的位置
	iterator erase(iterator p);						//从链表中删除 p

	void push_back(const Elem& v);		//将 v 插入链表末尾
	void push_front(const Elem& v);		//将 v 插入链表末头
	void pop_back();		//删除尾元素
	void pop_front();		//删除首元素

	Elem& front();			//获取首元素
	Elem& back();			//获取尾元素

	int size() const { return sz; }
};

template<typename Elem>
class list<Elem>::out_of_range {};

template<typename Elem>
class list<Elem>::iterator {
	Link<Elem>* curr;	//当前链接
public:
	iterator(Link<Elem>* p) :curr{ p } {}

	iterator& operator++();
	iterator& operator--();

	Elem& operator*() { return curr->val; }
	Elem* operator->() { return &(curr->val); }	//如果*(iter).m 有效,则可以使用iter->m 简写形式

	bool operator==(const iterator& b) const
	{	return curr == b.curr;	}
	bool operator!=(const iterator& b) const
	{	return curr != b.curr;	}

	friend iterator list<Elem>::insert(iterator p, const Elem& v);		//将 v 插入链表中 p 的位置
	friend iterator list<Elem>::erase(iterator p);						//从链表中删除 p
};

//双向循环链表特性,针对begin()的--和end()的++都返回nullptr
template<typename Elem>
typename list<Elem>::iterator& list<Elem>::iterator::operator++()
{
	if (curr != nullptr)
		curr = curr->succ;
	return *this;
}

template<typename Elem>
typename list<Elem>::iterator& list<Elem>::iterator::operator--()
{
	if (curr != nullptr)
		curr = curr->pred;
	return *this;
}

template<typename Elem>
class list<Elem>::range_check_iterator {
private:
	using iter = typename list<Elem>::iterator;
	iter curr;
	iter begin;
	iter end;
public:
	range_check_iterator(iter p, iter begin, iter end) :curr{ p }, begin{ begin }, end{ end }{}

	range_check_iterator& operator++();
	range_check_iterator& operator--();

	Elem& operator*() { return *curr; }
	Elem* operator->() { return &*curr; }	//如果*(iter).m 有效,则可以使用iter->m 简写形式

	bool operator==(const range_check_iterator& b) const
	{	return curr == b.curr;	}
	bool operator!=(const range_check_iterator& b) const
	{	return curr != b.curr;	}

	friend iterator list<Elem>::insert(iterator p, const Elem& v);		//将 v 插入链表中 p 的位置
	friend iterator list<Elem>::erase(iterator p);						//从链表中删除 p
};
template<typename Elem>
typename list<Elem>::range_check_iterator& list<Elem>::range_check_iterator::operator++()
{
	if (curr == end)
		throw out_of_range{};
	++curr;
	return *this;
}

template<typename Elem>
typename list<Elem>::range_check_iterator& list<Elem>::range_check_iterator::operator--()
{
	if (curr == begin)
		throw out_of_range{};
	--curr;
	return *this;
}

template<typename Elem>
typename list<Elem>::iterator list<Elem>::insert(iterator p, const Elem& v)
//将 v 插入链表中 p 的位置
{
	Link<Elem>* pnode = new Link<Elem>(v);
	Link<Elem>* temp = p.curr;
	pnode->succ = temp;
	temp->pred->succ = pnode;
	pnode->pred = temp->pred;
	temp->pred = pnode;
	++sz;
	return iterator(pnode);
}

template<typename Elem>
typename list<Elem>::iterator list<Elem>::erase(iterator p)
//从链表中删除 p
{
	if (begin() == end())
		return end();
	if (p == end())
		return end();

	Link<Elem>* q = p.curr->succ;

	q->pred = p.curr->pred;
	p.curr->pred->succ = q;

	delete p.curr;
	--sz;
	return iterator{ q };
}

template<typename Elem>
void list<Elem>::push_back(const Elem& v)
//将 v 插入链表末尾
{
	Link<Elem>* pnode = new Link<Elem>(v);
	header->pred->succ = pnode;
	pnode->succ = header;
	pnode->pred = header->pred;
	header->pred = pnode;
	++sz;
}

template<typename Elem>
void list<Elem>::push_front(const Elem& v)
//将 v 插入链表头
{
	Link<Elem>* pnode = new Link<Elem>(v);
	pnode->succ = header->succ;
	pnode->pred = header;
	header->succ->pred = pnode;
	header->succ = pnode;
	++sz;
}

template<typename Elem>
void list<Elem>::pop_back()
//删除尾元素
{
	if (begin() == end())
		return;
	Link<Elem>* p = header->pred;
	header->pred = p->pred;
	p->pred->succ = header;
	delete p;
	--sz;
}

template<typename Elem>
void list<Elem>::pop_front()
//删除首元素
{
	if (begin() == end())
		return;
	Link<Elem>* p = header->succ;
	header->succ = p->succ;
	p->succ->pred = header;
	delete p;
	--sz;
}

template<typename Elem>
Elem& list<Elem>::front()
//获取首元素
{
	if (begin() == end())
		throw out_of_range{};
	return header->val;
}

template<typename Elem>
Elem& list<Elem>::back()
//获取尾元素
{
	if (begin() == end())
		throw out_of_range{};
	return header->pred->val;
}

template<typename Elem>
list<Elem>::~list()
{
	Link<Elem>* p, * temp;
	for (p = header; p;)
	{
		temp = p;
		p = p->succ;
		delete temp;
	}
}

Vector.h 自己实现的加入迭代器的vector

//Vector_template.h

#include<iostream>
#include<memory>

using std::allocator;

//使用模板需要注意,目前VS2019都要求在使用模板的地方必须能得到模板的完整定义
//因此,我们将模板的定义都放在了头文件中

template<typename T, typename A = allocator<T>>
class vector {
public:
	using size_type = unsigned long;
	using value_type = T;
	using iterator = T*;
	using const_iterator = const T*;

private:
	static const size_type first_expand_space{ 8 };
	A alloc;			//用 alloc 管理元素内存
	size_type sz;				//元素数目
	size_type space;			//总空间 = 元素数目 + 给新元素的空闲空间(槽位);总空间是指当前分配的空间
	T* elem;

public:
	class Invalid {};
	struct out_of_range { /*...*/ };	//用来报告越界错误

	class range_check_iterator;

	vector();									//默认构造函数
	explicit vector(size_type x, T def = T{});		//构造函数,x为元素数量,def为初始化值,在定义中有默认值
	vector(std::initializer_list<T>lst);		//初始化器列表构造函数

	vector(const vector&);						//拷贝构造函数
	vector& operator=(const vector&);			//拷贝赋值函数

	vector(vector&&);							//移动构造函数
	vector& operator=(vector&&);				//移动赋值函数

	~vector();

	iterator begin();
	const_iterator begin() const;
	iterator end();
	const_iterator end() const;

	size_type size() const;
	size_type capacity()const;						//返回 space 的大小
	void reserve(size_type newalloc);					//改变 space 的大小
	void resize(size_type newalloc, T def = T{});		//该表元素数量
	void push_back(const T& val);
	iterator insert(iterator p, const T& val);
	iterator erase(iterator p);

	T& operator[](size_type n);
	const T& operator[](size_type n) const;
	T& at(size_type n);
	const T& at(size_type n) const;

	T& front();
	T& back();
	const T& front() const;
	const T& back() const;
};


//下面是vector定义

template<typename T, typename A>
vector<T, A>::vector()
	:sz{ 0 }, space{ 0 }, elem{ nullptr }
{ }

template<typename T, typename A>
vector<T, A>::vector(size_type x, T def)
//构造函数,x为元素数量
	: sz{ x }, space{ x }
{
	if (x < 0)
		throw Invalid{};
	elem = alloc.allocate(x);
	for (size_type i = 0; i < sz; i++)
		alloc.construct(elem + i, def);	//初始化
}

template<typename T, typename A>
vector<T, A>::vector(std::initializer_list<T> lst)
//初始化器列表构造函数
	:sz{ size_type(lst.size()) }, space{ size_type(lst.size()) }, elem{ alloc.allocate(lst.size()) }
{
	//std::cout << "初始化列表构造函数\n";
	const T* ti = lst.begin();
	for (size_type i = 0; i < sz; ++i)
		alloc.construct(elem + i, *ti++);	//初始化
}

template<typename T, typename A>
vector<T, A>::vector(const vector& arg)
//拷贝构造函数
	: sz{ arg.sz }, space{ arg.space }, elem{ alloc.allocate(arg.space) }
{
	//std::cout << "拷贝构造函数\n";
	for (size_type i = 0; i < sz; ++i)
		alloc.construct(elem + i, arg.elem[i]);
}

template<typename T, typename A>
vector<T, A>& vector<T, A>::operator=(const vector& arg)
//拷贝赋值函数
{
	//std::cout << "拷贝赋值函数\n";
	if (this == &arg)				//自赋值,什么也不用做
		;
	else if (arg.sz <= space)		//空间足够,无需分配空间
	{
		for (size_type i = 0; i < sz; ++i)
			alloc.destroy(elem + i);				//先销毁原来的元素
		for (size_type i = 0; i < arg.sz; ++i)
			alloc.construct(&elem[i], arg.elem[i]);	//拷贝元素
		sz = arg.sz;
	}
	else
	{
		T* p = alloc.allocate(arg.sz);
		for (size_type i = 0; i < arg.sz; ++i)
			alloc.construct(p + i, arg.elem[i]);	//拷贝元素
		alloc.deallocate(elem, space);
		sz = space = arg.sz;		//设置新大小
		elem = p;					//指向新元素的指针
	}
	return *this;					//按照惯例,赋值运算符将返回被赋值对象的引用
}

template<typename T, typename A>
vector<T, A>::vector(vector&& arg)
//移动构造函数
	:sz{ arg.sz }, space{ arg.space }, elem{ arg.elem }
{
	//std::cout << "移动构造函数\n";
	arg.sz = arg.space = 0;		//令 arg 变为空
	arg.elem = nullptr;
}


template<typename T, typename A>
vector<T, A>& vector<T, A>::operator=(vector&& arg)
//移动赋值函数,将 arg 移动到本vector
{
	//std::cout << "移动赋值函数\n";
	alloc.deallocate(elem, space);
	sz = arg.sz;
	space = arg.space;
	elem = arg.elem;
	arg.sz = arg.space = 0;
	arg.elem = nullptr;
	return *this;
}


template<typename C>
using Iterator = typename C::iterator;
template<typename C>
using Const_Iterator = typename C::const_iterator;

template<typename T, typename A>
Iterator<vector<T,A>> vector<T, A>::begin()
{
	return elem;
}


template<typename T, typename A>
Const_Iterator<vector<T, A>> vector<T, A>::begin() const
{
	return elem;
}
template<typename T, typename A>
Iterator<vector<T, A>> vector<T, A>::end()
{
	return elem + sz;
}

template<typename T, typename A>
Const_Iterator<vector<T, A>> vector<T, A>::end() const
{
	return elem + sz;
}


template<typename C>
using Size_type = typename C::size_type;

template<typename T, typename A>
Size_type<vector<T,A>> vector<T, A>::size() const
{
	return sz;
}

template<typename T, typename A>
Size_type<vector<T, A>> vector<T, A>::capacity() const
{
	return space;
}

template<typename T, typename A>
void vector<T, A>::reserve(size_type newalloc)
{
	if (newalloc <= space)					//永远不会减少分配的空间
		return;
	T* p = alloc.allocate(newalloc);	//分配新空间
	for (size_type i = 0; i < sz; ++i)
		alloc.construct(&p[i], elem[i]);		//拷贝现有元素
	for (size_type i = 0; i < sz; ++i)
		alloc.destroy(&elem[i]);			//销毁现有元素
	alloc.deallocate(elem, space);			//释放旧空间
	elem = p;
	space = newalloc;
}


template<typename T, typename A>
void vector<T, A>::resize(size_type newsize, T def)
//令 vector 有 newsize 个元素
//newsize 必须 >= 0
//用默认值 def 初始化每个新元素
{
	//我们保证 size_type 是无符号数
	/*if (newsize < 0)
		throw Invalid{};*/
	reserve(newsize);
	for (size_type i = newsize; i < sz; ++i)
		alloc.destroy(elem + i);			//销毁从newsize开始的元素
	for (size_type i = sz; i < newsize; ++i)
		alloc.construct(&elem[i], def);		//用默认值初始化
	sz = newsize;
}

template<typename T, typename A>
void vector<T, A>::push_back(const T& val)
//将 vector 的大小增加1:用 val 初始化新元素
{
	if (space == 0)
		reserve(first_expand_space);
	else if (sz >= space)
		reserve(space * 2);
	alloc.construct(&elem[sz], val);
	++sz;
}

template<typename T, typename A>
Iterator<vector<T,A>> vector<T, A>::insert(iterator p, const T& val)
{
	size_type index = p - begin();	//这个必须在reserve()之前,因为reserve()之后元素会移到新内存中,迭代器 p 会失效,因此必须记住元素位置索引
	if (size() == capacity())
		reserve(size() == 0 ? first_expand_space : size() << 1);	//确保有足够的空间
	alloc.construct(elem + sz, back());		//先把最后一个元素创建到未初始化的空间(必须)
	++sz;
	iterator pp = begin() + index;
	for (auto pos = end() - 1; pos != pp; --pos)
		*pos = *(pos - 1);
	*pp = val;
	return pp;
}

template<typename T, typename A>
Iterator<vector<T, A>> vector<T, A>::erase(iterator p)
{
	if (p != end())
	{
		for (auto pos = p + 1; pos != end(); ++pos)
			*(pos - 1) = *pos;
		alloc.destroy(&*(end() - 1));
		--sz;
	}
	return p;
}

template<typename T, typename A>
T& vector<T, A>::operator[](size_type n)
{
	return elem[n];
}

template<typename T, typename A>
const T& vector<T, A>::operator[](size_type n) const
{
	return elem[n];
}

template<typename T, typename A>
T& vector<T, A>::at(size_type n)
{
	if (n < 0 || sz <= n)
		throw out_of_range();
	return elem[n];
}

template<typename T, typename A>
const T& vector<T, A>::at(size_type n) const
{
	if (n < 0 || sz <= n)
		throw out_of_range();
	return elem[n];
}

template<typename T, typename A>
T& vector<T, A>::front()
{
	if (begin() == end())
		throw Invalid{};
	return *elem;
}

template<typename T, typename A>
T& vector<T, A>::back()
{
	if (begin() == end())
		throw Invalid{};
	return *(elem + sz - 1);
}

template<typename T, typename A>
const T& vector<T, A>::front() const
{
	if (begin() == end())
		throw Invalid{};
	return *elem;
}

template<typename T, typename A>
const T& vector<T, A>::back() const
{
	if (begin() == end())
		throw Invalid{};
	return *(elem + sz - 1);
}

template<typename T, typename A>
vector<T, A>::~vector()
{
	for (size_type i = 0; i < sz; ++i)
		alloc.destroy(elem + i);		//释放之前要销毁对象元素
	alloc.deallocate(elem, space);
}


//下面是 range_check_iterator 定义
template<typename T, typename A>
class vector<T, A>::range_check_iterator {
	iterator curr;
	const vector<T, A>& rvec;	//用于提供begin()和end()
public:
	range_check_iterator(const iterator p, const vector<T,A>& rv)
		:curr{ p }, rvec{ rv }
	{ if (p - rv.begin() < 0 || rv.end() - p < 0) throw out_of_range{}; }
	
	T& operator[](size_type i);
	const T& operator[](size_type i) const;
	T& operator*() { return curr->val; }
	const T& operator*() const { return curr->val; }
	T* operator->() { return &curr->val; }

	range_check_iterator& operator++();
	range_check_iterator& operator--();
	range_check_iterator& operator+=(size_type n);
	range_check_iterator operator+(size_type n);
	range_check_iterator& operator-=(size_type n);
	range_check_iterator operator-(size_type n);
	long operator-(const range_check_iterator& it2);

	bool operator==(range_check_iterator const& other) const { return curr == other.curr; }
	bool operator!=(range_check_iterator const& other) const { return !(*this == other); }
};

template<typename T, typename A>
T& vector<T, A>::range_check_iterator::operator[](size_type i)
{
	if (i >= rvec.end() - curr)
		throw out_of_range{};
	return *(curr + i);
}

template<typename T, typename A>
const T& vector<T, A>::range_check_iterator::operator[](size_type i) const
{
	if (i >= rvec.end() - curr)
		throw out_of_range{};
	return *(curr + i);
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator& vector<T, A>::range_check_iterator::operator++()
{
	if (curr == rvec.end() || curr > rvec.end() || curr < rvec.begin())
		throw out_of_range{};
	++curr;
	return *this;
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator& vector<T, A>::range_check_iterator::operator--()
{
	if (curr == rvec.begin() || curr < rvec.begin() || curr > rvec.end())
		throw out_of_range{};
	--curr;
	return *this;
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator vector<T, A>::range_check_iterator::operator+(size_type n)
{
	if (n > rvec.end() - curr)
		throw out_of_range{};
	return range_check_iterator(curr + n, rvec);
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator& vector<T, A>::range_check_iterator::operator+=(size_type n)
{
	if (n > rvec.end() - curr)
		throw out_of_range{};
	curr += n;
	return *this;
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator vector<T, A>::range_check_iterator::operator-(size_type n)
{
	if (n > curr - rvec.begin())
		throw out_of_range{};
	return range_check_iterator(curr - n, rvec);
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator& vector<T, A>::range_check_iterator::operator-=(size_type n)
{
	if (n > curr - rvec.begin())
		throw out_of_range{};
	curr -= n;
	return *this;
}

//对指向同一序列的两个迭代器进行减法操作来得到它们的距离。
template<typename T, typename A>
long vector<T, A>::range_check_iterator::operator-(const range_check_iterator& it2)
{
	return curr - it2.curr;
}

15.2 and 15.3

#include"../../std_lib_facilities.h"

#define BUFSIZE 50

double* get_from_jack(int* count);
vector<double>* get_from_jill();
double* high_v1(double* first, double* last);
double* high_v2(double data[], int size);

void fct()
{
	int jack_count = 0;
	double* jack_data = get_from_jack(&jack_count);
	vector<double>* jill_data = get_from_jill();
	vector<double>& v = *jill_data;

	//double* jack_high = high_v1(jack_data, jack_data + jack_count);
	double* jack_high = high_v2(jack_data, jack_count);
	double* jill_high = high_v1(&v[0], &v[0] + v.size());
	cout << "Jack's max: " << *jack_high
		<< "; Jill's max: " << *jill_high << endl;
	delete[] jack_data;
	delete jill_data;
}

double* get_from_jack(int* count)
{
	//简单的实现从文件中读取double类型数据
	ifstream ifs{ "jack.txt" };
	if (!ifs)
		error("file open failed");
	double* temp = nullptr;
	double* retd = new double[BUFSIZE];
	int cnt = 0, i = 0;
	double d;
	while (ifs >> d)
	{
		if (i >= BUFSIZE)
		{
			temp = retd;
			retd = new double[cnt + i];	//每次都扩大BUFSIZE大小
			for (int j = 0; j < cnt; ++j)
				retd[j] = temp[j];
			i = 0;
			delete[] temp;
		}
		retd[cnt] = d;
		++cnt;
		++i;
	}
	*count = cnt;
	return retd;
}

vector<double>* get_from_jill()
{
	ifstream ifs{ "jill.txt" };
	if (!ifs)
		error("open file");
	vector<double>* retv = new vector<double>;
	double d;
	while (ifs >> d)
		retv->push_back(d);
	return retv;
}

double* high_v1(double* first, double* last)
//返回一个指针,指向[first,last)中值最大的元素
{
	if (first == nullptr)
	{
		cout << "empty data set\n";
		return nullptr;
	}
	double h = *first;
	double* high = first;
	for(double* p = first + 1; p < last; ++p)
		if (h < *p)
		{
			high = p;
			h = *p;
		}
	return high;
}

double* high_v2(double data[], int size)
{
	if (size <= 0)
	{
		cerr << "empty data set\n";
		return nullptr;
	}
	double* high = &data[0];
	double h = data[0];
	for (int i = 1; i < size; ++i)
		if (h < data[i])
		{
			high = data + i;
			h = data[i];
		}
	return high;
}

int main()
try
{
	fct();
	return 0;
}
catch (runtime_error& e)
{
	cerr << "Runtime error: " << e.what() << endl;
	return 1;
}
catch (...)
{
	cerr << "Exception occured\n";
	return 2;
}

15.4

high() 函数没有判断迭代器背后的序列是否为空序列,如果贸然解引用,可能会引用空指针导致报错

15.5 为 vector 定义输入和输出运算符

#include"../../std_lib_facilities.h"

template<typename T>
	//要求T是可以有 >> 定义的类型
istream& operator>>(istream& is, vector<T>& v)
{
	T t;
	while (is >> t)
		v.push_back(t);
	return is;
}

template<typename T>
//要求T是可以有 >> 定义的类型
ostream& operator<<(ostream& os, const vector<T>& v)
{
	for (const T& t : v)
		os << t << '\n';
	return os;
}

int main()
try
{
	vector<double>v;
	cin >> v;
	cout << v;
	return 0;
}
catch (runtime_error& e)
{
	cerr << "Runtime error: " << e.what() << endl;
	return 1;
}
catch (...)
{
	cerr << "Exception occured\n";
	return 2;
}

15.6 find_replace()

//查找并替换文档中的字符串,具体见Document.h, Document.cpp
//练习15_6:find_replace()和find_replace_all()函数
Text_iterator Document::find_replace(Text_iterator first, Text_iterator last, const string& find_str, const string& repl_str)
//只替换第一个查找到的字符串
{
	//int rs_sz = repl_str.size();
	Text_iterator pos = find_txt(first, last, find_str);
	if (pos != last)
	{
		string::const_iterator fs_it = find_str.begin();
		string::const_iterator rs_it = repl_str.begin();
		while (fs_it != find_str.end() && rs_it != repl_str.end())
		{
			if (*fs_it != *rs_it)	//如果字符不相等, 则替换
			{
				*pos = *rs_it;
				if (*fs_it == '\n')			//如果被替换的字符是换行符,那么需要将下一行合并上来
					pos = concat_line(pos);
				else if (*rs_it == '\n')	//如果替换的字符是换行符,那么需要将该行的换行符后面所有字符开辟为新行
					pos = break_line(pos);
			}
			++pos;
			++fs_it;
			++rs_it;
		}
		while (fs_it != find_str.end())	//如果被替换的字符比替换字符长,那么需要将剩余被替换字符删除
		{
			pos = erase(pos);
			++fs_it;
		}
		while (rs_it != repl_str.end())	//如果被替换的字符比替换字符短,那么需要将剩余替换字符插入
		{
			pos = insert(pos, *rs_it);
			++pos;
			++rs_it;
		}
	}
	//advance(pos, -rs_sz);	//往前找完成替换操作后的替换字符串首字符
	return pos;
}

void Document::find_replace_all(Text_iterator first, Text_iterator last, const string& find_str, const string& repl_str)
//替换所有查找到的字符串
{
	Text_iterator pos = first;
	do {
		pos = find_replace(pos, last, find_str, repl_str);
	} while (pos != last);
}

15.6 chapter20_ex06_in.txt

Lorem ipsum dolor sit amet, consectetur adipiscing
elit. Etiam molestie id tortor a mollis. Morbi
dapibus, nulla nec porttitor iaculis, enim massa
posuere lorem, sed placerat orci tortor quis leo.
Donec pretium metus at turpis facilisis vestibulum.
Nulla tristique ornare pharetra. Donec in est
mollis nisi fring!illa consequat euismod a odio.
Mauris sit amet sem ac justo pretium sollicitudin
et nec urna. Morbi ut dia’m hendrerit ipsum faucibus
pellentesque. Sed tempor lacus nibh, et pulvinar
nisi pulvinar quis. Mauris id semper tortor. Proin
eget facilisis dui. Quisque faucibus ut sem eget
faucibus. Praesent mauris metus, elementum in
maximus non, consequat vitae nibh. Maecenas et mi
quis mi imperdiet tempor vel sed risus.
alpha.numeric as12b

15.7

#include"../../std_lib_facilities.h"

template<typename Iterator>
Iterator high(Iterator first, Iterator last)
//返回指向[first,last)中最大元素的迭代器,元素必须能够应用 > 比较操作符
{
	if (first == last)	//empty sequence
		return last;
	Iterator high = first;
	for (Iterator p = first; p != last; ++p)
		if (*p > * high)
			high = p;
	return high;
}

int main()
try
{
	vector<string>v{ "Jack","Jill", "jack","jill", "ewr", "ewR"};
	vector<string>::iterator h = high(v.begin(),v.end());
	cout << "Highest string in vector is " << *h << endl;
	return 0;
}
catch (runtime_error& e)
{
	cerr << "Runtime error: " << e.what() << endl;
	return 1;
}
catch (...)
{
	cerr << "Exception occured\n";
	return 2;
}

15.8

int cnt_char(Document& d)
{
	int cnt = 0;
	for (auto p = d.begin(); p != d.end(); ++p)
		cnt++;
	return cnt;
}

15.9 and 15.10

//15_9 统计单词数
int cnt_word_v1(Document& d)
//单词是以空白符分隔的字符序列
{
	int cnt{ 0 };
	bool in_word{ false };
	for (auto p : d)
	{
		if (isspace(p))
		{
			if (in_word)
			{
				in_word = false;
				++cnt;
			}
		}
		else
			in_word = true;
	}
	return cnt;
}

int cnt_word_v2(Document& d)
//单词是一个连续的字母序列
{
	int cnt{ 0 };
	bool in_word{ false };
	for (auto p : d)
	{
		if (!isalpha(p))
		{
			if (in_word)
			{
				in_word = false;
				++cnt;
			}
		}
		else
			in_word = true;
	}
	return cnt;
}

static bool in_space_set(const char ch, const vector<char>& space_set)
{
	for (const char sp : space_set)
		if (ch == ch)
			return true;
	return false;
}

//15_10 统计单词数,用户可以指定空白符集合
int cnt_word_v3(Document& d, const vector<char>& space_set)
//单词是以用户指定的空白符分隔的字符序列
{
	int cnt{ 0 };
	bool in_word{ false };
	for (auto p : d)
	{
		if (in_space_set(p, space_set))
		{
			if (in_word)
			{
				in_word = false;
				++cnt;
			}
		}
		else
			in_word = true;
	}
	return cnt;
}

15.11

#include"../../std_lib_facilities.h"

template<typename T>
//要求T是可以有 >> 定义的类型
ostream& operator<<(ostream& os, const vector<T>& v)
{
	for (const T& t : v)
		os << t << '\n';
	return os;
}

vector<double> list2vector(list<int>& lst)
{
	vector<double>vec;
	for (int i : lst)
		vec.push_back(static_cast<double>(i));
	return vec;
}

int main()
try
{
	list<int> lst{ 9,8,7,6,5,0,1,2,3,4 };
	vector<double>vec = list2vector(lst);
	//验证拷贝操作的完整性与正确性
	if (lst.size() != vec.size())
		cout << "Uncomplete copy\n";
	else
	{
		auto pl = lst.begin();
		auto pv = vec.begin();
		while (pl != lst.end())
		{
			if (static_cast<double>(*pl) != *pv)
			{
				cout << "Uncorrect copy\n";
				break;
			}
			++pl;
			++pv;
		}
	}
	sort(vec.begin(), vec.end());
	cout << vec;
	return 0;
}
catch (runtime_error& e)
{
	cerr << "Runtime error: " << e.what() << endl;
	return 1;
}
catch (...)
{
	cerr << "Exception occured!\n";
	return 2;
}

15.12 and 15.13 list

15.12 list_tail.h

该 list 有一个尾后位置的Link节点

#include<iostream>

template<typename Elem>
struct Link {
	Elem val;
	Link* pred;
	Link* succ;

	Link() :pred{ nullptr }, succ{ nullptr }{}
	Link(const Elem& v) :val{v}, pred{ nullptr }, succ{ nullptr }{}
};


template<typename Elem>
class list {
private:
	int sz;
	Link<Elem>* first;
	Link<Elem>* last;	//指向尾元素之后

public:
	class iterator;	//成员类型:迭代器

	list() :sz{0}, first { new Link<Elem>{} }, last{ first }{}		//默认构造函数
	~list();														//析构函数

	iterator begin() { return iterator{ first }; }	//指向首元素的迭代器
	iterator end() { return iterator{ last }; }		//指向尾元素之后的迭代器

	iterator insert(iterator p, const Elem& v);		//将 v 插入链表中 p 的位置
	iterator erase(iterator p);						//从链表中删除 p

	void push_back(const Elem& v);		//将 v 插入链表末尾
	void push_front(const Elem& v);		//将 v 插入链表末头
	void pop_back();		//删除尾元素
	void pop_front();		//删除首元素

	Elem& front();			//获取首元素
	Elem& back();			//获取尾元素

	int size() const { return sz; }
};

template<typename Elem>
class list<Elem>::iterator {
	Link<Elem>* curr;	//当前链接
public:
	iterator(Link<Elem>* p) :curr{ p } {}

	iterator& operator++()
	{	curr = curr->succ; return *this;	}
	iterator& operator--()
	{	curr = curr->pred; return *this;	}

	Elem& operator*() { return curr->val; }
	Elem* operator->() { return &(curr->val); }	//如果*(iter).m 有效,则可以使用iter->m 简写形式

	bool operator==(const iterator& b) const
	{	return curr == b.curr;	}
	bool operator!=(const iterator& b) const
	{	return curr != b.curr;	}

	friend iterator list<Elem>::insert(iterator p, const Elem& v);		//将 v 插入链表中 p 的位置
	friend iterator list<Elem>::erase(iterator p);						//从链表中删除 p
};


template<typename Elem>
typename list<Elem>::iterator list<Elem>::insert(iterator p, const Elem& v)
//将 v 插入链表中 p 的位置
{
	Link<Elem>* pnode = new Link<Elem>(v);

	pnode->succ = p.curr;
	iterator q = p;
	if (first == q.curr)
	{
		first = pnode;
		pnode->pred = nullptr;
	}
	else {
		--q;
		pnode->pred = q.curr;
		(q.curr)->succ = pnode;
	}
	(p.curr)->pred = pnode;
	++sz;
	return iterator(pnode);
}

template<typename Elem>
typename list<Elem>::iterator list<Elem>::erase(iterator p)
//从链表中删除 p
{
	if (first == last)
		return end();
	if (p == end())
		return end();
	iterator q = p;
	++q;
	if (p == begin())
	{
		first = p.curr->succ;
		q.curr->pred = nullptr;
	}
	else
	{
		p.curr->pred->succ = q.curr;
		q.curr->pred = p.curr->pred;
	}
	delete p.curr;
	--sz;
	return q;
}

template<typename Elem>
void list<Elem>::push_back(const Elem& v)
//将 v 插入链表末尾
{
	Link<Elem>* pnode = new Link<Elem>(v);
	if (first == last)
		first = pnode;
	else
		last->pred->succ = pnode;
	pnode->succ = last;
	pnode->pred = last->pred;
	last->pred = pnode;
	++sz;
}

template<typename Elem>
void list<Elem>::push_front(const Elem& v)
//将 v 插入链表头
{
	Link<Elem>* pnode = new Link<Elem>(v);
	pnode->pred = nullptr;
	pnode->succ = first;
	first->pred = pnode;
	first = pnode;
	++sz;
}

template<typename Elem>
void list<Elem>::pop_back()
//删除尾元素
{
	if (first == last)
		return;
	Link<Elem>* p = last->pred;
	if (p == first)
	{
		last->pred = nullptr;
		first = last;
	}
	else
	{
		last->pred = p->pred;
		p->pred->succ = last;
	}
	delete p;
	--sz;
}

template<typename Elem>
void list<Elem>::pop_front()
//删除首元素
{
	if (first == last)
		return;
	Link<Elem>* p = first;
	first->succ->pred = nullptr;
	first = first->succ;
	delete p;
	--sz;
}

template<typename Elem>
Elem& list<Elem>::front()
//获取首元素
{
	if (first == last)
	{
		std::cout << "No element\n";
		return last->val;
	}
	return first->val;
}

template<typename Elem>
Elem& list<Elem>::back()
//获取尾元素
{
	if (first == last)
	{
		std::cout << "No element\n";
		return last->val;
	}
	return last->pred->val;
}

template<typename Elem>
list<Elem>::~list()
{
	Link<Elem>* p, * temp;
	for (p = first; p;)
	{
		temp = p;
		p = p->succ;
		delete temp;
	}
}

15.13 list_notail.h

该 list 没有尾后位置的Link节点,用 nullptr 代表 end()

#include<iostream>

template<typename Elem>
struct Link {
	Elem val;
	Link* pred;
	Link* succ;

	Link() :pred{ nullptr }, succ{ nullptr }{}
	Link(const Elem& v) :val{ v }, pred{ nullptr }, succ{ nullptr }{}
};


//双向链表,header是链表第一个节点,最后一个节点的succ指向 nullptr == end()
template<typename Elem>
class list {
private:
	//int sz;	//为了满足13题的要求,去掉这个size
	Link<Elem>* header;

public:
	class out_of_range;
	class iterator;	//成员类型:迭代器

	//list() :sz{ 0 }, header{ nullptr }{}		//默认构造函数
	list() : header{ nullptr }{}		//默认构造函数
	~list();							//析构函数

	iterator begin() { return iterator{ header }; }	//指向首元素的迭代器
	iterator end() { return iterator{ nullptr }; }		//指向尾元素之后的迭代器

	iterator insert(iterator p, const Elem& v);		//将 v 插入链表中 p 的位置
	iterator erase(iterator p);						//从链表中删除 p

	void push_back(const Elem& v);		//将 v 插入链表末尾
	void push_front(const Elem& v);		//将 v 插入链表末头
	void pop_back();		//删除尾元素
	void pop_front();		//删除首元素

	Elem& front();			//获取首元素
	Elem& back();			//获取尾元素

	//int size() const { return sz; }
};

template<typename Elem>
class list<Elem>::out_of_range {};

template<typename Elem>
class list<Elem>::iterator {
	Link<Elem>* curr;	//当前链接
public:
	iterator(Link<Elem>* p) :curr{ p } {}

	iterator& operator++();
	iterator& operator--();

	Elem& operator*() { return curr->val; }
	Elem* operator->() { return &(curr->val); }	//如果*(iter).m 有效,则可以使用iter->m 简写形式
	
	bool operator==(const iterator& b) const
	{
		return curr == b.curr;
	}
	bool operator!=(const iterator& b) const
	{
		return curr != b.curr;
	}

	friend iterator list<Elem>::insert(iterator p, const Elem& v);		//将 v 插入链表中 p 的位置
	friend iterator list<Elem>::erase(iterator p);						//从链表中删除 p
};

//双向循环链表特性,针对begin()的--和end()的++都返回nullptr
template<typename Elem>
typename list<Elem>::iterator& list<Elem>::iterator::operator++()
{
	if(curr != nullptr)
		curr = curr->succ;
	return *this;
}

template<typename Elem>
typename list<Elem>::iterator& list<Elem>::iterator::operator--()
{
	if (curr != nullptr)
		curr = curr->pred;
	return *this;
}

template<typename Elem>
typename list<Elem>::iterator list<Elem>::insert(iterator p, const Elem& v)
//将 v 插入链表中 p 的位置
{
	Link<Elem>* pnode = new Link<Elem>(v);

	if (begin() == end())	//空链表
	{
		pnode->pred = nullptr;
		pnode->succ = nullptr;
	}
	else if (p == end())	//如果是end(),则不插入
	{
		auto q = header;
		while (q->succ)
			q = q->succ;
		q->succ = pnode;
		pnode->pred = q;
	}
	else
	{
		pnode->succ = p.curr;
		if(p.curr->pred)
			p.curr->pred->succ = pnode;
		pnode->pred = p.curr->pred;
		p.curr->pred = pnode;
		if (p == begin())
			header = pnode;
	}
	//++sz;
	return iterator(pnode);
}

template<typename Elem>
typename list<Elem>::iterator list<Elem>::erase(iterator p)
//从链表中删除 p
{
	if (begin() == end())
		return end();
	if (p == end())
		return end();

	Link<Elem>* t = p.curr->succ;
	if(t != nullptr)
		t->pred = p.curr->pred;
	if (p == begin())
		header = t;
	else
		p.curr->pred->succ = t;
	delete p.curr;
	//--sz;
	return iterator{t};
}

template<typename Elem>
void list<Elem>::push_back(const Elem& v)
//将 v 插入链表末尾
{
	Link<Elem>* pnode = new Link<Elem>(v);
	if (begin() == end())	//如果为空链表
		header = pnode;
	else
	{
		auto q = header;
		while (q->succ)
			q = q->succ;
		q->succ = pnode;
		pnode->pred = q;
	}
	//++sz;
}

template<typename Elem>
void list<Elem>::push_front(const Elem& v)
//将 v 插入链表头
{
	Link<Elem>* pnode = new Link<Elem>(v);
	if (begin() != end())	//如果不为空链表
	{
		pnode->succ = header;
		pnode->pred = header->pred;
		header->pred = pnode;
	}
	header = pnode;
	//++sz;
}

template<typename Elem>
void list<Elem>::pop_back()
//删除尾元素
{
	if (begin() == end())
		return;
	Link<Elem>* p = header;
	while (p->succ)
		p = p->succ;
	if (p == header)
		header = nullptr;
	else
		p->pred->succ = nullptr;
	delete p;
	//--sz;
}

template<typename Elem>
void list<Elem>::pop_front()
//删除首元素
{
	if (begin() == end())
		return;
	Link<Elem>* p = header;
	if (header->succ != nullptr)	//如果链表不止一个结点
		header->succ->pred = header->pred;
	header = header->succ;
	delete p;
	//--sz;
}

template<typename Elem>
Elem& list<Elem>::front()
//获取首元素
{
	if (begin() == end())
		throw out_of_range{};
	return header->val;
}

template<typename Elem>
Elem& list<Elem>::back()
//获取尾元素
{
	if (begin() == end())
		throw out_of_range{};
	Link<Elem>* p = header;
	while (p->succ)
		p = p->succ;
	return p->val;
}

template<typename Elem>
list<Elem>::~list()
{
	Link<Elem>* p, * temp;
	for (p = header; p;)
	{
		temp = p;
		p = p->succ;
		delete temp;
	}
}

main.cpp 测试两个list

//#include"List_naive.h"
//#include"List_Circular.h"
#include"List.h"

using std::cout;

template<typename Iter>
Iter high(Iter first, Iter last)
{
	Iter high = first;
	for (Iter p = first; p != last; ++p)
		if (*high < *p)
			high = p;
	return high;
}

int main()
{
    list<int> li1;
    //std::cout << "Empty list size: " << li1.size() << '\n';

    list<char> lc1;
    lc1.push_front('a');
    lc1.push_back('c');
    lc1.push_front('j');
    lc1.push_back('o');
    lc1.push_back('b');

    cout << "lc1: front = " << lc1.front() << " back = " << lc1.back() << '\n';

    auto pi = lc1.begin();
    ++pi; ++pi; ++pi;
    lc1.insert(pi, 'k');
    lc1.insert(lc1.begin(), 'A');
    lc1.insert(lc1.end(), 'Z');

    for (auto a : lc1)
        std::cout << a << ' ';
    std::cout << '\n';

    pi = lc1.begin();
    lc1.erase(pi);
    for (auto a : lc1)
        std::cout << a << ' ';
    std::cout << '\n';

    pi = lc1.end();
    lc1.erase(pi);
    for (auto a : lc1)
        std::cout << a << ' ';
    std::cout << '\n';

    //下面这项测试无法在没有真尾后位置的list中实现
    /*--pi; --pi;
    pi = lc1.erase(pi);
    for (auto a : lc1)
        std::cout << a << ' ';
    std::cout << '\n';
    cout << "now *pi = " << *pi << '\n';*/
    
    pi = lc1.begin();
    do {
        cout << "before erase(pi), *pi = " << *pi << '\n';
        //cout << "size of lc1 = " << lc1.size() << '\n';
    } while ((pi = lc1.erase(pi)) != lc1.end());

    list<char> lc2;
    lc2.push_back('o');
    lc2.push_back('r');
    lc2.push_back('a');
    lc2.push_front('n');

    for (auto a : lc2)
        std::cout << a << ' ';
    std::cout << '\n';


    lc2.pop_back();
    lc2.pop_front();
    lc2.pop_front();
    lc2.pop_front();
    lc2.pop_front();
    lc2.pop_back();
    for (auto a : lc2)
        std::cout << a << ' ';
    std::cout << '\n';

	list<int>lst;
	for (int x; std::cin >> x;)
		lst.push_front(x);
	list<int>::iterator p = high(lst.begin(), lst.end());
	std::cout << "the highest value was " << *p << '\n';
	return 0;
}

15.14

懒得实现了,list 中的 insert 操作在 slist 中变成向 iterator p 的位置后面插入。其他的操作其实都可以存在,只不过erase操作变得麻烦一些罢了

15.15 pvector

//#include"../../std_lib_facilities.h"
#include"Vector.h"

// pvector<Elem> == vector<Elem *>
template<typename Elem>
class pvector {
	vector<Elem*> pelem;
public:
	using size_type = unsigned long;
	using value_type = Elem*;
	using iterator = typename vector<Elem*>::iterator;
	using const_iterator = typename vector<Elem*>::const_iterator;

	pvector() :pelem{} {}		//默认构造函数
	explicit pvector(size_type sz) :pelem{vector<Elem*>(sz)} {}
	//暂不支持拷贝操作,因为这会有两个及以上pvector的元素指向对象,一个或以上的pvector析构时会造成重复释放,其他pvector指向非法对象等问题
	//pvector(const pvector& pv) :pelem{ pv.pelem } {}
	//移动操作可以,但我没有实现

	~pvector();					//析构函数,会对每个指针指向的对象进行delete操作

	iterator begin() { return pelem.begin(); }
	const_iterator begin() const { return pelem.begin(); }
	iterator end() { return pelem.end(); }
	const_iterator end() const { return pelem.end(); }

	Elem* operator[](size_type i) { return pelem[i]; }
	const Elem* operator[](size_type i) const { return pelem[i]; }

	size_type size() const { return pelem.size(); }
	size_type capacity() const { return pelem.capacity(); }
	void reserve(size_type newalloc) { pelem.reserve(newalloc); }
	void resize(size_type newalloc, Elem* def = nullptr) { pelem.resize(newalloc, def); }
	void push_back(Elem* pval) { pelem.push_back(pval); }
	iterator insert(iterator p, Elem* pval) { return pelem.insert(p, pval); }
	iterator erase(iterator p) { return pelem.erase(p); }
};

template<typename Elem>
pvector<Elem>::~pvector()
//析构函数,会对每个指针指向的对象进行delete操作
{
	for (iterator p = begin(); p != end(); ++p)
	{
		std::cout << "Deleting " << **p << "\n";		//测试
		delete (*p);
	}
}

// test pvector
void f1()
{
	pvector<int> pv;
	for (int i = 0; i < 10; ++i) {
		pv.push_back(new int{i});
	}
	for (pvector<int>::size_type i = 0; i < pv.size(); ++i)
		std::cout << *pv[i] << "\n"; // test [] - requires dereference
}

int main()
{
	f1();
	
	return 0;
}

15.16 ovector

#include"../../std_lib_facilities.h"
//#include"Vector.h"

// ovector<Elem> == vector<Elem *>
template<typename Elem>
class ovector {
	vector<Elem*> pelem;
public:
	using size_type = unsigned long;
	using value_type = Elem*;

	class iterator;
	class const_iterator;

	ovector() :pelem{} {}		//默认构造函数
	explicit ovector(size_type sz) :pelem{ vector<Elem*>(sz) } {}
	//暂不支持拷贝操作,因为这会有两个及以上ovector的元素指向对象,一个或以上的ovector析构时会造成重复释放,其他ovector指向非法对象等问题
	//ovector(const ovector& pv) :pelem{ pv.pelem } {}
	//移动操作可以,但我没有实现

	~ovector();					//析构函数,会对每个指针指向的对象进行delete操作

	iterator begin() { return pelem.begin(); }
	const_iterator begin() const { return pelem.begin(); }
	iterator end() { return pelem.end(); }
	const_iterator end() const { return pelem.end(); }

	Elem& operator[](size_type i) { return *pelem[i]; }
	const Elem& operator[](size_type i) const { return *pelem[i]; }

	size_type size() const { return pelem.size(); }
	size_type capacity() const { return pelem.capacity(); }
	void reserve(size_type newalloc) { pelem.reserve(newalloc); }
	void resize(size_type newalloc, Elem* def = nullptr) { pelem.resize(newalloc, def); }
	void push_back(Elem* pval) { pelem.push_back(pval); }
	iterator insert(iterator p, Elem* pval) { return pelem.insert(p, pval); }
	iterator erase(iterator p) { return pelem.erase(p); }
};

template<typename Elem>
ovector<Elem>::~ovector()
//析构函数,会对每个指针指向的对象进行delete操作
{
	for (iterator p = begin(); p != end(); ++p)
	{
		std::cout << "Deleting " << *p << "\n";		//test
		delete &(*p);	//这里的释放应该有所变化
	}
}

template<typename Elem>
class ovector<Elem>::iterator {
	typename vector<Elem*>::iterator iter;
public:
	iterator(const iterator& it) :iter{ it } {}
	iterator(const typename vector<Elem*>::iterator& it) :iter{ it } {}

	iterator& operator++() { ++iter; return *this; }
	iterator& operator--() { ++iter; return *this; }
	bool operator==(const iterator& it) const { return it.iter == iter; }
	bool operator!=(const iterator& it) const { return it.iter != iter; }
	// * 运算符返回元素所指向的对象的引用,而不是返回指针
	Elem& operator*() { return **iter; }
};

template<typename Elem>
class ovector<Elem>::const_iterator {
	typename vector<Elem*>::const_iterator citer;
public:
	const_iterator(const_iterator& it) : citer{ it } {}
	const_iterator(typename vector<Elem*>::const_iterator& it) : citer{ it } {}

	const_iterator& operator++() { ++citer; return *this; }
	const_iterator& operator--() { ++citer; return *this; }
	bool operator==(const_iterator& it) const { return it.citer == citer; }
	bool operator!=(const_iterator& it) const { return it.citer != citer; }
	// * 运算符返回元素所指向的对象的引用,而不是返回指针
	Elem& operator*() { return **citer; }
};

// test ovector
void f2()
{
	ovector<double> ov;
	for (int i = 0; i < 10; ++i)
		ov.push_back(new double(i * 1.1));
	for (typename ovector<double>::size_type i = 0; i < ov.size(); ++i)
		std::cout << ov[i] << "\n";  // test [] - no dereference required

	ovector<double>::iterator it = ov.begin();
	while (it != ov.end()) {
		std::cout << *it << ' '; // test * - no second dereference required
		++it;
	}
	std::cout << "\n";
}

int main()
{
	f2();

	return 0;
}

15.17 ownership_vector

//#include"../../std_lib_facilities.h"
#include"Vector.h"

// ownership_vector<Elem> == vector<Elem *>
template<typename Elem>
class ownership_vector {
	vector<Elem*> pelem;
	vector<bool> ownership;
public:
	using size_type = unsigned long;
	using value_type = Elem*;
	using iterator = typename vector<Elem*>::iterator;
	using const_iterator = typename vector<Elem*>::const_iterator;

	ownership_vector() :pelem{}, ownership{} {}		//默认构造函数
	explicit ownership_vector(size_type sz) :pelem{ vector<Elem*>(sz) }, ownership{ vector<bool>(sz) }{}
	//暂不支持拷贝操作,因为这会有两个及以上ownership_vector的元素指向对象,一个或以上的ownership_vector析构时会造成重复释放,其他ownership_vector指向非法对象等问题
	//ownership_vector(const ownership_vector& pv) :pelem{ pv.pelem } {}
	//移动操作可以,但我没有实现

	~ownership_vector();					//析构函数,会对每个为向量所有的对象进行delete操作

	iterator begin() { return pelem.begin(); }
	const_iterator begin() const { return pelem.begin(); }
	iterator end() { return pelem.end(); }
	const_iterator end() const { return pelem.end(); }

	Elem* operator[](size_type i) { return pelem[i]; }
	const Elem* operator[](size_type i) const { return pelem[i]; }

	size_type size() const { return pelem.size(); }
	size_type capacity() const { return pelem.capacity(); }
	
	void reserve(size_type newalloc) { pelem.reserve(newalloc); ownership.reserve(newalloc); }
	void resize(size_type newalloc, Elem* def = nullptr) { pelem.resize(newalloc, def); ownership.resize(newalloc, false); }
	
	//根据迭代器或者索引判断该对象是否为向量所有
	bool is_owner(const_iterator p) const { size_type index = p - begin(); return ownership[index]; }
	bool is_owner(size_type index) const { return ownership[index]; }

	//用户在添加元素时,可以选择该元素对象是否为向量所有
	void push_back(Elem* pval, bool owner) { pelem.push_back(pval); ownership.push_back(owner); }
	iterator insert(iterator p, Elem* pval, bool owner)
	{ 
		ownership.insert(ownership.begin() + (p - begin()), owner); 
		return pelem.insert(p, pval);
	}
	iterator erase(iterator p) 
	{ 
		ownership.erase(ownership.begin() + (p - begin()));
		return pelem.erase(p);
	}
};

template<typename Elem>
ownership_vector<Elem>::~ownership_vector()
//析构函数,会对每个指针指向的对象进行delete操作
{
	for (iterator p = begin(); p != end(); ++p)
	{
		std::cout << "Object: " << **p;
		if (is_owner(p))	//只有为向量所有的对象才释放
		{
			std::cout << "  Owner, delete!";		
			delete (*p);
		}
		std::cout << '\n';
	}
}

// test ownership_vector
void f3()
{
	ownership_vector<int> osv;
	
	osv.push_back((new int{2}), true);
	osv.push_back((new int{3}), false);
	osv.push_back((new int{4}), false);
	osv.push_back((new int{5}), true);
	osv.push_back((new int{6}), true);
	osv.insert(osv.begin(), (new int{ 1 }), false);

	for (ownership_vector<int>::size_type i = 0; i < osv.size(); ++i)
	{
		std::cout << *osv[i] << " is"
			<< (osv.is_owner(i) ? " " : " not ") << "owner\n";
	}

	ownership_vector<int>::iterator iter1 = osv.end();
	--iter1; --iter1;
	osv.erase(iter1);
	ownership_vector<int>::iterator iter2 = osv.begin();
	++iter2; ++iter2;
	osv.erase(iter2);
	for(ownership_vector<int>::const_iterator p = osv.begin(); p != osv.end(); ++p)
		std::cout << **p << " is"
		<< (osv.is_owner(p) ? " " : " not ") << "owner\n";
		
}

int main()
{
	f3();

	return 0;
}

15.18

#include<iostream>
#include<memory>
using std::allocator;

//具体实现见 Vector.h
template<typename T, typename A = allocator<T>>
class vector {
private:
	/*...其他声明略...*/
public:
	class range_check_iterator;		//范围检查随机访问迭代器
	/*...其他声明略...*/
};
//下面是 range_check_iterator 定义
template<typename T, typename A>
class vector<T, A>::range_check_iterator {
	iterator curr;
	const vector<T, A>& rvec;	//用于提供begin()和end()
public:
	range_check_iterator(const iterator p, const vector<T,A>& rv)
		:curr{ p }, rvec{ rv }
	{ if (p - rv.begin() < 0 || rv.end() - p < 0) throw out_of_range{}; }
	
	T& operator[](size_type i);
	const T& operator[](size_type i) const;
	T& operator*() { return curr->val; }
	const T& operator*() const { return curr->val; }
	T* operator->() { return &curr->val; }

	range_check_iterator& operator++();
	range_check_iterator& operator--();
	range_check_iterator& operator+=(size_type n);
	range_check_iterator operator+(size_type n);
	range_check_iterator& operator-=(size_type n);
	range_check_iterator operator-(size_type n);
	long operator-(const range_check_iterator& it2);

	bool operator==(range_check_iterator const& other) const { return curr == other.curr; }
	bool operator!=(range_check_iterator const& other) const { return !(*this == other); }
};

template<typename T, typename A>
T& vector<T, A>::range_check_iterator::operator[](size_type i)
{
	if (i >= rvec.end() - curr)
		throw out_of_range{};
	return *(curr + i);
}

template<typename T, typename A>
const T& vector<T, A>::range_check_iterator::operator[](size_type i) const
{
	if (i >= rvec.end() - curr)
		throw out_of_range{};
	return *(curr + i);
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator& vector<T, A>::range_check_iterator::operator++()
{
	if (curr == rvec.end() || curr > rvec.end() || curr < rvec.begin())
		throw out_of_range{};
	++curr;
	return *this;
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator& vector<T, A>::range_check_iterator::operator--()
{
	if (curr == rvec.begin() || curr < rvec.begin() || curr > rvec.end())
		throw out_of_range{};
	--curr;
	return *this;
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator vector<T, A>::range_check_iterator::operator+(size_type n)
{
	if (n > rvec.end() - curr)
		throw out_of_range{};
	return range_check_iterator(curr + n, rvec);
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator& vector<T, A>::range_check_iterator::operator+=(size_type n)
{
	if (n > rvec.end() - curr)
		throw out_of_range{};
	curr += n;
	return *this;
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator vector<T, A>::range_check_iterator::operator-(size_type n)
{
	if (n > curr - rvec.begin())
		throw out_of_range{};
	return range_check_iterator(curr - n, rvec);
}

template<typename T, typename A>
typename vector<T, A>::range_check_iterator& vector<T, A>::range_check_iterator::operator-=(size_type n)
{
	if (n > curr - rvec.begin())
		throw out_of_range{};
	curr -= n;
	return *this;
}

//对指向同一序列的两个迭代器进行减法操作来得到它们的距离。
template<typename T, typename A>
long vector<T, A>::range_check_iterator::operator-(const range_check_iterator& it2)
{
	return curr - it2.curr;
}

15.19 为list定义范围检查迭代器

//双向循环链表,header是链表第一个节点也是最后一个节点的succ指向的节点
template<typename Elem>
class list {
private:
	long sz;
	Link<Elem>* header;

public:
	class out_of_range;
	class iterator;				//成员类型:双向迭代器
	class range_check_iterator;	//成员类型:范围检查双向迭代器

	list() :sz{ 0 }, header{ new Link<Elem>{} }
	{ header->pred = header; header->succ = header; }		//默认构造函数
	~list();

	iterator begin() { return iterator{ header->succ }; }	//指向首元素的迭代器
	iterator end() { return iterator{ header }; }		//指向尾元素之后的迭代器

	iterator insert(iterator p, const Elem& v);		//将 v 插入链表中 p 的位置
	iterator erase(iterator p);						//从链表中删除 p

	void push_back(const Elem& v);		//将 v 插入链表末尾
	void push_front(const Elem& v);		//将 v 插入链表末头
	void pop_back();		//删除尾元素
	void pop_front();		//删除首元素

	Elem& front();			//获取首元素
	Elem& back();			//获取尾元素

	int size() const { return sz; }
};

/* 其他实现略,具体见开头的List_Circular.h */

//循环链表的范围检查迭代器
template<typename Elem>
class list<Elem>::range_check_iterator {
private:
	using iter = typename list<Elem>::iterator;
	iter curr;
	iter begin;
	iter end;
public:
	range_check_iterator(iter p, iter begin, iter end) :curr{ p }, begin{ begin }, end{ end }{}

	range_check_iterator& operator++();
	range_check_iterator& operator--();

	Elem& operator*() { return *curr; }
	Elem* operator->() { return &*curr; }	//如果*(iter).m 有效,则可以使用iter->m 简写形式

	bool operator==(const range_check_iterator& b) const
	{	return curr == b.curr;	}
	bool operator!=(const range_check_iterator& b) const
	{	return curr != b.curr;	}

	friend iterator list<Elem>::insert(iterator p, const Elem& v);		//将 v 插入链表中 p 的位置
	friend iterator list<Elem>::erase(iterator p);						//从链表中删除 p
};
template<typename Elem>
typename list<Elem>::range_check_iterator& list<Elem>::range_check_iterator::operator++()
{
	if (curr == end)
		throw out_of_range{};
	++curr;
	return *this;
}

template<typename Elem>
typename list<Elem>::range_check_iterator& list<Elem>::range_check_iterator::operator--()
{
	if (curr == begin)
		throw out_of_range{};
	--curr;
	return *this;
}

15.20

这是github上一个大佬(Chrinkus)的测试用例,我觉得不错,就直接拿来了,

//
// Stroustrup - Programming Principles & Practice
//
// Chapter 20 Exercise 20
//
// Run a timing experiment to compare the cost of using vector and list. Create
// random numbers and store them in an ordered vector and list.
//
// Originally this was run with just push backs, not bothering to keep order.
// That was NOT what the text asked but it was still fun. I had to figure out
// how to insert into vectors and lists while keeping order AND equal, as I
// thought the point was isolating the insertion operation.
//
// I ended up learning a lot more than anticipated. My inital ordered insertion
// was kind of ham-handed, start at front and iterate till a larger value was
// found then insert there. This solution is found in the Linear_ordered_fill
// function object. The results of this timing experiment saw vectors being
// faster than lists, which is not what was expected. I'd guess that stepping
// through a List may be more slower than insert and reallocations are in a 
// vector. Good to know.
//
// The next idea was to just remove the ordered requirement again but use
// insert rather than push_back as I initially attempted. This approach saw
// the linked list trounce the vector as expected.
//
// Lastly, when looking for better alternatives to ordered insertion I found
// the binary search algorithms, specifically upper_bound, which work excep-
// tionally well with random-access iterators. The results were astoundingly
// in favour of vectors with lists actually performing worse than my linear
// solution (since they don't have random-access iterators).
//
// Comparing to a multiset I see that ordered insertion into a vector using
// binary search to find the right spot is fast enough to reinforce the state-
// ment "use vector almost always"!

#include <iostream>
#include <stdexcept>
#include <chrono>
#include <vector>
#include <list>
#include <random>
#include <functional>
#include <array>
#include <set>

using namespace std::chrono;

template<typename Func>
void time_check(Func& op, const std::string& label = "")
{
    auto t1 = system_clock::now();//.time_since_epoch().count();

    op();

    auto t2 = system_clock::now();//.time_since_epoch().count();

    std::cout << "Task " << label << " took\n"
              << '\t' << duration_cast<milliseconds>(t2 - t1).count()
              << " milliseconds\n"
              << '\t' << duration_cast<microseconds>(t2 - t1).count()
              << " microseconds\n";
}

template<typename C, typename D>
class Linear_ordered_fill {
    C c;
    const D& d;
public:
    Linear_ordered_fill(C cc, const D& dd) : c{cc}, d{dd} { }

    void operator()()   //()运算符重载
    {
        for (auto p = d.begin(); p != d.end(); ++p) {
            auto it = c.begin();
            while (it != c.end() && *it < *p) ++it;
            c.insert(it, *p);
        }
    }
};

template<typename C, typename D>
class Binary_search_ordered_fill {
    C c;
    const D& d;
public:
    Binary_search_ordered_fill(C cc, const D& dd) : c{cc}, d{dd} { }

    void operator()()   //()运算符重载
    {
        for (const auto a : d) {
            auto it = std::upper_bound(c.begin(), c.end(), a);
            c.insert(it, a);
        }
    }
};

template<typename C, typename D>
class Front_fill {
    C c;
    const D& d;
public:
    Front_fill(C cc, const D& dd) : c{cc}, d{dd} { }

    void operator()()   //()运算符重载
    {
        for (const auto a : d)
            c.insert(c.begin(), a);
    }
};

template<typename D>
class Set_fill {
    std::multiset<int> st;
    const D& d;
public:
    Set_fill(std::multiset<int> ss, const D& dd) : st{ ss }, d{ dd } { }

    void operator()()   //()运算符重载
    {
        for (const auto a : d)
            st.insert(a);
    }
};

int main()
try {
    const int n = 1000;

    // randomizer
    int seed = system_clock::now().time_since_epoch().count();
    std::default_random_engine generator(seed);
    std::uniform_int_distribution<int> distribution(1, n);
    auto dice = std::bind(distribution, generator);

    std::array<int,n> rand_arr;
    for (auto it = rand_arr.begin(); it != rand_arr.end(); ++it)
        *it = dice();

    Linear_ordered_fill<std::vector<int>,std::array<int,n>> vec {
        std::vector<int>(), rand_arr
    };

    Linear_ordered_fill<std::list<int>,std::array<int,n>> lst {
        std::list<int>(), rand_arr
    };

    time_check(vec, "linear ordered vector");
    time_check(lst, "linear ordered list");

    Binary_search_ordered_fill<std::vector<int>,std::array<int,n>> vec3 {
        std::vector<int>(), rand_arr
    };

    Binary_search_ordered_fill<std::list<int>,std::array<int,n>> lst3 {
        std::list<int>(), rand_arr
    };

    time_check(vec3, "binary search ordered vector");
    time_check(lst3, "binary search ordered list");

    My_Binary_search_ordered_fill<std::vector<int>, std::array<int, n>> vec4{
        std::vector<int>(), rand_arr
    };

    My_Binary_search_ordered_fill<std::list<int>, std::array<int, n>> lst4{
        std::list<int>(), rand_arr
    };

    time_check(vec4, "my binary search ordered vector");
    time_check(lst4, "my binary search ordered list");

    Front_fill<std::vector<int>,std::array<int,n>> vec2 {
        std::vector<int>(), rand_arr
    };

    Front_fill<std::list<int>,std::array<int,n>> lst2 {
        std::list<int>(), rand_arr
    };

    time_check(vec2, "front filled vector");
    time_check(lst2, "front filled list");

    Set_fill<std::array<int,n>> si { std::multiset<int>(), rand_arr };

    time_check(si, "naturally ordered set");

    
}
catch(std::exception& e) {
    std::cerr << "Exception: " << e.what() << '\n';
    return 1;
}
catch(...) {
    std::cerr << "Unknown exception\n";
    return 2;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
 本书是经典程序设计思想与C++开发实践的完美结合,是C++之父回归校园后对C++编程原理和技巧的全新阐述。书中全面地介绍了程序设计基本原理,包括基本概念、设计和编程技术、语言特性以及标准库等,教你学会如何编写具有输入、输出、计算以及简单图形显示等功能的程序。此外,本书通过对C++思想和历史的讨论、对经典实例(如矩阵运算、文本处理、测试以及嵌入式系统程序设计)的展示,以及对C语言的简单描述,为你呈现了一幅程序设计的全景图。   ·C++初学者的权威指南。无论你是从事软件开发还是其他领域的工作,本书将为你打开程序开发之门。   ·中高级程序员的必备参考。通过观察程序设计大师如何处理编程中的各种问题,使你获得新的领悟和指引。   ·全面阐释C++基本概念和技术。与传统的C++教材相比,本书对基本概念和技术的介绍更为深入,为你编写实用、正确、易维护和有效的代码打下坚实的基础。   ·强调现代C++编程风格。本书从开篇就介绍现代C++程序设计技术,并揭示了大量关于如何使用C++标准库来简化程序设计原理,使你快速掌握实用编成技巧。 图书目录   出版者的话   译者序   前言   第0 致读者   第1 计算机、人与程序设计   第一部分 基本知识   第2 Hello,World!   第3 对象、类型和值   第4 计算   第5 错误   第6 编写一个程序   第7 完成一个程序   第8 函数相关的技术细节   第9 类相关的技术细节   第二部分 输入和输出   第10 输入/输出流   第11 定制输入/输出   第12 一个显示模型   第13 图形类   第14 设计图形类   第15 绘制函数图和数据图   第16 图形用户界面   第三部分 数据结构和算法   第17 向量和自由空间   第18 向量和数组   第19 向量、模板和异常   第20 容器和迭代器   第21 算法和映射   第四部分 拓宽视野   第22 理念和历史   第23 文本处理   第24 数值计算   第25 嵌入式系统程序设计   第26 测试   第27 C语言   术语表   参考书目   第五部分 附录?   附录A C++语言概要   附录B 标准库概要   附录C Visual Studio简要入门教程   附录D 安装FLTK   附录E GUI实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值