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