c++primer第五版第十二章练习

12.1

b1=b2,所以都有4个元素,赋值后b1原先指向的内存被释放,因为计数为0

b2离开作用域后被摧毁,但计数器不为0,内存不用释放


12.2

#ifndef HEAD_H_
#define HEAD_H_
#include <memory>
#include <initializer_list>
#include <string>
#include <vector>
class StrBlob
{
	std::shared_ptr<std::vector<std::string>> data;
	void check(std::vector<std::string>::size_type i, const std::string &msg)const;
public:
	using size_type = std::vector<std::string>::size_type;
	StrBlob();
	StrBlob(std::initializer_list<std::string> il);
	size_type size()const;//返回vector元素数量
	bool empty()const;//是否为空
	void push_back(const std::string &t);//添加新元素到尾
	void pop_back();//弹出最后一个
	std::string front()const;
	std::string back()const;
	std::string &front();//返回第一个
	std::string &back();//返回最后一个
};
void StrBlob::check(std::vector<std::string>::size_type i, const std::string &msg)const
{
	if (i >= data->size())
		throw std::out_of_range(msg);
}
StrBlob::StrBlob() :data(std::make_shared<std::vector<std::string>>())
{

}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il))
{

}
StrBlob::size_type StrBlob::size()const
{
	return data->size();
}
bool StrBlob::empty()const
{
	return data->empty();
}
void StrBlob::push_back(const std::string &t)
{
	data->push_back(t);
}
void StrBlob::pop_back()
{
	check(0, "pop_push on empty StrBlob");
	data->pop_back();
}
std::string &StrBlob::front()
{
	check(0, "front on empty StrBlob");
	return data->front();
}
std::string &StrBlob::back()
{
	check(0, "back on empty StrBlob");
	return data->back();
}
std::string StrBlob::front()const
{
	return data->front();
}
std::string StrBlob::back()const
{
	return data->back();
}
#endif

#include <iostream>
#include "标头.h"
int main()
{
	using namespace std;
	StrBlob strb{ "dsdsdsd", "dsdsdsdsd" ,"dasdafwafwadwa","fwqdswqdeqdwqed"};
	cout << strb.front();
	strb.pop_back();
	cout << endl << strb.front();
	strb.pop_back();
	cout << strb.front();
	system("puse");
	return 0;
}

12.3

可以这样做,但是然并卵

在方法形参为const时才会使用const版本


12.4

因为size_type是无符号类型,如果小于0将会自动转换为大于0的数

所以当参数为负数时,i肯定会比size()大


12.5

使用容易,因为可以自动转换参数类型

调试难,出问题时就悲剧


12.6

#include <iostream>
#include <vector>
void input(std::vector<int> &vec)
{
	int i;
	while (std::cin >> i)
		vec.push_back(i);
}
void print(const std::vector<int> &vec)
{
	for (auto a : vec)
		std::cout << a << "\t";
}
std::vector<int> *func()
{
	return new std::vector<int>;
}
int main()
{
	using namespace std;
	auto p = func();
	input(*p);
	print(*p);
	delete p;
	system("pause");
	return 0;
}

12.7

#include <iostream>
#include <memory> //shared_ptr....智能指针
#include <vector>
void input(std::shared_ptr<std::vector<int>> vec)
{
	int i;
	while (std::cin >> i)
		vec->push_back(i);
}
void print(const std::shared_ptr<std::vector<int>> vec)
{
	for (auto a : *vec)
		std::cout << a << "\t";
}
std::shared_ptr<std::vector<int>> func()
{
	//return std::make_shared<std::vector<int>>();	//创建一个智能指针分配内存,返回地址
	return std::shared_ptr<std::vector<int>>(new std::vector<int>);//new创建一个vector并隐式转换为智能指针,返回给智能指针初始化
}
int main()
{
	using namespace std;
	auto p = func();
	input(p);
	print(p);
	system("pause");
	return 0;
}

