C++ Prime 第十二章 动态内存
2023-05-05~2023-05-07
12.1.1节练习
练习12.1:
b1:4个元素,b2:4个元素
练习12.2:
#include<iostream>
#include<vector>
#include<memory>
using namespace std;
class StrBlob
{
public:
StrBlob() : data(make_shared<vector<string>>()) {};
StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {};
vector<string>::size_type size() const
{
return data->size();
}
bool empty() const { return data->empty(); };
void push_back(const string& s)
{
data->push_back(s);
}
string& front()
{
check(0, "front on empty StrBlob");
return data->front();
}
string& back()
{
check(0, "back on empty StrBlo");
return data->back();
}
void pop_back()
{
check(0, "pop_back on empty StrBlo");
data->pop_back();
}
string& const front() const
{
check(0, "const front on empty StrBlob");
return data->front();
}
string& const back() const
{
check(0, "const back on empty StrBlob");
return data->back();
}
private:
shared_ptr<vector<string>> data;
void check(vector<string>::size_type i, const string& msg) const
{
if (i >= data->size())
{
throw out_of_range(msg);
}
}
};
练习12.3:
不需要,const对象不应该被修改
练习12.4:
check函数是一个私有函数,提供给类内部其他函数操作数据时的一个前置检查,应该由其他函数通过参数的形式来判断,而不是在check函数内部进行限制
练习12.5:
略
12.1.2节练习:
练习12.6:
#include<iostream>
#include<vector>
#include<memory>
using namespace std;
vector<int>* get_vec_ptr()
{
vector<int>* vecPtr = new vector<int>();
return vecPtr;
}
void push_vec(vector<int>* ptr)
{
int temp;
while (cin >> temp)
{
ptr->push_back(temp);
}
}
void print_vec(vector<int>* ptr)
{
for (size_t i = 0; i < (*ptr).size(); ++i)
{
cout << (*ptr)[i] << endl;
}
}
int main()
{
auto ptr = get_vec_ptr();
push_vec(ptr);
print_vec(ptr);
delete ptr;
ptr = nullptr;
system("pause");
return 0;
}
练习12.7:
#include<iostream>
#include<vector>
#include<memory>
using namespace std;
shared_ptr<vector<int>> get_vec_ptr()
{
shared_ptr<vector<int>> ptr(new vector<int>());
return ptr;
}
void push_vec(shared_ptr<vector<int>> ptr)
{
int temp;
while (cin >> temp)
{
(*ptr).push_back(temp);
}
}
void print_vec(shared_ptr<vector<int>> ptr)
{
for (size_t i = 0; i < (*ptr).size(); ++i)
{
cout << (*ptr)[i] << endl;
}
}
int main()
{
auto ptr = get_vec_ptr();
push_vec(ptr);
print_vec(ptr);
system("pause");
return 0;
}
练习12.8:
错误,函数返回值类型是bool但是实际上返回的是一个int类型的指针
练习12.9:
r指针指向的内存空间还没释放就将r指针重新指向q指针指向的内存空间,存在内存泄露问题
智能指针r2指向q2时,由于r2原本指向的内存空间的引用计数=0,该内存空间被释放,智能指针q2的引用计数+1
12.1.3节练习
练习12.10:
代码可以正常执行,但是使用process(p)方式可以减小性能开销,不需要额外创建一个临时变量,创建、销毁临时变量都会影响开销
练习12.11:
会导致指针指针p被释放两次引起程序异常
练习12.12:
(a)合法,将智能指针sp通过值传递的方式传递给函数process
(b)、(c)不合法,无法通过隐式转化将new分配的指针转化成指针指针
(d)合法,创建一个临时变量,将临时变量传递给函数process
练习12.13:
程序结束时会自动释放智能指针sp指向的内存空间,但是该内存空间已经被指针p释放过了,重复释放会导致程序异常
12.1.4节练习
练习12.14:
#include<iostream>
#include<vector>
#include<memory>
using namespace std;
struct destination {};
struct connection
{
connection(destination&) {};
};
connection connect(destination& d)
{
cout << "连接" << endl;
return connection(d);
};
void disconnect(connection* c)
{
cout << "关闭" << endl;
};
void end_connect(connection* c) { disconnect(c); };
void f(destination& d)
{
connection c = connect(d);
shared_ptr<connection> cptr(&c, end_connect);
}
int main()
{
destination info;
f(info);
system("pause");
return 0;
}
练习12.15:
#include<iostream>
#include<vector>
#include<memory>
using namespace std;
struct destination {};
struct connection
{
connection(destination&) {};
};
connection connect(destination& d)
{
cout << "连接" << endl;
return connection(d);
};
void disconnect(connection* c)
{
cout << "关闭" << endl;
};
void f(destination& d)
{
connection c = connect(d);
shared_ptr<connection> cptr(&c, [](connection* p) {disconnect(p); });
}
int main()
{
destination info;
f(info);
system("pause");
return 0;
}
12.1.5节练习
练习12.16:
略
练习12.17:
(a)错误,不能将一个int类型的数据赋值给unique_ptr< int > 类型
(b)、(d)错误,将智能指针指向非动态内存的指针
(c)、(e)合法
(f)对同一内存空间重复释放,导致程序异常
练习12.18:
release用来放弃并转让对内存空间的所有权,shared_ptr类型的指针可以通过赋值、拷贝的方式进行所有权的放弃、转让
12.1.6节练习
练习12.19:
#include<iostream>
#include<vector>
#include<memory>
using namespace std;
class StrBlob
{
friend class StrBlobPtr;
public:
StrBlob() : data(make_shared<vector<string>>()) {};
StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {};
vector<string>::size_type size() const
{
return data->size();
}
bool empty() const { return data->empty(); };
void push_back(const string& s)
{
data->push_back(s);
}
string& front()
{
check(0, "front on empty StrBlob");
return data->front();
}
string& back()
{
check(0, "back on empty StrBlo");
return data->back();
}
void pop_back()
{
check(0, "pop_back on empty StrBlo");
data->pop_back();
}
string& const front() const
{
check(0, "const front on empty StrBlob");
return data->front();
}
string& const back() const
{
check(0, "const back on empty StrBlob");
return data->back();
}
StrBlobPtr begin();
StrBlobPtr end();
private:
shared_ptr<vector<string>> data;
void check(vector<string>::size_type i, const string& msg) const
{
if (i >= data->size())
{
throw out_of_range(msg);
}
}
};
class StrBlobPtr
{
public:
StrBlobPtr() : curr(0) {};
StrBlobPtr(StrBlob& s, size_t sz = 0) : wptr(s.data), curr(sz) {};
string& deref() const
{
auto ret = check(curr, "increment past end of StrBlobPtr");
return (*ret)[curr];
}
StrBlobPtr& incr()
{
auto ret = check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
StrBlobPtr& redu()
{
auto ret = check(curr-1, "increment past end of StrBlobPtr");
--curr;
return *this;
}
private:
size_t curr;
weak_ptr<vector<string>> wptr;
shared_ptr<vector<string>> check(size_t i, const string& msg) const
{
auto ret = wptr.lock();
if (!ret)
{
throw runtime_error("wptr unbound");
}
if (i > ret->size())
{
throw out_of_range(msg);
}
return ret;
}
};
StrBlobPtr StrBlob::begin()
{
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
int main()
{
StrBlob s1 = { "1", "2", "3" };
StrBlobPtr sptr1 = s1.begin();
cout << sptr1.deref() << endl;
StrBlobPtr sptr2 = s1.end();
sptr2.redu();
cout << sptr2.deref() << endl;
system("pause");
return 0;
}
练习12.20:
#include<iostream>
#include<vector>
#include<memory>
#include<fstream>
#include<sstream>
using namespace std;
class StrBlob
{
friend class StrBlobPtr;
public:
StrBlob() : data(make_shared<vector<string>>()) {};
StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {};
vector<string>::size_type size() const
{
return data->size();
}
bool empty() const { return data->empty(); };
void push_back(const string& s)
{
data->push_back(s);
}
string& front()
{
check(0, "front on empty StrBlob");
return data->front();
}
string& back()
{
check(0, "back on empty StrBlo");
return data->back();
}
void pop_back()
{
check(0, "pop_back on empty StrBlo");
data->pop_back();
}
string& const front() const
{
check(0, "const front on empty StrBlob");
return data->front();
}
string& const back() const
{
check(0, "const back on empty StrBlob");
return data->back();
}
StrBlobPtr begin();
StrBlobPtr end();
private:
shared_ptr<vector<string>> data;
void check(vector<string>::size_type i, const string& msg) const
{
if (i >= data->size())
{
throw out_of_range(msg);
}
}
};
class StrBlobPtr
{
public:
StrBlobPtr() : curr(0) {};
StrBlobPtr(StrBlob& s, size_t sz = 0) : wptr(s.data), curr(sz) {};
string& deref() const
{
auto ret = check(curr, "increment past end of StrBlobPtr");
return (*ret)[curr];
}
StrBlobPtr& incr()
{
auto ret = check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
StrBlobPtr& redu()
{
auto ret = check(curr-1, "increment past end of StrBlobPtr");
--curr;
return *this;
}
private:
size_t curr;
weak_ptr<vector<string>> wptr;
shared_ptr<vector<string>> check(size_t i, const string& msg) const
{
auto ret = wptr.lock();
if (!ret)
{
throw runtime_error("wptr unbound");
}
if (i > ret->size())
{
throw out_of_range(msg);
}
return ret;
}
};
StrBlobPtr StrBlob::begin()
{
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
int main()
{
StrBlob s1;
ifstream fs("data.txt");
string line;
int times = 0;
while (getline(fs, line))
{
string word;
istringstream ss(line);
while (ss >> word)
{
s1.push_back(word);
++times;
}
}
StrBlobPtr sptr1 = s1.begin();
while (times>0)
{
cout << sptr1.deref() << endl;
sptr1.incr();
--times;
}
system("pause");
return 0;
}
练习12.21:
略
练习12.22:
增加const类型的构造函数、cbegin、cend
#include<iostream>
#include<vector>
#include<memory>
#include<fstream>
#include<sstream>
using namespace std;
class StrBlob
{
friend class StrBlobPtr;
public:
StrBlob() : data(make_shared<vector<string>>()) {};
StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {};
vector<string>::size_type size() const
{
return data->size();
}
bool empty() const { return data->empty(); };
void push_back(const string& s)
{
data->push_back(s);
}
string& front()
{
check(0, "front on empty StrBlob");
return data->front();
}
string& back()
{
check(0, "back on empty StrBlo");
return data->back();
}
void pop_back()
{
check(0, "pop_back on empty StrBlo");
data->pop_back();
}
string& const front() const
{
check(0, "const front on empty StrBlob");
return data->front();
}
string& const back() const
{
check(0, "const back on empty StrBlob");
return data->back();
}
StrBlobPtr begin();
StrBlobPtr end();
StrBlobPtr cbegin() const;
StrBlobPtr cend() const;
private:
shared_ptr<vector<string>> data;
void check(vector<string>::size_type i, const string& msg) const
{
if (i >= data->size())
{
throw out_of_range(msg);
}
}
};
class StrBlobPtr
{
public:
StrBlobPtr() : curr(0) {};
StrBlobPtr(StrBlob& s, size_t sz = 0) : wptr(s.data), curr(sz) {};
StrBlobPtr(const StrBlob& s, size_t sz = 0) : wptr(s.data), curr(sz) {};
string& deref() const
{
auto ret = check(curr, "increment past end of StrBlobPtr");
return (*ret)[curr];
}
StrBlobPtr& incr()
{
auto ret = check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
StrBlobPtr& redu()
{
auto ret = check(curr-1, "increment past end of StrBlobPtr");
--curr;
return *this;
}
private:
size_t curr;
weak_ptr<vector<string>> wptr;
shared_ptr<vector<string>> check(size_t i, const string& msg) const
{
auto ret = wptr.lock();
if (!ret)
{
throw runtime_error("wptr unbound");
}
if (i > ret->size())
{
throw out_of_range(msg);
}
return ret;
}
};
StrBlobPtr StrBlob::begin()
{
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end()
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
StrBlobPtr StrBlob::cbegin() const
{
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::cend() const
{
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
int main()
{
const StrBlob s1 = {"100", "200", "300"};
int times = s1.size();
StrBlobPtr sptr1 = s1.cbegin();
while (times > 0)
{
cout << sptr1.deref() << endl;
sptr1.incr();
--times;
}
system("pause");
return 0;
}
12.2.1节练习
练习12.23:
#include<iostream>
#include<vector>
#include<memory>
#include<fstream>
#include<sstream>
using namespace std;
int main()
{
char const* str1 = "abc";
char const* str2 = "def";
string s = string(str1) + str2;
char* p = new char[s.size()+1];
strcpy_s(p, s.size()+1, s.c_str());
for (int i = 0; i < s.size(); ++i)
{
cout << p[i] << endl;
}
string s1 = "abc";
string s2 = "bcd";
string s3 = s1 + s2;
char* p2 = new char[s3.size() + 1];
strcpy_s(p2, s3.size() + 1, s3.c_str());
for (int i = 0; i < s3.size(); ++i)
{
cout << p2[i] << endl;
}
system("pause");
return 0;
}
练习12.24:
#include<iostream>
#include<vector>
#include<memory>
#include<fstream>
#include<sstream>
using namespace std;
int main()
{
char temp;
char* p = new char[20];
int index = 0;
while (cin >> temp)
{
p[index++] = temp;
}
for (int i = 0; i < index; ++i)
{
cout << p[i] << endl;
}
delete[]p;
system("pause");
return 0;
}
练习12.25:
delete[] pa;
12.2.2节练习
练习12.26:
#include<iostream>
#include<vector>
#include<memory>
#include<fstream>
#include<sstream>
using namespace std;
int main()
{
int size = 20;
allocator<string> alloc;
auto const p = alloc.allocate(size);
auto q = p;
string temp;
while (cin >> temp && q != p + size)
{
alloc.construct(q++, temp);
}
while (q != p)
{
cout << *(--q) << endl;
alloc.destroy(q);
}
alloc.deallocate(p, size);
system("pause");
return 0;
}
12.3.1节练习
练习12.27:
#include<iostream>
#include<vector>
#include<memory>
#include<fstream>
#include<sstream>
#include<set>
#include<map>
using namespace std;
class QueryResult;
class TextQuery
{
public:
using line_no_type = vector<string>::size_type;
TextQuery(ifstream& infile)
{
// 创建vector<string>容器并使用智能指针管理
lines_vec = make_shared<vector<string>>();
string line;
string word;
int line_no = 0;
while (getline(infile, line))
{
// 分行保存到vector中
lines_vec->push_back(line);
istringstream ss(line);
while (ss >> word)
{
// 在单词与行号(set)的map映射中查找单词是否存在
// 如果存在,在该行号(set)中插入当前行
// 如果不存在,将这个行号(set)指针指向新创建的set
auto &line_no_set = this->word_lineno_map[word];
if (!line_no_set)
{
line_no_set.reset(new set<line_no_type>);
}
// set容器自带去重、排序
line_no_set->insert(line_no);
}
++line_no;
}
}
QueryResult query(const string& s);
private:
shared_ptr<vector<string>> lines_vec;
map<string, shared_ptr<set<line_no_type>>> word_lineno_map;
};
class QueryResult
{
using line_no_type = TextQuery::line_no_type;
friend ostream& print(ostream& out, const QueryResult& qr);
public:
QueryResult() = default;
QueryResult(const string& s, shared_ptr<vector<string>> l, shared_ptr<set<line_no_type>> l_no) :
word(s), lines(l), lines_no(l_no){};
private:
shared_ptr<vector<string>> lines;
shared_ptr<set<line_no_type>> lines_no;
const string word;
};
QueryResult TextQuery::query(const string& s)
{
auto ret = this->word_lineno_map.find(s);
if (ret != this->word_lineno_map.end())
{
return QueryResult(s, this->lines_vec, ret->second);
};
return QueryResult();
};
ostream& print(ostream& out, const QueryResult& qr)
{
if (qr.word == "")
{
out << "not found word" << endl;
return out;
}
out << qr.word << " occurs " << qr.lines_no->size() << " times " << endl;
for (auto line_no : *qr.lines_no)
{
cout << "\t" << "(line " << line_no << ")" << (*qr.lines)[line_no] << endl;
}
return out;
};
void runQueries(ifstream& infile)
{
TextQuery tq(infile);
string word;
while (cin >> word)
{
print(cout, tq.query(word));
}
}
int main()
{
ifstream infile("test_word.txt");
runQueries(infile);
system("pause");
return 0;
}
练习12.28:
#include<iostream>
#include<vector>
#include<memory>
#include<fstream>
#include<sstream>
#include<set>
#include<map>
using namespace std;
void get_txt_info(ifstream& infile, vector<string>&v, map<string, set<string::size_type>>&m)
{
string line;
string word;
string::size_type line_no = 0;
while (getline(infile, line))
{
v.push_back(line);
istringstream ss(line);
while (ss >> word)
{
m[word].insert(line_no);
}
++line_no;
}
}
void runQueries(ifstream& infile)
{
vector<string>lines;
map<string, set<string::size_type>> words_map;
get_txt_info(infile, lines, words_map);
string word;
while (cin >> word)
{
auto ret = words_map.find(word);
if (ret != words_map.end())
{
cout << word << " occurs " << words_map[word].size()+1 << " times " << endl;
for (auto line_no : words_map[word])
{
cout << "\t" << "(line " << line_no << ")" << lines[line_no] << endl;
}
}
else
{
cout << "not found" << endl;
}
}
}
int main()
{
ifstream infile("test_word.txt");
runQueries(infile);
system("pause");
return 0;
}
练习12.29:
略
12.3.2节练习
练习12.30:
答案见练习练习12.27
练习12.31:
vector按照插入顺序对数据进行排序,set按照字典顺序进行排序,vector可以重复插入相同的数据,对于单词出现次数统计的更精准
练习12.32:
#include<iostream>
#include<vector>
#include<memory>
#include<fstream>
#include<sstream>
#include<set>
#include<map>
using namespace std;
class TextQuery;
class StrBlob
{
public:
friend class TextQuery;
StrBlob() : data(make_shared<vector<string>>()) {};
StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {};
vector<string>::size_type size() const
{
return data->size();
}
bool empty() const { return data->empty(); };
void push_back(const string& s)
{
data->push_back(s);
}
string& front()
{
check(0, "front on empty StrBlob");
return data->front();
}
string& back()
{
check(0, "back on empty StrBlo");
return data->back();
}
void pop_back()
{
check(0, "pop_back on empty StrBlo");
data->pop_back();
}
string& const front() const
{
check(0, "const front on empty StrBlob");
return data->front();
}
string& const back() const
{
check(0, "const back on empty StrBlob");
return data->back();
}
private:
shared_ptr<vector<string>> data;
void check(vector<string>::size_type i, const string& msg) const
{
if (i >= data->size())
{
throw out_of_range(msg);
}
}
};
class QueryResult;
class TextQuery
{
public:
using line_no_type = vector<string>::size_type;
TextQuery(ifstream& infile)
{
// 创建vector<string>容器并使用智能指针管理
lines_vec = StrBlob();
string line;
string word;
int line_no = 0;
while (getline(infile, line))
{
// 分行保存到vector中
lines_vec.data->push_back(line);
istringstream ss(line);
while (ss >> word)
{
// 在单词与行号(set)的map映射中查找单词是否存在
// 如果存在,在该行号(set)中插入当前行
// 如果不存在,将这个行号(set)指针指向新创建的set
auto& line_no_set = this->word_lineno_map[word];
if (!line_no_set)
{
line_no_set.reset(new set<line_no_type>);
}
// set容器自带去重、排序
line_no_set->insert(line_no);
}
++line_no;
}
}
void test()
{
for (auto temp : *(this->lines_vec.data))
{
cout << temp << endl;
}
}
QueryResult query(const string& s);
private:
StrBlob lines_vec;
map<string, shared_ptr<set<line_no_type>>> word_lineno_map;
};
class QueryResult
{
using line_no_type = TextQuery::line_no_type;
friend ostream& print(ostream& out, const QueryResult& qr);
public:
QueryResult() = default;
QueryResult(const string& s, shared_ptr<vector<string>> l, shared_ptr<set<line_no_type>> l_no) :
word(s), lines(l), lines_no(l_no) {};
private:
shared_ptr<vector<string>> lines;
shared_ptr<set<line_no_type>> lines_no;
const string word;
};
QueryResult TextQuery::query(const string& s)
{
auto ret = this->word_lineno_map.find(s);
if (ret != this->word_lineno_map.end())
{
return QueryResult(s, this->lines_vec.data, ret->second);
};
return QueryResult();
};
ostream& print(ostream& out, const QueryResult& qr)
{
if (qr.word == "")
{
out << "not found word" << endl;
return out;
}
out << qr.word << " occurs " << qr.lines_no->size() << " times " << endl;
for (auto line_no : *qr.lines_no)
{
cout << "\t" << "(line " << line_no << ")" << (*qr.lines)[line_no] << endl;
}
return out;
};
void runQueries(ifstream& infile)
{
TextQuery tq(infile);
string word;
//tq.test();
while (cin >> word)
{
print(cout, tq.query(word));
}
}
int main()
{
ifstream infile("test_word.txt");
runQueries(infile);
system("pause");
return 0;
}
练习12.33:
#include<iostream>
#include<vector>
#include<memory>
#include<fstream>
#include<sstream>
#include<set>
#include<map>
using namespace std;
class TextQuery;
class StrBlob
{
public:
friend class TextQuery;
StrBlob() : data(make_shared<vector<string>>()) {};
StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {};
vector<string>::size_type size() const
{
return data->size();
}
bool empty() const { return data->empty(); };
void push_back(const string& s)
{
data->push_back(s);
}
string& front()
{
check(0, "front on empty StrBlob");
return data->front();
}
string& back()
{
check(0, "back on empty StrBlo");
return data->back();
}
void pop_back()
{
check(0, "pop_back on empty StrBlo");
data->pop_back();
}
string& const front() const
{
check(0, "const front on empty StrBlob");
return data->front();
}
string& const back() const
{
check(0, "const back on empty StrBlob");
return data->back();
}
private:
shared_ptr<vector<string>> data;
void check(vector<string>::size_type i, const string& msg) const
{
if (i >= data->size())
{
throw out_of_range(msg);
}
}
};
class QueryResult;
class TextQuery
{
public:
using line_no_type = vector<string>::size_type;
TextQuery(ifstream& infile)
{
// 创建vector<string>容器并使用智能指针管理
lines_vec = StrBlob();
string line;
string word;
int line_no = 0;
while (getline(infile, line))
{
// 分行保存到vector中
lines_vec.data->push_back(line);
istringstream ss(line);
while (ss >> word)
{
// 在单词与行号(set)的map映射中查找单词是否存在
// 如果存在,在该行号(set)中插入当前行
// 如果不存在,将这个行号(set)指针指向新创建的set
auto& line_no_set = this->word_lineno_map[word];
if (!line_no_set)
{
line_no_set.reset(new set<line_no_type>);
}
// set容器自带去重、排序
line_no_set->insert(line_no);
}
++line_no;
}
}
void test()
{
for (auto temp : *(this->lines_vec.data))
{
cout << temp << endl;
}
}
QueryResult query(const string& s);
private:
StrBlob lines_vec;
map<string, shared_ptr<set<line_no_type>>> word_lineno_map;
};
class QueryResult
{
using line_no_type = TextQuery::line_no_type;
friend ostream& print(ostream& out, const QueryResult& qr);
public:
QueryResult() = default;
QueryResult(const string& s, shared_ptr<vector<string>> l, shared_ptr<set<line_no_type>> l_no) :
word(s), lines(l), lines_no(l_no) {};
shared_ptr<vector<string>> get_file()
{
return this->lines;
}
set<line_no_type>::iterator cbegin() const
{
return (*this->lines_no).begin();
}
set<line_no_type>::iterator cend() const
{
return (*this->lines_no).end();
}
private:
shared_ptr<vector<string>> lines;
shared_ptr<set<line_no_type>> lines_no;
const string word;
};
QueryResult TextQuery::query(const string& s)
{
auto ret = this->word_lineno_map.find(s);
if (ret != this->word_lineno_map.end())
{
return QueryResult(s, this->lines_vec.data, ret->second);
};
return QueryResult();
};
ostream& print(ostream& out, const QueryResult& qr)
{
if (qr.word == "")
{
out << "not found word" << endl;
return out;
}
out << qr.word << " occurs " << qr.lines_no->size() << " times " << endl;
for (auto line_no : *qr.lines_no)
{
cout << "\t" << "(line " << line_no << ")" << (*qr.lines)[line_no] << endl;
}
return out;
};
void runQueries(ifstream& infile)
{
TextQuery tq(infile);
string word;
//tq.test();
while (cin >> word)
{
print(cout, tq.query(word));
}
}
int main()
{
ifstream infile("test_word.txt");
runQueries(infile);
system("pause");
return 0;
}
勇敢和愚蠢只有一剑之差