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; }
可以这样做,但是然并卵
在方法形参为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; }
#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.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; }
#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; }
#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; }
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
#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.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
#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; }
#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; }
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; }
#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; }
#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; }
#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; }
使用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