12.8

内存地址丢失


12.9

r=q后r原先指向的内存丢失

r2=q2后r2原先保存的计数器变为0,释放内存


12.10

可以这样,没有错误,然并卵


12.11

发生错误,当函数结束时会把get()返回的地址调用delete释放,使得p变成悬空指针


12.12

a:ok

b:error,new分配内存后返回的是一个普通指针,无法赋值到shared_ptr对象

c:error,p是一个普通指针,同上

d:ok,但容易发生错误,比较糟的做法


12.13

运行时错误,在delete后sp智能指针所管理的内存已经被释放,而当智能指针作用域过后会再释放一次


12.14

#include <iostream>
#include <memory>		//shared_ptr
#include <string>
struct destination
{
	std::string ip;
	int port;
	destination(std::string _ip, int _port) :ip(_ip), port(_port){}
};
struct connection
{
	std::string ip;
	int port;
	connection(std::string _ip, int _port) :ip(_ip), port(_port){}
};
connection connect(destination *p)
{
	std::shared_ptr<connection> ptr(new connection(p->ip, p->port));
	std::cout << "use_count:" << ptr.use_count() << std::endl;
	return *ptr;
}
void disconnect(connection p)
{
	std::cout << "close " << p.ip << std::endl;
	//delete ....
	//...
}
void end_connection(connection *p)
{
	disconnect(*p);
}
void f(destination &d)
{
	connection c = connect(&d);
	std::shared_ptr<connection> p(&c, end_connection);

}
int main()
{
	using namespace std;
	destination d("192.168.1.233", 2333);
	f(d);
	system("pause");
	return 0;
}

12.15

#include <iostream>
#include <memory>		//shared_ptr
#include <string>
struct destination
{
	std::string ip;
	int port;
	destination(std::string _ip, int _port) :ip(_ip), port(_port){}
};
struct connection
{
	std::string ip;
	int port;
	connection(std::string _ip, int _port) :ip(_ip), port(_port){}
};
connection connect(destination *p)
{
	std::shared_ptr<connection> ptr(new connection(p->ip, p->port));
	std::cout << "use_count:" << ptr.use_count() << std::endl;
	return *ptr;
}
void disconnect(connection p)
{
	std::cout << "close " << p.ip << std::endl;
	//delete ....
	//...
}
//void end_connection(connection *p)
//{
//	disconnect(*p);
//}
void f(destination &d)
{
	connection c = connect(&d);
	std::shared_ptr<connection> p(&c, [](connection *p){disconnect(*p); });

}
int main()
{
	using namespace std;
	destination d("192.168.1.233", 2333);
	f(d);
	system("pause");
	return 0;
}

12.16

#include <iostream>
#include <memory>		//shared_ptr
int main()
{
	using namespace std;
	unique_ptr<int> p(new int(0));
	unique_ptr<int> p1(p);	//它是已删除的函数
	unique_ptr<int> p2;
	p2 = p;			//它是已删除的函数
	system("pause");
	return 0;
}

12.17

a: 错误,ix是局部变量b:错误,同a

c:√ d:错误,同a

e:√ f:错误,多次释放同一位置内存


12.18

release会释放内存,无法保证计数为0


12.19

#ifndef HEAD_H_
#define HEAD_H_
#include <memory>
#include <initializer_list>
#include <string>
#include <vector>
class StrBlobPtr;
class StrBlob
{
	friend class StrBlobPtr;
	std::shared_ptr<std::vector<std::string>> data;
	void check(std::vector<std::string>::size_type i, const std::string &msg)const;
public:
	using size_type = std::vector<std::string>::size_type;
	

	StrBlob();
	StrBlob(std::initializer_list<std::string> il);
	size_type size()const;//返回vector元素数量
	bool empty()const;//是否为空
	void push_back(const std::string &t);//添加新元素到尾
	void pop_back();//弹出最后一个
	std::string front()const;
	std::string back()const;
	std::string &front();//返回第一个
	std::string &back();//返回最后一个

