cppPrimer学习12th
cppPrimer学习12th
目录
12.1
b1 有4个
b2 元素销毁了
12.2
// 12.2 编写你自己的StrBlob类,包含const版本的front和back
#include "../include/include.h"
#include <initializer_list>
#include <memory>
#include <exception>
class StrBlob
{
public:
typedef vector<string>::size_type size_type;
() : data(make_shared<vector<string>>()) {}
StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
size_type size() const
{
return data->size();
}
bool empty() const
{
return data->empty();
}
void push_back(const string &s)
{
data->push_back(s);
}
void pop_back();
string &front();
string &back();
const string &front() const;
const string &back() const;
~StrBlob();
private:
shared_ptr<vector<string>> data;
void check(size_type i, const string &message) const
{
if (i >= data->size())
throw std::out_of_range(message);
}
};
StrBlob::~StrBlob()
{
}
string &StrBlob::front()
{
check(0, "front on empty StrBlob");
return data->front();
}
string &StrBlob::back()
{
check(0, "back on empty StrBlob");
return data->back();
}
const string &StrBlob::front() const
{
check(0, "front on empty StrBlob");
return data->front();
}
const string &StrBlob::back() const
{
check(0, "back on empty StrBlob");
return data->back();
}
void StrBlob::pop_back()
{
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
int main(int argc, const char **argv)
{
StrBlob csb{"1", "2", "3"};
StrBlob sb{"A1", "A2", "A3"};
std::cout << csb.front() << " " << csb.back() << std::endl;
sb.back() = "change";
std::cout << sb.front() << " " << sb.back() << std::endl;
while (1)
;
return 0;
}
12.3
不需要,因为这个操作本身会改变data指向的内容
12.4
size>=0 size_type 是unsigned的
12.5
如果有 initialize_list explicit的构造函数 那么就不能使用隐式转换了
没有的优点:
在需要 StrBlob的地方可以自动进行列表转换,比如使用一个类 StrBlob=("1","2");
缺点:
我们总是使用构造函数来构造一个临时的StrBlob对象
反之
编译器不会在自动转换中使用此构造函数,我们可以清楚地知道我们使用了哪个类
12.6
/*
编写函数,返回一个动态分配的int的vector。将此vector传递给另一个函数。这个函数读取标准输入,
将读入的值保存在vector中。再将vector传递给另一个函数,打印读入的值。记得在恰当的时刻delete vector
*/
#include <vector>
#include <memory>
#include <iostream>
using namespace std;
vector<int> *get_vector_int_pt(void)
{
return new vector<int>();
}
vector<int> *put_vector_int_pt(vector<int> *pt)
{
int num;
while (cin >> num)
pt->push_back(num);
return pt;
}
void show_vector_int_pt(vector<int> *pt)
{
for (int a : *pt)
cout << a << " ";
cout << endl;
}
int main(int argc, char const *argv[])
{
vector<int> *t = get_vector_int_pt();
put_vector_int_pt(t);
show_vector_int_pt(t);
delete t;
while (1)
;
return 0;
}
12.7
/*
12.7 使用 shared_ptr
编写函数,返回一个动态分配的int的vector。将此vector传递给另一个函数。这个函数读取标准输入,
将读入的值保存在vector中。再将vector传递给另一个函数,打印读入的值。记得在恰当的时刻delete vector
*/
#include <vector>
#include <memory>
#include <iostream>
using namespace std;
shared_ptr<vector<int>> get_vector_int_pt(void)
{
return make_shared<vector<int>>();
}
shared_ptr<vector<int>> put_vector_int_pt(shared_ptr<vector<int>> pt)
{
int num;
while (cin >> num)
pt->push_back(num);
return pt;
}
void show_vector_int_pt(shared_ptr<vector<int>> pt)
{
for (int a : *pt)
cout << a << " ";
cout << endl;
}
int main(int argc, char const *argv[])
{
shared_ptr<vector<int>> t = get_vector_int_pt();
put_vector_int_pt(t);
show_vector_int_pt(t);
while (1)
;
return 0;
}
12.8
p 是一个指针,转换为bool, 但是p原来的内存永远不会释放了
12.9
r和q指向42,但是r原来的内存无法释放,同时两个指针指向同一个地方
可能释放了一个指针后,另一个没释放的指向已经释放的内存,也就是空悬指针问题
r2指向q2,同时原来r2 内存释放
12.10
void process(shared_ptr ptr) // 注意这里是值拷贝,也就是引用+1
{
// 使用ptr
}
//离开后释放ptr
//p 指向int
shared_ptr<int>p(new int(42));
process(shared_ptr<int>p);
这里p不会被释放的
p.reset(); //执行释放
这段代码本身没有问题
12.11
有两个共享指针指向了同一个区域
也就是退出函数后 p的内存已经被这个临时共享指针对象释放了
12.12
void process(shared_ptr ptr) // 注意这里是值拷贝,也就是引用+1
{
// 使用ptr
}
//离开后释放ptr
a 合法
b,c 非法,没有隐式转换的构造函数
d 合法,但是会删除p的内存
12.13
sp指向int
p 释放了sp的内容,但是sp的计数还在,所以sp会再次释放
也就是释放了两次
12.14
12.15
//shared_ptr<connection>p (&c,[](struct connection*p){disconnect(*p);});
/*
12.14+12.15
智能指针与异常结合的使用
当异常发生后,我们在异常发生之后的语句无法执行,比如一些资源清理操作,这个时候可以把清理动作作为一个共享指针的delte参数
shared_ptr<connection> end_link(&linkme, try_end_link); try_end_link 在程序结束或者异常后能够执行
*/
#include <vector>
#include <memory>
#include <iostream>
using namespace std;
struct connection
{
int fd;
};
struct disconnection
{
int fd;
int port;
};
connection
connect(struct disconnection *t)
{
struct connection ret;
ret.fd = t->port + 1;
cout << "link to port:" << t->port << endl;
return ret;
}
disconnection
disconnect(struct connection *t)
{
struct disconnection ret;
if (t->fd > 0)
{
ret.fd = -1;
ret.port = t->fd - 1;
cout << "break LINK to port:" << ret.port << endl;
t->fd = -1;
}
return ret;
}
void try_end_link(struct connection *t)
{
cout << "By shared_ptr" << endl;
disconnect(t);
}
int main(int argc, char const *argv[])
{
{
struct disconnection unlinkme = {-1, 20};
connection linkme = connect(&unlinkme);
// disconnect(&linkme);
//shared_ptr<connection> end_link(&linkme, try_end_link);
shared_ptr<connection> end_link(&linkme, [](struct connection *t) {cout << "By shared_ptr" << endl;disconnect(t); });
}
while (1)
;
return 0;
}
12.16
/*
12.16 给一个unique_ptr 赋值观察错误
*/
#include <iostream>
#include <memory>
using namespace std;
int main(int argc, char const *argv[])
{
unique_ptr<int> p(new int(3));
int *pint = new int(3);
unique_ptr<int> p_unique(new int(3));
//unique_ptr<int> s(3);
// no known conversion for argument 1 from 'int*' to 'std::nullptr_t'
//p = pint;
// use of deleted function 'std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]'
//unique_ptr& operator=(const unique_ptr&) = delete;
//p = p_unique;
while (1)
;
return 0;
}
12.17
下面的unique_ptr声明中,哪些是合法的,哪些可能导致后续的程序错误?
int ix = 1024, *pi = &ix, *pi2 = new int(20478);
typedef unique_ptr<int> IntP;
(a) IntP p0(ix); 非法,无法将int转为指针
(b) IntP p1(pi); 合法,但是----原始内容是int 不是new出来的,无法del
(c) IntP p2(pi2); 合法,两个指针指向同一个内存
(d) IntP p3(&ix); 同b非法
(e) IntP p4(new int(2048)); 合法
(f) IntP p5(p2.get()); 合法,但是----两个指针指向同一个地方
12.18
release 是放弃控制权清空unique_ptr
release操作是用来将对象的所有权转移给另一个unique_ptr的
share_ptr 本身就没有控制权,可以相互拷贝赋值
12.19
12.20
/*
12.19
12.20 读入文件 使用这个类
一个 StrBlob类,底层数据是指向 vector<string> 的指针
一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
定义 StrBlob类,数据成员是 vector<string> 的shared_ptr
begin 指向第一个元素的 StrBlob_ptr 也就是cur=0?
end 最后一个元素的指针cur=size() end是开区间,所以不用减1
定义 StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
一个指向 vector<string> 的指针,带有小标
* 获得string
++ 将下标++
*/
#include <vector>
#include <string>
#include <memory>
#include <initializer_list>
#include <exception>
#include <iostream>
#include <fstream>
using namespace std;
class StrBlob_ptr;
class StrBlob
{
using Blob_size_type = vector<string>::size_type;
friend class StrBlob_ptr;
private:
/* data */
shared_ptr<vector<string>> data;
public:
StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
StrBlob_ptr begin(); //{ return StrBlob_ptr(*this); }
StrBlob_ptr end(); //{ return StrBlob_ptr(*this, data->size()); }
Blob_size_type size() const
{
return data->size();
}
bool empty() const
{
return data->empty();
}
bool check(Blob_size_type has, const string &msg) const
{
if (has >= data->size())
throw std::out_of_range(msg);
}
void push_back(string &s)
{
data->push_back(s);
}
void pop_back()
{
check(0, "pop_back");
data->pop_back();
}
string &front()
{
check(0, "front");
return data->front();
}
string &back()
{
check(0, "back");
return data->back();
}
const string &front() const
{
check(0, "front");
return data->front();
}
const string &back() const
{
check(0, "back");
return data->back();
}
~StrBlob() {}
};
class StrBlob_ptr
{
private:
// 底层指针指向的内容是 shared_ptr,可能存在释放的情况
weak_ptr<vector<string>> ptr;
int cur;
shared_ptr<vector<string>> check(int size, const string msg) const;
public:
// 构造函数,指向空的ptr
StrBlob_ptr() : cur(0) {}
StrBlob_ptr(StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
~StrBlob_ptr() {}
// * 解引用
string &deref() const;
StrBlob_ptr &increase_ref();
// 同时需要定义!= 这里应该还要判断 p的指向是否相同
bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
};
shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
{
auto ptr_get = ptr.lock();
if (!ptr_get)
throw runtime_error(msg);
if (size >= ptr_get->size())
throw out_of_range(msg);
return ptr_get;
}
string &StrBlob_ptr::deref() const
{
auto ptr_get = check(cur, "get shared_ptr");
return (*ptr_get)[cur];
}
StrBlob_ptr &StrBlob_ptr::increase_ref()
{
check(cur, "get shared_ptr");
cur++;
return *this;
}
/*
* 这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
*
*
*
*/
StrBlob_ptr StrBlob::begin()
{
return StrBlob_ptr(*this);
}
StrBlob_ptr StrBlob::end()
{
return StrBlob_ptr(*this, data->size());
}
int main(int argc, const char **argv)
{
StrBlob csb{"1", "2", "3"};
StrBlob sb{"A1", "A2", "A3"};
std::cout << csb.front() << " " << csb.back() << std::endl;
sb.back() = "change";
std::cout << sb.front() << " " << sb.back() << std::endl;
cout << "vector string :" << endl;
for (StrBlob_ptr ch = sb.begin(); ch != sb.end(); ch.increase_ref())
cout << ch.deref() << ",";
cout << endl;
ifstream ifile("./12.19.cpp");
StrBlob fs_blob;
for (string str; getline(ifile, str);)
fs_blob.push_back(str);
cout << "file string :" << endl;
for (StrBlob_ptr ch = fs_blob.begin(); ch != fs_blob.end(); ch.increase_ref())
cout << ch.deref() << endl;
while (1)
;
return 0;
}
12.21
原来的好,原来的好看 哈哈哈
12.22
/*
12.19
12.20 读入文件 使用这个类
12.22 使用 const StrBlob类
strBlob begin end 返回const
底层指针是个const,只有在构造的时候赋值
解引用的时候返回const
一个 StrBlob类,底层数据是指向 vector<string> 的指针
一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
定义 StrBlob类,数据成员是 vector<string> 的shared_ptr
begin 指向第一个元素的 StrBlob_ptr 也就是cur=0?
end 最后一个元素的指针cur=size() end是开区间,所以不用减1
定义 StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
一个指向 vector<string> 的指针,带有小标
* 获得string
++ 将下标++
*/
#include <vector>
#include <string>
#include <memory>
#include <initializer_list>
#include <exception>
#include <iostream>
#include <fstream>
using namespace std;
class StrBlob_ptr;
class StrBlob
{
using Blob_size_type = vector<string>::size_type;
friend class StrBlob_ptr;
private:
/* data */
shared_ptr<vector<string>> data;
public:
StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
StrBlob_ptr begin() const; //{ return StrBlob_ptr(*this); }
StrBlob_ptr end() const; //{ return StrBlob_ptr(*this, data->size()); }
Blob_size_type size() const
{
return data->size();
}
bool empty() const
{
return data->empty();
}
bool check(Blob_size_type has, const string &msg) const
{
if (has >= data->size())
throw std::out_of_range(msg);
}
void push_back(string &s)
{
data->push_back(s);
}
void pop_back()
{
check(0, "pop_back");
data->pop_back();
}
string &front()
{
check(0, "front");
return data->front();
}
string &back()
{
check(0, "back");
return data->back();
}
const string &front() const
{
check(0, "front");
return data->front();
}
const string &back() const
{
check(0, "back");
return data->back();
}
~StrBlob() {}
};
class StrBlob_ptr
{
private:
// 底层指针指向的内容是 shared_ptr,可能存在释放的情况
weak_ptr<vector<string>> ptr;
int cur;
shared_ptr<vector<string>> check(int size, const string msg) const;
public:
// 构造函数,指向空的ptr
StrBlob_ptr() : cur(0) {}
StrBlob_ptr(const StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
~StrBlob_ptr() {}
// * 解引用
const string &deref() const;
StrBlob_ptr &increase_ref();
// 同时需要定义!= 这里应该还要判断 p的指向是否相同
bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
};
shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
{
auto ptr_get = ptr.lock();
if (!ptr_get)
throw runtime_error(msg);
if (size >= ptr_get->size())
throw out_of_range(msg);
return ptr_get;
}
const string &StrBlob_ptr::deref() const
{
auto ptr_get = check(cur, "get shared_ptr");
return (*ptr_get)[cur];
}
StrBlob_ptr &StrBlob_ptr::increase_ref()
{
check(cur, "get shared_ptr");
cur++;
return *this;
}
/*
* 这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
*
*
*
*/
StrBlob_ptr StrBlob::begin() const
{
return StrBlob_ptr(*this);
}
StrBlob_ptr StrBlob::end() const
{
return StrBlob_ptr(*this, data->size());
}
int main(int argc, const char **argv)
{
const StrBlob csb{"1", "2", "3"};
StrBlob sb{"A1", "A2", "A3"};
std::cout << csb.front() << " " << csb.back() << std::endl;
sb.back() = "change";
std::cout << sb.front() << " " << sb.back() << std::endl;
cout << "vector string :" << endl;
for (StrBlob_ptr ch = sb.begin(); ch != sb.end(); ch.increase_ref())
cout << ch.deref() << ",";
cout << endl;
ifstream ifile("./12.19.cpp");
StrBlob fs_blob;
for (string str; getline(ifile, str);)
fs_blob.push_back(str);
cout << "file string :" << endl;
for (StrBlob_ptr ch = fs_blob.begin(); ch != fs_blob.end(); ch.increase_ref())
cout << ch.deref() << endl;
while (1)
;
return 0;
}
12.23
/*
编写一个程序,连接两个字符串字面值常量,将结果保存在一个动态分配的char数组中。重写这个程序,连接两个标准库string对象
*/
#include <string>
#include <string.h>
#include <iostream>
using std::cout;
using std::endl;
using std::string;
int main(int argc, char const *argv[])
{
const char *c1 = "hello";
const char *c2 = " world";
char *c3 = new char[strlen(c1) + strlen(c2) + 1];
memcpy(c3, c1, strlen(c1));
memcpy(c3 + strlen(c1), c2, strlen(c2));
c3[strlen(c1) + strlen(c2)] = 0;
string s1(c1), s2(c2);
string s3 = s1 + s2;
char *s4 = new char[s3.length()];
strcpy(s4, s3.c_str());
cout << string(c3) << endl;
cout << s3 << endl;
cout << s4 << endl;
while (1)
;
return 0;
}
12.24
/*12.24:编写一个程序,从标准输入读取一个字符串,存入一个动态分配的字符数组中。描述你的程序如何处理变长。测试你的程序,输入一个超出你分配的数组长度的字符串*/
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
char c;
char *s = new char[4];
int i = 0;
int len = 4;
while (cin >> c)
{
if (i >= len - 1)
{
char *s_new = new char[len * 2];
memcpy(s_new, s, len - 1);
len *= 2;
delete[] s;
s = s_new;
cout << "before len:" << len / 2 << ",arter len=" << len << " last char is " << s_new[i - 1] << endl;
}
if (c == '\r' || c == '\n')
break;
s[i++] = c;
}
s[i] = 0;
cout << s << endl;
while (1)
;
return 0;
}
12.25
int *pa = new int[10];
如何释放pa?
delete[] pa
12.26
/*
12.26 使用 allocater 替代new
*/
#include <iostream>
#include <string>
#include <memory>
using namespace std;
void old_test()
{
cout << "use new[] " << endl;
string *const p = new string[10];
string s, *q = p;
while (cin >> s && q != p + 10)
{
*q++ = s; // q=s q++
}
const size_t size = q - p; // 实际使用的内存
for (int i = 0; i < size; i++)
cout << p[i] << endl;
delete[] p;
cout << "end of use new[] " << endl;
}
void new_test()
{
cout << "use allocater " << endl;
allocator<string> allocator_string;
auto const p = allocator_string.allocate(10);
string *q = p;
string s;
while (cin >> s && q != p + 10)
{
allocator_string.construct(q++, s);
}
for (size_t i = 0; i < q - p; i++)
{
cout << p[i] << endl;
}
while (q != p)
{
allocator_string.destroy(--q);
}
allocator_string.deallocate(p, 100);
cout << "end of use allocater " << endl;
}
int main(int argc, char const *argv[])
{
/* code */
//old_test();
new_test();
while (1)
;
return 0;
}
12.27
#include <string>
#include <map>
#include <set>
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <memory>
using namespace std;
// 0. 没有使用 Query类保存结果,这里的简单例子直接从 TextQuery取得结果
// 1. 使用 vector<string> 保存每行文字
// 2. 每个string 有一个set 保存行号
// 3. 使用 map<string,set>绑定这个数据
class TextQuery
{
private:
/* data */
vector<string> txtline;
map<string, set<int>> data;
public:
TextQuery(ifstream &file);
~TextQuery(){};
ostream &GetWant(ostream &out, string ch);
};
TextQuery::TextQuery(ifstream &file)
{
// 读入文件到文件流,保存每一行到vector<string>
string s;
int line_at = 0;
while (getline(file, s))
{
txtline.push_back(s);
string ch;
istringstream ss(s);
while (ss >> ch)
{
data[ch].insert(line_at);
}
line_at++;
}
}
ostream &TextQuery::GetWant(ostream &out, string ch)
{
out << "[" << ch << "]:" << endl;
for (auto i = data[ch].begin(); i != data[ch].end(); i++)
out << "Line[" << (*i) + 1 << "]: " << txtline[*i] << endl;
return out;
}
void runQueries(ifstream &file)
{
// 从文件流建立查询的数据
TextQuery tq(file);
while (true)
{
cout << "Enter what you want to find?" << endl;
string s;
if (!(cin >> s) || s == "q")
break;
tq.GetWant(cout, s);
}
}
int main(int argc, char const *argv[])
{
ifstream fs("D:\\a.txt");
runQueries(fs);
return 0;
}
12.27.1
#include <string>
#include <map>
#include <set>
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <memory>
using namespace std;
/*
定义一个类 保存 string,行号,以及一个指向txt的指针
*/
class ResultQuery
{
friend ostream &print(ostream &, const ResultQuery &);
public:
// 单词
string w;
// 行号的列表
shared_ptr<set<int>> lines;
// 全部的文本,可以通过行号寻找
shared_ptr<vector<string>> txtline;
public:
ResultQuery(string word, shared_ptr<set<int>> line_num, shared_ptr<vector<string>> txt) : w(word), lines(line_num), txtline(txt){};
~ResultQuery(){};
};
class TextQuery
{
private:
/* data */
shared_ptr<vector<string>> txtline;
// 因为在ret里面共享的是set的行号,所以这里也是行号共享指针,而不是整个map
map<string, shared_ptr<set<int>>> data;
public:
TextQuery(ifstream &file);
ResultQuery Query(string &w);
~TextQuery(){};
};
TextQuery::TextQuery(ifstream &file) : txtline(new vector<string>)
{
// 读入文件到文件流,保存每一行到vector<string>
string s;
int line_at = 0;
while (getline(file, s))
{
txtline->push_back(s);
string ch;
istringstream ss(s);
while (ss >> ch)
{
if (!data[ch])
data[ch].reset(new set<int>);
data[ch]->insert(line_at);
}
line_at++;
}
}
ResultQuery TextQuery::Query(string &w)
{
static shared_ptr<std::set<int>> nodate(new std::set<int>);
auto found = data.find(w);
if (found == data.end())
return ResultQuery(w, nodate, txtline);
else
return ResultQuery(w, data[w], txtline);
}
//ostream &print(ostream &, const ResultQuery &)
ostream &print(ostream &out, const ResultQuery &want)
{
out << "----------------------------------------------" << endl;
out << "string:" << want.w << endl;
out << "Txt List:" << endl;
//if (want.lines) // 先要判断指针是否存在
{
for (auto ls : *(want.lines))
out << ls << ":\t\t\t" << want.txtline->at(ls) << endl;
//qr.input->at(i)
}
out << "----------------------------------------------" << endl;
return out;
}
void runQueries(ifstream &file)
{
// 从文件流建立查询的数据
TextQuery tq(file);
while (true)
{
cout << "Enter what you want to find?" << endl;
string s;
if (!(cin >> s) || s == "q")
break;
print(cout, tq.Query(s)) << endl;
}
}
int main(int argc, char const *argv[])
{
ifstream fs("D:\\a.txt");
if (fs)
runQueries(fs);
else
cout << "fs open failed " << endl;
while (1)
;
return 0;
}
12.28
/*
12.28:编写程序实现文本查询,不要定义类来管理数据,你的程序应该接受一个文件,并与用户交互来查询单词。
使用vector、map和set容器来保存来自文件的数据并生成查询结果。
*/
#include <string>
#include <map>
#include <set>
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <memory>
using namespace std;
void test(ifstream &file)
{
vector<string> txtline;
map<string, set<int>> num;
// 读入文件到文件流,保存每一行到vector<string>
string s;
int line_at = 0;
while (getline(file, s))
{
txtline.push_back(s);
string ch;
istringstream ss(s);
while (ss >> ch)
{
num[ch].insert(line_at);
}
line_at++;
}
string ch;
cout << "pls input word to search" << endl;
while (cin >> ch)
{
cout << "find " << ch << endl;
for (auto i : num[ch])
{
cout << "line:" << i << "]:" << txtline[i] << endl;
}
}
}
int main(int argc, char const *argv[])
{
ifstream fin("C:\\JLink.log");
if (fin)
test(fin);
else
cout << "check file" << endl;
while (1)
;
return 0;
}
12.29
差不多
12.31
vector 会有重复行号,需要处理相同行号
12.32
/*
12.32
重写TextQuery和QueryResult类,用StrBlob代替vector<vector>保存输入文件
TextQuery 使用StrBlob 存储shared_ptr<vector<string>> 文本
具体查询打印的时候,我们要从 *(StrBlob.ptr) 中取小标
也就是 使用 StrBlob_ptr 这个类指向了StrBlob中vector[下标]
github的答案是这里 使用 shared_ptr 执行StrBlob 也就是 shared_ptr<StrBlob> 的操作,
*/
/*
12.19
12.20 读入文件 使用这个类
12.22 使用 const StrBlob类
strBlob begin end 返回const
底层指针是个const,只有在构造的时候赋值
解引用的时候返回const
一个 StrBlob类,底层数据是指向 vector<string> 的指针
一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
定义 StrBlob类,数据成员是 vector<string> 的shared_ptr
begin 指向第一个元素的 StrBlob_ptr 也就是cur=0?
end 最后一个元素的指针cur=size() end是开区间,所以不用减1
定义 StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
一个指向 vector<string> 的指针,带有小标
* 获得string
++ 将下标++
*/
#include <vector>
#include <string>
#include <memory>
#include <initializer_list>
#include <exception>
#include <iostream>
#include <fstream>
#include <set>
#include <map>
#include <sstream>
using namespace std;
class StrBlob_ptr;
class StrBlob
{
using Blob_size_type = vector<string>::size_type;
friend class StrBlob_ptr;
private:
/* data */
shared_ptr<vector<string>> data;
public:
StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
StrBlob_ptr begin() const; //{ return StrBlob_ptr(*this); }
StrBlob_ptr end() const; //{ return StrBlob_ptr(*this, data->size()); }
Blob_size_type size() const
{
return data->size();
}
bool empty() const
{
return data->empty();
}
bool check(Blob_size_type has, const string &msg) const
{
if (has >= data->size())
throw std::out_of_range(msg);
}
void push_back(string &s)
{
data->push_back(s);
}
void pop_back()
{
check(0, "pop_back");
data->pop_back();
}
string &front()
{
check(0, "front");
return data->front();
}
string &back()
{
check(0, "back");
return data->back();
}
const string &front() const
{
check(0, "front");
return data->front();
}
const string &back() const
{
check(0, "back");
return data->back();
}
~StrBlob() {}
};
class StrBlob_ptr
{
private:
// 底层指针指向的内容是 shared_ptr,可能存在释放的情况
weak_ptr<vector<string>> ptr;
int cur;
shared_ptr<vector<string>> check(int size, const string msg) const;
public:
// 构造函数,指向空的ptr
StrBlob_ptr() : cur(0) {}
StrBlob_ptr(const StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
~StrBlob_ptr() {}
// * 解引用
const string &deref() const;
StrBlob_ptr &increase_ref();
// 同时需要定义!= 这里应该还要判断 p的指向是否相同
bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
};
shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
{
auto ptr_get = ptr.lock();
if (!ptr_get)
throw runtime_error(msg);
if (size >= ptr_get->size())
throw out_of_range(msg);
return ptr_get;
}
const string &StrBlob_ptr::deref() const
{
auto ptr_get = check(cur, "get shared_ptr");
return (*ptr_get)[cur];
}
StrBlob_ptr &StrBlob_ptr::increase_ref()
{
check(cur, "get shared_ptr");
cur++;
return *this;
}
/*
* 这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
*
*
*
*/
StrBlob_ptr StrBlob::begin() const
{
return StrBlob_ptr(*this);
}
StrBlob_ptr StrBlob::end() const
{
return StrBlob_ptr(*this, data->size());
}
/******************************************************************************************************************/
class ResultQuery
{
friend ostream &print(ostream &, const ResultQuery &);
public:
// 单词
string w;
// 行号的列表
shared_ptr<set<int>> lines;
// 全部的文本,可以通过行号寻找
StrBlob txtline; //----------modify
public:
ResultQuery(string word, shared_ptr<set<int>> line_num, StrBlob txt) : w(word), lines(line_num), txtline(txt){}; //----------modify
~ResultQuery(){};
};
class TextQuery
{
private:
/* data */
StrBlob txtline; //----------modify
// 因为在ret里面共享的是set的行号,所以这里也是行号共享指针,而不是整个map
map<string, shared_ptr<set<int>>> data;
public:
TextQuery(ifstream &file);
ResultQuery Query(string &w);
~TextQuery(){};
};
TextQuery::TextQuery(ifstream &file) : txtline() //----------modify
{
// 读入文件到文件流,保存每一行到vector<string>
string s;
int line_at = 0;
while (getline(file, s))
{
txtline.push_back(s); //----------modify
string ch;
istringstream ss(s);
while (ss >> ch)
{
if (!data[ch])
data[ch].reset(new set<int>);
data[ch]->insert(line_at);
}
line_at++;
}
}
ResultQuery TextQuery::Query(string &w)
{
static shared_ptr<std::set<int>> nodate(new std::set<int>);
auto found = data.find(w);
if (found == data.end())
return ResultQuery(w, nodate, txtline);
else
return ResultQuery(w, data[w], txtline);
}
//ostream &print(ostream &, const ResultQuery &)
ostream &print(ostream &out, const ResultQuery &want)
{
out << "----------------------------------------------" << endl;
out << "string:" << want.w << endl;
out << "Txt List:" << endl;
//if (want.lines) // 先要判断指针是否存在
{
for (auto ls : *(want.lines))
{
StrBlob_ptr xx(want.txtline, ls); //----------modify
out << ls << ":\t\t\t" << xx.deref() << endl; //----------modify
}
//qr.input->at(i)
}
out << "----------------------------------------------" << endl;
return out;
}
void runQueries(ifstream &file)
{
// 从文件流建立查询的数据
TextQuery tq(file);
while (true)
{
cout << "Enter what you want to find?" << endl;
string s;
if (!(cin >> s) || s == "q")
break;
print(cout, tq.Query(s)) << endl;
}
}
int main(int argc, char const *argv[])
{
ifstream fs("D:\\a.txt");
if (fs)
runQueries(fs);
else
cout << "fs open failed " << endl;
while (1)
;
return 0;
}
12.32.2
/*
12.32.2
完全使用 shared_ptr<StrBlob> 替换 shared_ptr<vector<string>>
12.32
重写TextQuery和QueryResult类,用StrBlob代替vector<vector>保存输入文件
TextQuery 使用StrBlob 存储shared_ptr<vector<string>> 文本
具体查询打印的时候,我们要从 *(StrBlob.ptr) 中取小标
也就是 使用 StrBlob_ptr 这个类指向了StrBlob中vector[下标]
github的答案是这里 使用 shared_ptr 执行StrBlob 也就是 shared_ptr<StrBlob> 的操作,
*/
/*
12.19
12.20 读入文件 使用这个类
12.22 使用 const StrBlob类
strBlob begin end 返回const
底层指针是个const,只有在构造的时候赋值
解引用的时候返回const
一个 StrBlob类,底层数据是指向 vector<string> 的指针
一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
定义 StrBlob类,数据成员是 vector<string> 的shared_ptr
begin 指向第一个元素的 StrBlob_ptr 也就是cur=0?
end 最后一个元素的指针cur=size() end是开区间,所以不用减1
定义 StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
一个指向 vector<string> 的指针,带有小标
* 获得string
++ 将下标++
*/
#include <vector>
#include <string>
#include <memory>
#include <initializer_list>
#include <exception>
#include <iostream>
#include <fstream>
#include <set>
#include <map>
#include <sstream>
using namespace std;
class StrBlob_ptr;
class StrBlob
{
using Blob_size_type = vector<string>::size_type;
friend class StrBlob_ptr;
private:
/* data */
shared_ptr<vector<string>> data;
public:
StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
StrBlob_ptr begin() const; //{ return StrBlob_ptr(*this); }
StrBlob_ptr end() const; //{ return StrBlob_ptr(*this, data->size()); }
Blob_size_type size() const
{
return data->size();
}
bool empty() const
{
return data->empty();
}
bool check(Blob_size_type has, const string &msg) const
{
if (has >= data->size())
throw std::out_of_range(msg);
}
void push_back(string &s)
{
data->push_back(s);
}
void pop_back()
{
check(0, "pop_back");
data->pop_back();
}
string &front()
{
check(0, "front");
return data->front();
}
string &back()
{
check(0, "back");
return data->back();
}
const string &front() const
{
check(0, "front");
return data->front();
}
const string &back() const
{
check(0, "back");
return data->back();
}
~StrBlob() {}
};
class StrBlob_ptr
{
private:
// 底层指针指向的内容是 shared_ptr,可能存在释放的情况
weak_ptr<vector<string>> ptr;
int cur;
shared_ptr<vector<string>> check(int size, const string msg) const;
public:
// 构造函数,指向空的ptr
StrBlob_ptr() : cur(0) {}
StrBlob_ptr(const StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
~StrBlob_ptr() {}
// * 解引用
const string &deref() const;
StrBlob_ptr &increase_ref();
// 同时需要定义!= 这里应该还要判断 p的指向是否相同
bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
};
shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
{
auto ptr_get = ptr.lock();
if (!ptr_get)
throw runtime_error(msg);
if (size >= ptr_get->size())
throw out_of_range(msg);
return ptr_get;
}
const string &StrBlob_ptr::deref() const
{
auto ptr_get = check(cur, "get shared_ptr");
return (*ptr_get)[cur];
}
StrBlob_ptr &StrBlob_ptr::increase_ref()
{
check(cur, "get shared_ptr");
cur++;
return *this;
}
/*
* 这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
*
*
*
*/
StrBlob_ptr StrBlob::begin() const
{
return StrBlob_ptr(*this);
}
StrBlob_ptr StrBlob::end() const
{
return StrBlob_ptr(*this, data->size());
}
/******************************************************************************************************************/
class ResultQuery
{
friend ostream &print(ostream &, const ResultQuery &);
public:
// 单词
string w;
// 行号的列表
shared_ptr<set<int>> lines;
// 全部的文本,可以通过行号寻找
shared_ptr<StrBlob> txtline; //----------modify
public:
ResultQuery(string word, shared_ptr<set<int>> line_num, shared_ptr<StrBlob> txt) : w(word), lines(line_num), txtline(txt){}; //----------modify
~ResultQuery(){};
};
class TextQuery
{
private:
/* data */
shared_ptr<StrBlob> txtline; //----------modify
// 因为在ret里面共享的是set的行号,所以这里也是行号共享指针,而不是整个map
map<string, shared_ptr<set<int>>> data;
public:
TextQuery(ifstream &file);
ResultQuery Query(string &w);
~TextQuery(){};
};
TextQuery::TextQuery(ifstream &file) : txtline(new StrBlob) //----------modify
{
// 读入文件到文件流,保存每一行到vector<string>
string s;
int line_at = 0;
while (getline(file, s))
{
txtline->push_back(s); //----------modify
string ch;
istringstream ss(s);
while (ss >> ch)
{
if (!data[ch])
data[ch].reset(new set<int>);
data[ch]->insert(line_at);
}
line_at++;
}
}
ResultQuery TextQuery::Query(string &w)
{
static shared_ptr<std::set<int>> nodate(new std::set<int>);
auto found = data.find(w);
if (found == data.end())
return ResultQuery(w, nodate, txtline);
else
return ResultQuery(w, data[w], txtline);
}
//ostream &print(ostream &, const ResultQuery &)
ostream &print(ostream &out, const ResultQuery &want)
{
out << "----------------------------------------------" << endl;
out << "string:" << want.w << endl;
out << "Txt List:" << endl;
//if (want.lines) // 先要判断指针是否存在
{
for (auto ls : *(want.lines))
{
StrBlob_ptr xx(*(want.txtline), ls); //----------modify
out << ls << ":\t\t\t" << xx.deref() << endl; //----------modify
}
//qr.input->at(i)
}
out << "----------------------------------------------" << endl;
return out;
}
void runQueries(ifstream &file)
{
// 从文件流建立查询的数据
TextQuery tq(file);
while (true)
{
cout << "Enter what you want to find?" << endl;
string s;
if (!(cin >> s) || s == "q")
break;
print(cout, tq.Query(s)) << endl;
}
}
int main(int argc, char const *argv[])
{
ifstream fs("D:\\a.txt");
if (fs)
runQueries(fs);
else
cout << "fs open failed " << endl;
while (1)
;
return 0;
}
12.33
/*
12.33 增加 QueryResult 的begin,end 取得set的begin,end 增加一个get_file 返回shared_ptr 指向QueryResult的文件也就是strBlob_ptr
12.32
重写TextQuery和QueryResult类,用StrBlob代替vector<vector>保存输入文件
TextQuery 使用StrBlob 存储shared_ptr<vector<string>> 文本
具体查询打印的时候,我们要从 *(StrBlob.ptr) 中取小标
也就是 使用 StrBlob_ptr 这个类指向了StrBlob中vector[下标]
github的答案是这里 使用 shared_ptr 执行StrBlob 也就是 shared_ptr<StrBlob> 的操作,
*/
/*
12.19
12.20 读入文件 使用这个类
12.22 使用 const StrBlob类
strBlob begin end 返回const
底层指针是个const,只有在构造的时候赋值
解引用的时候返回const
一个 StrBlob类,底层数据是指向 vector<string> 的指针
一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
定义 StrBlob类,数据成员是 vector<string> 的shared_ptr
begin 指向第一个元素的 StrBlob_ptr 也就是cur=0?
end 最后一个元素的指针cur=size() end是开区间,所以不用减1
定义 StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
一个指向 vector<string> 的指针,带有小标
* 获得string
++ 将下标++
*/
#include <vector>
#include <string>
#include <memory>
#include <initializer_list>
#include <exception>
#include <iostream>
#include <fstream>
#include <set>
#include <map>
#include <sstream>
using namespace std;
class StrBlob_ptr;
class StrBlob
{
using Blob_size_type = vector<string>::size_type;
friend class StrBlob_ptr;
private:
/* data */
shared_ptr<vector<string>> data;
public:
StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
StrBlob_ptr begin() const; //{ return StrBlob_ptr(*this); }
StrBlob_ptr end() const; //{ return StrBlob_ptr(*this, data->size()); }
Blob_size_type size() const
{
return data->size();
}
bool empty() const
{
return data->empty();
}
bool check(Blob_size_type has, const string &msg) const
{
if (has >= data->size())
throw std::out_of_range(msg);
}
void push_back(string &s)
{
data->push_back(s);
}
void pop_back()
{
check(0, "pop_back");
data->pop_back();
}
string &front()
{
check(0, "front");
return data->front();
}
string &back()
{
check(0, "back");
return data->back();
}
const string &front() const
{
check(0, "front");
return data->front();
}
const string &back() const
{
check(0, "back");
return data->back();
}
~StrBlob() {}
};
class StrBlob_ptr
{
private:
// 底层指针指向的内容是 shared_ptr,可能存在释放的情况
weak_ptr<vector<string>> ptr;
int cur;
shared_ptr<vector<string>> check(int size, const string msg) const;
public:
// 构造函数,指向空的ptr
StrBlob_ptr() : cur(0) {}
StrBlob_ptr(const StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
~StrBlob_ptr() {}
// * 解引用
const string &deref() const;
StrBlob_ptr &increase_ref();
// 同时需要定义!= 这里应该还要判断 p的指向是否相同
bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
};
shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
{
auto ptr_get = ptr.lock();
if (!ptr_get)
throw runtime_error(msg);
if (size >= ptr_get->size())
throw out_of_range(msg);
return ptr_get;
}
const string &StrBlob_ptr::deref() const
{
auto ptr_get = check(cur, "get shared_ptr");
return (*ptr_get)[cur];
}
StrBlob_ptr &StrBlob_ptr::increase_ref()
{
check(cur, "get shared_ptr");
cur++;
return *this;
}
/*
* 这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
*
*
*
*/
StrBlob_ptr StrBlob::begin() const
{
return StrBlob_ptr(*this);
}
StrBlob_ptr StrBlob::end() const
{
return StrBlob_ptr(*this, data->size());
}
/******************************************************************************************************************/
class ResultQuery
{
friend ostream &print(ostream &, const ResultQuery &);
public:
// 单词
string w;
// 行号的列表
shared_ptr<set<int>> lines;
// 全部的文本,可以通过行号寻找
StrBlob txtline; //----------modify
public:
ResultQuery(string word, shared_ptr<set<int>> line_num, StrBlob txt) : w(word), lines(line_num), txtline(txt){}; //----------modify
set<int>::iterator begin() const { return lines->begin(); } // 这里要使用const 因为下面的调用是使用 const ResultQuery&
set<int>::iterator end() const { return lines->end(); }
StrBlob get_file() { return txtline; }
~ResultQuery(){};
};
class TextQuery
{
private:
/* data */
StrBlob txtline; //----------modify
// 因为在ret里面共享的是set的行号,所以这里也是行号共享指针,而不是整个map
map<string, shared_ptr<set<int>>> data;
public:
TextQuery(ifstream &file);
ResultQuery Query(string &w);
~TextQuery(){};
};
TextQuery::TextQuery(ifstream &file) : txtline() //----------modify
{
// 读入文件到文件流,保存每一行到vector<string>
string s;
int line_at = 0;
while (getline(file, s))
{
txtline.push_back(s); //----------modify
string ch;
istringstream ss(s);
while (ss >> ch)
{
if (!data[ch])
data[ch].reset(new set<int>);
data[ch]->insert(line_at);
}
line_at++;
}
}
ResultQuery TextQuery::Query(string &w)
{
static shared_ptr<std::set<int>> nodate(new std::set<int>);
auto found = data.find(w);
if (found == data.end())
return ResultQuery(w, nodate, txtline);
else
return ResultQuery(w, data[w], txtline);
}
//ostream &print(ostream &, const ResultQuery &)
ostream &print(ostream &out, const ResultQuery &want)
{
out << "----------------------------------------------" << endl;
out << "string:" << want.w << endl;
out << "Txt List:" << endl;
for (auto it = want.begin(); it != want.end(); it++)
{
StrBlob_ptr xx(want.txtline, *it); //----------modify
out << *it << ":\t\t\t" << xx.deref() << endl; //----------modify
}
//for(auto it=want.begin();)
//if (want.lines) // 先要判断指针是否存在
{
// for (auto ls : *(want.lines))
// {
// StrBlob_ptr xx(want.txtline, ls); //----------modify
// out << ls << ":\t\t\t" << xx.deref() << endl; //----------modify
// }
//qr.input->at(i)
}
out << "----------------------------------------------" << endl;
return out;
}
void runQueries(ifstream &file)
{
// 从文件流建立查询的数据
TextQuery tq(file);
while (true)
{
cout << "Enter what you want to find?" << endl;
string s;
if (!(cin >> s) || s == "q")
break;
print(cout, tq.Query(s)) << endl;
}
}
int main(int argc, char const *argv[])
{
ifstream fs("D:\\a.txt");
if (fs)
runQueries(fs);
else
cout << "fs open failed " << endl;
while (1)
;
return 0;
}
12.33.2
/*
12.33.2
完全使用 shared_ptr<StrBlob> 替换 shared_ptr<vector<string>>
12.33 增加 QueryResult 的begin,end 取得set的begin,end 增加一个get_file 返回shared_ptr 指向QueryResult的文件也就是strBlob_ptr
12.32
重写TextQuery和QueryResult类,用StrBlob代替vector<vector>保存输入文件
TextQuery 使用StrBlob 存储shared_ptr<vector<string>> 文本
具体查询打印的时候,我们要从 *(StrBlob.ptr) 中取小标
也就是 使用 StrBlob_ptr 这个类指向了StrBlob中vector[下标]
github的答案是这里 使用 shared_ptr 执行StrBlob 也就是 shared_ptr<StrBlob> 的操作,
*/
/*
12.19
12.20 读入文件 使用这个类
12.22 使用 const StrBlob类
strBlob begin end 返回const
底层指针是个const,只有在构造的时候赋值
解引用的时候返回const
一个 StrBlob类,底层数据是指向 vector<string> 的指针
一个 StrBlob_ptr类,可以认为是StrBlob类的指针类
定义 StrBlob类,数据成员是 vector<string> 的shared_ptr
begin 指向第一个元素的 StrBlob_ptr 也就是cur=0?
end 最后一个元素的指针cur=size() end是开区间,所以不用减1
定义 StrBlob_ptr 类,指向 StrBlob类中的数据成员 *shared_ptr
一个指向 vector<string> 的指针,带有小标
* 获得string
++ 将下标++
*/
#include <vector>
#include <string>
#include <memory>
#include <initializer_list>
#include <exception>
#include <iostream>
#include <fstream>
#include <set>
#include <map>
#include <sstream>
using namespace std;
class StrBlob_ptr;
class StrBlob
{
using Blob_size_type = vector<string>::size_type;
friend class StrBlob_ptr;
private:
/* data */
shared_ptr<vector<string>> data;
public:
StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob(initializer_list<string> li) : data(make_shared<vector<string>>(li)) {}
StrBlob_ptr begin() const; //{ return StrBlob_ptr(*this); }
StrBlob_ptr end() const; //{ return StrBlob_ptr(*this, data->size()); }
Blob_size_type size() const
{
return data->size();
}
bool empty() const
{
return data->empty();
}
bool check(Blob_size_type has, const string &msg) const
{
if (has >= data->size())
throw std::out_of_range(msg);
}
void push_back(string &s)
{
data->push_back(s);
}
void pop_back()
{
check(0, "pop_back");
data->pop_back();
}
string &front()
{
check(0, "front");
return data->front();
}
string &back()
{
check(0, "back");
return data->back();
}
const string &front() const
{
check(0, "front");
return data->front();
}
const string &back() const
{
check(0, "back");
return data->back();
}
~StrBlob() {}
};
class StrBlob_ptr
{
private:
// 底层指针指向的内容是 shared_ptr,可能存在释放的情况
weak_ptr<vector<string>> ptr;
int cur;
shared_ptr<vector<string>> check(int size, const string msg) const;
public:
// 构造函数,指向空的ptr
StrBlob_ptr() : cur(0) {}
StrBlob_ptr(const StrBlob &s, int offset = 0) : ptr(s.data), cur(offset) {}
~StrBlob_ptr() {}
// * 解引用
const string &deref() const;
StrBlob_ptr &increase_ref();
// 同时需要定义!= 这里应该还要判断 p的指向是否相同
bool operator!=(const StrBlob_ptr &p) { return p.cur != cur; }
};
shared_ptr<vector<string>> StrBlob_ptr::check(int size, const string msg) const
{
auto ptr_get = ptr.lock();
if (!ptr_get)
throw runtime_error(msg);
if (size >= ptr_get->size())
throw out_of_range(msg);
return ptr_get;
}
const string &StrBlob_ptr::deref() const
{
auto ptr_get = check(cur, "get shared_ptr");
return (*ptr_get)[cur];
}
StrBlob_ptr &StrBlob_ptr::increase_ref()
{
check(cur, "get shared_ptr");
cur++;
return *this;
}
/*
* 这两个函数一定要放到 StrBlob_ptr 这个类下面定义,因为用到了StrBlob_ptr具体的构造函数; 即使最开始已经声明了
*
*
*
*/
StrBlob_ptr StrBlob::begin() const
{
return StrBlob_ptr(*this);
}
StrBlob_ptr StrBlob::end() const
{
return StrBlob_ptr(*this, data->size());
}
/******************************************************************************************************************/
class ResultQuery
{
friend ostream &print(ostream &, const ResultQuery &);
public:
// 单词
string w;
// 行号的列表
shared_ptr<set<int>> lines;
// 全部的文本,可以通过行号寻找
shared_ptr<StrBlob> txtline; //----------modify
public:
ResultQuery(string word, shared_ptr<set<int>> line_num, shared_ptr<StrBlob> txt) : w(word), lines(line_num), txtline(txt){}; //----------modify
set<int>::iterator begin() const { return lines->begin(); } // 这里要使用const 因为下面的调用是使用 const ResultQuery&
set<int>::iterator end() const { return lines->end(); }
shared_ptr<StrBlob> get_file() const { return txtline; } //modify
~ResultQuery(){};
};
class TextQuery
{
private:
/* data */
shared_ptr<StrBlob> txtline; //----------modify
// 因为在ret里面共享的是set的行号,所以这里也是行号共享指针,而不是整个map
map<string, shared_ptr<set<int>>> data;
public:
TextQuery(ifstream &file);
ResultQuery Query(string &w);
~TextQuery(){};
};
TextQuery::TextQuery(ifstream &file) : txtline(new StrBlob) //----------modify
{
// 读入文件到文件流,保存每一行到vector<string>
string s;
int line_at = 0;
while (getline(file, s))
{
txtline->push_back(s); //----------modify
string ch;
istringstream ss(s);
while (ss >> ch)
{
if (!data[ch])
data[ch].reset(new set<int>);
data[ch]->insert(line_at);
}
line_at++;
}
}
ResultQuery TextQuery::Query(string &w)
{
static shared_ptr<std::set<int>> nodate(new std::set<int>);
auto found = data.find(w);
if (found == data.end())
return ResultQuery(w, nodate, txtline);
else
return ResultQuery(w, data[w], txtline);
}
//ostream &print(ostream &, const ResultQuery &)
ostream &print(ostream &out, const ResultQuery &want)
{
out << "----------------------------------------------" << endl;
out << "string:" << want.w << endl;
out << "Txt List:" << endl;
for (auto it = want.begin(); it != want.end(); it++)
{
StrBlob_ptr xx(*(want.get_file()), *it);
//StrBlob_ptr xx(*(want.txtline), *it); //----------modify
out << *it << ":\t\t\t" << xx.deref() << endl; //----------modify
}
//for(auto it=want.begin();)
//if (want.lines) // 先要判断指针是否存在
{
// for (auto ls : *(want.lines))
// {
// StrBlob_ptr xx(want.txtline, ls); //----------modify
// out << ls << ":\t\t\t" << xx.deref() << endl; //----------modify
// }
//qr.input->at(i)
}
out << "----------------------------------------------" << endl;
return out;
}
void runQueries(ifstream &file)
{
// 从文件流建立查询的数据
TextQuery tq(file);
while (true)
{
cout << "Enter what you want to find?" << endl;
string s;
if (!(cin >> s) || s == "q")
break;
print(cout, tq.Query(s)) << endl;
}
}
int main(int argc, char const *argv[])
{
ifstream fs("D:\\a.txt");
if (fs)
runQueries(fs);
else
cout << "fs open failed " << endl;
while (1)
;
return 0;
}