	StrBlobPtr begin();
	StrBlobPtr end();
};
class StrBlobPtr
{
	std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string &)const;
	std::weak_ptr<std::vector<std::string>> wptr;
	std::size_t curr;
public:
	StrBlobPtr() :curr(0){}
	StrBlobPtr(StrBlob &a, std::size_t sz = 0) :wptr(a.data), curr(sz){}
	std::string &deref()const;	//解引用
	StrBlobPtr &incr();	//++n;运算符
};

void StrBlob::check(std::vector<std::string>::size_type i, const std::string &msg)const
{
	if (i >= data->size())
		throw std::out_of_range(msg);
}
StrBlob::StrBlob() :data(std::make_shared<std::vector<std::string>>())
{

}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il))
{

}
StrBlob::size_type StrBlob::size()const
{
	return data->size();
}
bool StrBlob::empty()const
{
	return data->empty();
}
void StrBlob::push_back(const std::string &t)
{
	data->push_back(t);
}
void StrBlob::pop_back()
{
	check(0, "pop_push on empty StrBlob");
	data->pop_back();
}
std::string &StrBlob::front()
{
	check(0, "front on empty StrBlob");
	return data->front();
}
std::string &StrBlob::back()
{
	check(0, "back on empty StrBlob");
	return data->back();
}
std::string StrBlob::front()const
{
	return data->front();
}
std::string StrBlob::back()const
{
	return data->back();
}
StrBlobPtr StrBlob::begin()
{ 
	return StrBlobPtr(*this); 
}
StrBlobPtr StrBlob::end()
{
	return StrBlobPtr(*this, data->size());
}
std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(std::size_t i, const std::string &msg)const
{
	auto ret = wptr.lock();	//返回shared_ptr
	if (!ret)
		throw std::runtime_error("unbound StrBlobPtr");
	if (i >= ret->size())
		throw std::out_of_range(msg);
	return ret;
}
std::string &StrBlobPtr::deref()const
{
	auto ret = check(curr, "dereference past end");
	return (*ret)[curr];
}
StrBlobPtr &StrBlobPtr::incr()
{
	check(curr, "increment past end of StrBlobPtr");
	++curr;
	return *this;
}
#endif

12.20

#include "标头.h"
#include <iostream>
#include <fstream>

bool iseq(const StrBlobPtr &s1, const StrBlobPtr &s2)	//StrBlobPtr的友元函数:当两个引用 不相等 时返回真
{
	if (s1.wptr.lock() == s2.wptr.lock())
		return !(s1.curr == s2.curr);
	return true;
}
int main(int argc, char **argv)
{
	using namespace std;
	ifstream ifile("F:\\11.txt");
	if (!ifile)
	{
		cerr << "open file error!";
		exit(1);
	}
	StrBlob str;
	string temp;
	while (getline(ifile, temp))
	{
		str.push_back(temp);
	}
	for (auto beg = str.begin(), end = str.end(); iseq(beg, end); beg.incr())
	{
		cout << beg.deref() << endl;
	}
	return 0;
}

12.21

一样,但前一个版本好理解


12.22

#ifndef HEAD_H_
#define HEAD_H_
#include <memory>
#include <initializer_list>
#include <string>
#include <vector>
class ConstStrBlobPtr;
class StrBlob
{
	friend class ConstStrBlobPtr;
	std::shared_ptr<std::vector<std::string>> data;
	void check(std::vector<std::string>::size_type i, const std::string &msg)const;
public:
	using size_type = std::vector<std::string>::size_type;


	StrBlob();
	StrBlob(std::initializer_list<std::string> il);
	size_type size()const;//返回vector元素数量
	bool empty()const;//是否为空
	void push_back(const std::string &t);//添加新元素到尾
	void pop_back();//弹出最后一个
	std::string front()const;
	std::string back()const;
	const std::string &front();//返回第一个	const
	const std::string &back();//返回最后一个 const

	ConstStrBlobPtr begin();	//curr=0
	ConstStrBlobPtr end();	//curr=data->size();
};
class ConstStrBlobPtr
{
	std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string &)const;
	std::weak_ptr<std::vector<std::string>> wptr;
	std::size_t curr;
public:
	ConstStrBlobPtr() :curr(0){}
	ConstStrBlobPtr(const StrBlob &a, std::size_t sz = 0) :wptr(a.data), curr(sz){}		//const
	const std::string &deref()const;	//解引用	const
	ConstStrBlobPtr &incr();	//++n;运算符

	friend bool iseq(const ConstStrBlobPtr &, const ConstStrBlobPtr &);
};

void StrBlob::check(std::vector<std::string>::size_type i, const std::string &msg)const
{
	if (i >= data->size())
		throw std::out_of_range(msg);
}
StrBlob::StrBlob() :data(std::make_shared<std::vector<std::string>>())
{

}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il))
{

}
StrBlob::size_type StrBlob::size()const
{
	return data->size();
}
bool StrBlob::empty()const
{
	return data->empty();
}
void StrBlob::push_back(const std::string &t)
{
	data->push_back(t);
}
void StrBlob::pop_back()
{
	check(0, "pop_push on empty StrBlob");
	data->pop_back();
}
const std::string &StrBlob::front()
{
	check(0, "front on empty StrBlob");
	return data->front();
}
const std::string &StrBlob::back()
{
	check(0, "back on empty StrBlob");
	return data->back();
}
std::string StrBlob::front()const
{
	return data->front();
}
std::string StrBlob::back()const
{
	return data->back();
}
ConstStrBlobPtr StrBlob::begin()
{
	return ConstStrBlobPtr(*this);
}
ConstStrBlobPtr StrBlob::end()
{
	return ConstStrBlobPtr(*this, data->size());
}
std::shared_ptr<std::vector<std::string>> ConstStrBlobPtr::check(std::size_t i, const std::string &msg)const
{
	auto ret = wptr.lock();	//返回shared_ptr
	if (!ret)
		throw std::runtime_error("unbound StrBlobPtr");
	if (i >= ret->size())
		throw std::out_of_range(msg);
	return ret;
}
const std::string &ConstStrBlobPtr::deref()const
{
	auto ret = check(curr, "dereference past end");
	return (*ret)[curr];
}
ConstStrBlobPtr &ConstStrBlobPtr::incr()
{
	check(curr, "increment past end of StrBlobPtr");
	++curr;
	return *this;
}
#endif

12.23

#include <iostream>
#include <string>
int main()
{
	using namespace std;
	char s1[] = "c++ ";
	char s2[] = "primer";
	char *p = new char[strlen(s1) + strlen(s2)+1]();	//要注意初始化
	strcat(p, s1);
	strcat(p, s2);
	cout << p << endl;
	delete[] p;

	string str1{ "c++" }, str2{ "primer" };
	auto str = str1 + str2;
	cout << str;
	system("pause");
	return 0;
}

12.24

#include <iostream>

int main()
{
	using namespace std;
	char *str = new char[10];
	cin.get(str, 10);//只读取10个字符
	cout << str << endl;
	delete[]str;
	system("pause");
	return 0;
}

12.25

deete [] pa;


12.26

#include <iostream>
#include <string>
#include <memory>	//allcator
//#include <vector>
int main()
{
	using namespace std;
	allocator<string> alloc;
	auto const p = alloc.allocate(10);
	auto q = p;
	string temp;

	//vector<string> vec;
	//while (vec.size() < 10)
	//{
	//	cin >> temp;
	//	++q;
	//	vec.push_back(temp);
	//}
	把vec中的元素拷贝到p指向的内地址中
	//uninitialized_copy(vec.begin(), vec.end(), p);
	while (q - p < 10)
	{
		cout << q - p + 1 << ":";
		cin >> temp;
		alloc.construct(q++, temp);		//把temp传递给string的构造函数构造一个对象存放到q指向的位置	然后++把q指向下一个
	}

	const size_t size = q - p;
	q = p;
	while (q != p + size)
		cout << *q++ << endl;
	while (q != p)
		alloc.destroy(--q);			//删除q指向的地址的对象数据
	alloc.deallocate(p,10);				//释放p开始的10个string的地址的内存
	system("pause");
	return 0;
}

12.27

#ifndef HEAD_H_
#define HEAD_H_
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>	//istringstream
//#include <iterator>	//find
#include <vector>
#include <map>
#include <set>
#include <memory>	//shared_ptr
#include <cctype>
class QueryResult;
class TextQuery
{
	std::vector<std::string> str;	//把文件每一行都保存到string中
	std::map<std::string, std::set<std::vector<std::string>::size_type>> line;	//保存单词对应的行号	相当于map<string,set<unsigned>> line;
	std::string isword(std::string s)
	{
		s[0] = tolower(s[0]);
		if (!isalnum(s[s.size() - 1]))
			s = std::string(s.begin(), s.end() - 1);
		return s;
	}
public:
	TextQuery(std::ifstream &in)
	{
		if (!in)
		{
			std::cerr << "open file error in class";
			exit(1);
		}
		std::string temp;
		while (std::getline(in, temp))
		{
			str.push_back(temp);
			std::istringstream instr(temp);
			std::string t;
			while (instr >> t)
				line[isword(t)].insert(str.size()-1);
		}
	}
	QueryResult query(const std::string &s);
};
class QueryResult
{
public:
	std::string word;
	std::map<std::vector<std::string>::size_type, std::string> mw;
	friend std::ostream &print(std::ostream &os, const QueryResult &qr);
	QueryResult(){}
};

QueryResult TextQuery::query(const std::string &s)
{
	QueryResult qr;
	if (line.find(s) == line.cend())
	{
		std::cout << "not word\n";
		return qr;
	}
	qr.word = s;
	for (auto &x : line[s])
		qr.mw[x] = str[x];
	return qr;
}
#endif
#include "标头.h"
std::ostream &print(std::ostream &os, const QueryResult &qr)
{
	os << qr.word << " occurs " << qr.mw.size() << " times" << std::endl;
	for (auto &x : qr.mw)
		os << "(line " << x.first +1<< ") " << x.second << std::endl;
	return os;
}

void runQuerues(std::ifstream &in)
{
	TextQuery tq(in);
	while (1)
	{
		std::cout << "enter word to look for,or q to quit: ";
		std::string s;
		if (!(std::cin >> s) || s == "q")
			break;
		print(std::cout, tq.query(s)) << std::endl;
	}
}
int main(int argc, char **argv)
{
	using namespace std;
	ifstream infile(argv[1]);
	runQuerues(infile);
	return 0;
}

12.28

#include <iostream>
#include <fstream>
#include <sstream>	//istringstream
#include <vector>
#include <string>
#include <map>
#include <set>
#include <cctype>

int main(int argc, char **argv)
{
	using namespace std;
	ifstream infile(argv[1]);
	if (!infile)
	{
		cerr << "open file error";
		exit(1);
	}
	vector<string> vec;
	map<string, set<vector<string>::size_type>> mw;
	string temp,word;
	while (getline(infile, temp))
	{
		vec.push_back(temp);
		istringstream ist(temp);
		while (ist >> word)
		{
			if (!isalpha(word[0]))
				continue;
			word[0] = tolower(word[0]);
			if (!isalnum(word[word.size() - 1]))
				word.erase(word.size() - 1, 1);
			mw[word].insert(vec.size()-1);
		}
	}
	cout << "enter find word:";
	while (cin >> word)
	{
		if (mw.find(word) == mw.cend())
		{
			cout << "not word!" << endl;
			continue;
		}
		cout << word << " occurs " << mw.size()<< " times" << endl;
		for (auto x : mw[word])
			cout << "(line " << x +1 << ") " << vec[x] << endl;
	}


	//system("pause");
	return 0;
}

12.29

#ifndef HEAD_H_
#define HEAD_H_
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>	//istringstream
//#include <iterator>	//find
#include <vector>
#include <map>
#include <set>
#include <memory>	//shared_ptr
#include <cctype>
class QueryResult;
class TextQuery
{
	std::vector<std::string> str;	//把文件每一行都保存到string中
	std::map<std::string, std::set<std::vector<std::string>::size_type>> line;	//保存单词对应的行号	相当于map<string,set<unsigned>> line;
	std::string isword(std::string s)
	{
		s[0] = tolower(s[0]);
		if (!isalnum(s[s.size() - 1]))
			s = std::string(s.begin(), s.end() - 1);
		return s;
	}
public:
	TextQuery(std::ifstream &in)
	{
		if (!in)
		{
			std::cerr << "open file error in class";
			exit(1);
		}
		std::string temp;
		do 
		{
			if (!std::getline(in, temp))<span style="white-space:pre">			</span>//.................do while
				break;
			str.push_back(temp);
			std::istringstream instr(temp);
			std::string t;
			while (instr >> t)
				line[isword(t)].insert(str.size() - 1);
		} while (1);
	}
	QueryResult query(const std::string &s);
};
class QueryResult
{
public:
	std::string word;
	std::map<std::vector<std::string>::size_type, std::string> mw;
	friend std::ostream &print(std::ostream &os, const QueryResult &qr);
	QueryResult(){}
};

QueryResult TextQuery::query(const std::string &s)
{
	QueryResult qr;
	if (line.find(s) == line.cend())
	{
		std::cout << "not word\n";
		return qr;
	}
	qr.word = s;
	for (auto &x : line[s])
		qr.mw[x] = str[x];
	return qr;
}
#endif

#include "标头.h"
std::ostream &print(std::ostream &os, const QueryResult &qr)
{
	os << qr.word << " occurs " << qr.mw.size() << " times" << std::endl;
	for (auto &x : qr.mw)
		os << "(line " << x.first + 1 << ") " << x.second << std::endl;
	return os;
}

void runQuerues(std::ifstream &in)
{
	TextQuery tq(in);
	do
	{
		std::cout << "enter word to look for,or q to quit: ";
		std::string s;
		if (!(std::cin >> s) || s == "q")
			break;
		print(std::cout, tq.query(s)) << std::endl;
	} while (1);
}
int main(int argc, char **argv)
{
	using namespace std;
	ifstream infile(argv[1]);
	runQuerues(infile);
	return 0;
}


比较倾向以前一个版本,易理解,好判断


12.30

#ifndef HEAD_H_
#define HEAD_H_

#include <iostream>
#include <fstream>	//ifstream
#include <string>
#include <vector>
#include <sstream>	//istringstream
#include <map>
#include <set>
#include <memory>	//shared_ptr
class QueryResult;
using line_no = std::vector < std::string > ::size_type;
class TextQuery
{
	
	std::shared_ptr<std::vector<std::string>> file;					//保存整个文件内容,按行分
	std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;	//每个单词对应行号
public:

	TextQuery(std::ifstream &is);
	QueryResult query(const std::string &s)const;					//返回QR,单词、行号set,还有关联到文件内容
};
class QueryResult
{
	friend std::ostream &print(std::ostream &os, const QueryResult &qr);
	std::string sought;
	std::shared_ptr<std::set<line_no>> lines;						//记录出现的行号
	std::shared_ptr<std::vector<std::string>> file;					//关联到文件内容
public:
	QueryResult(std::string s, std::shared_ptr<std::set<line_no>> p, std::shared_ptr<std::vector<std::string>> f) :sought(s), lines(p), file(f){}
};
TextQuery::TextQuery(std::ifstream &is) :file(new std::vector<std::string>())	//为智能指针file分配空间
{
	std::string text;
	while (getline(is, text))
	{
		file->push_back(text);
		int n = file->size() - 1;
		std::istringstream line(text);
		std::string word;
		while (line >> word)
		{
			auto &lines = wm[word];						//如果word在wm中第一次出现,那么对应的set就未分配内存,所以为空
			if (!lines)										//如果第一次出现
				lines.reset(new std::set<line_no>());
			lines->insert(n);
		}
	}
}
QueryResult TextQuery::query(const std::string &s)const
{
	static std::shared_ptr<std::set<line_no>> nodata(new std::set<line_no>());	//当没找到单词时返回	内存常驻
	auto loc = wm.find(s);
	if (loc == wm.end())
		return QueryResult(s, nodata, file);
	else
		return QueryResult(s, loc->second, file);
}
std::ostream &print(std::ostream &os, const QueryResult &qr)
{
	os << qr.sought << " occurs " << qr.lines->size() << " " << (qr.lines->size() > 1 ? "times" : "time") << std::endl;
	for (auto x : *qr.lines)			//*(qr.file->begin()+x)
		os << "\t(line " << x + 1 << ") " << (*qr.file)[x] << std::endl;	//file返回一个指向vec的智能指针,解引用后得到vector 然后使用下标运算符
	return os;
}
#endif
#include "标头.h"

void runQueries(std::ifstream &infile)
{
	TextQuery tq(infile);
	while (1)
	{
		std::cout << "enter word to look for, or q to quit:";
		std::string s;
		if (!(std::cin >> s) || s == "q")break;
		print(std::cout, tq.query(s));
	}
}

int main(int argc, char **argv)
{
	using namespace std;
	ifstream infile(argv[1]);
	if (!infile)
	{
		cerr << "open file error!";
		exit(1);
	}
	runQueries(infile);
	return 0;
}

12.31

使用insert时将出现重复行号,必须花费额外的代码处理


12.32

#ifndef HEAD1_H_
#define HEAD1_H_
#include <memory>
#include <initializer_list>
#include <string>
#include <vector>
class StrBlob
{
	std::shared_ptr<std::vector<std::string>> data;
	void check(std::vector<std::string>::size_type i, const std::string &msg)const;
public:
	using size_type = std::vector<std::string>::size_type;
	StrBlob();
	StrBlob(std::initializer_list<std::string> il);
	size_type size()const;//返回vector元素数量
	bool empty()const;//是否为空
	void push_back(const std::string &t);//添加新元素到尾
	void pop_back();//弹出最后一个
	std::string front()const;
	std::string back()const;
	std::string &front();//返回第一个
	std::string &back();//返回最后一个
	const std::shared_ptr<std::vector<std::string>> &shared_ptr()const	//返回data的const引用
	{
		return data;
	}
};
void StrBlob::check(std::vector<std::string>::size_type i, const std::string &msg)const
{
	if (i >= data->size())
		throw std::out_of_range(msg);
}
StrBlob::StrBlob() :data(std::make_shared<std::vector<std::string>>())
{

}
StrBlob::StrBlob(std::initializer_list<std::string> il) : data(std::make_shared<std::vector<std::string>>(il))
{

}
StrBlob::size_type StrBlob::size()const
{
	return data->size();
}
bool StrBlob::empty()const
{
	return data->empty();
}
void StrBlob::push_back(const std::string &t)
{
	data->push_back(t);
}
void StrBlob::pop_back()
{
	check(0, "pop_push on empty StrBlob");
	data->pop_back();
}
std::string &StrBlob::front()
{
	check(0, "front on empty StrBlob");
	return data->front();
}
std::string &StrBlob::back()
{
	check(0, "back on empty StrBlob");
	return data->back();
}
std::string StrBlob::front()const
{
	return data->front();
}
std::string StrBlob::back()const
{
	return data->back();
}
#endif
#ifndef HEAD_H_
#define HEAD_H_
#include "标头1.h"
#include <iostream>
#include <fstream>	//ifstream
#include <string>
#include <vector>
#include <sstream>	//istringstream
#include <map>
#include <set>
#include <memory>	//shared_ptr
class QueryResult;
class TextQuery
{

	std::shared_ptr<StrBlob> file;							//保存整个文件内容,按行分
	std::map<std::string, std::shared_ptr<std::set<StrBlob::size_type>>> wm;	//每个单词对应行号
public:

	TextQuery(std::ifstream &is);
	QueryResult query(const std::string &s)const;					//返回QR,单词、行号set,还有关联到文件内容
};
class QueryResult
{
	friend std::ostream &print(std::ostream &os, const QueryResult &qr);
	std::string sought;
	std::shared_ptr<std::set<StrBlob::size_type>> lines;						//记录出现的行号
	std::shared_ptr<StrBlob> file;									//关联到文件内容
public:
	QueryResult(std::string s,const std::shared_ptr<std::set<StrBlob::size_type>> &p, std::shared_ptr<StrBlob> f) :sought(s), lines(p), file(f){}
};

TextQuery::TextQuery(std::ifstream &is) :file(new StrBlob())	//为智能指针file分配空间
{
	std::string text;
	while (getline(is, text))
	{
		file->push_back(text);
		int n = file->size() - 1;
		std::istringstream line(text);
		std::string word;
		while (line >> word)
		{
			auto &lines = wm[word];						//如果word在wm中第一次出现,那么对应的set就未分配内存,所以为空
			if (!lines)										//如果第一次出现
				lines.reset(new std::set<StrBlob::size_type>);
			lines->insert(n);
		}
	}
}

QueryResult TextQuery::query(const std::string &s)const
{
	static std::shared_ptr<std::set<StrBlob::size_type>> nodata(new std::set<StrBlob::size_type>);	//当没找到单词时返回	内存常驻
	auto loc = wm.find(s);
	if (loc == wm.end())
		return QueryResult(s, nodata, file);
	else
		return QueryResult(s, loc->second, file);
}

std::ostream &print(std::ostream &os, const QueryResult &qr)
{
	os << qr.sought << " occurs " << qr.lines->size() << " " << (qr.lines->size() > 1 ? "times" : "time") << std::endl;
	for (auto x : *qr.lines)
		os << "\t(line " << x + 1 << ") " << qr.file->shared_ptr()->at(x) << std::endl;		//StrBlob需要添加返回data const引用的方法
	return os;
}
#endif
#include "标头.h"


void runQueries(std::ifstream &infile)
{
	TextQuery tq(infile);
	while (1)
	{
		std::cout << "enter word to look for, or q to quit:";
		std::string s;
		if (!(std::cin >> s) || s == "q")break;
		print(std::cout, tq.query(s));
	}
}

int main(int argc, char **argv)
{
	using namespace std;
	ifstream infile(argv[1]);
	if (!infile)
	{
		cerr << "open file error!";
		exit(1);
	}
	runQueries(infile);
	return 0;
}


12.33

class QueryResult
{
	friend std::ostream &print(std::ostream &os, const QueryResult &qr);
	std::string sought;
	std::shared_ptr<std::set<StrBlob::size_type>> lines;						//记录出现的行号
	std::shared_ptr<StrBlob> file;									//关联到文件内容
public:
	QueryResult(std::string s,const std::shared_ptr<std::set<StrBlob::size_type>> &p, std::shared_ptr<StrBlob> f) :sought(s), lines(p), file(f){}
	std::set<StrBlob::size_type>::iterator begin()const{ return lines->begin(); }
	std::set<StrBlob::size_type>::iterator end()const{ return lines->end(); }
	std::shared_ptr<StrBlob> get_file()const{ return file; }
};





2015年12月3日12:15:51



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值