StrBlob类封装shared_ptr的文本查询程序
核心: 类之间通过智能指针来共享数据
接口和实现分离,并且将shared_ptr<vector<string>>封装成StrBlob类
并且通过StrBlobPtr来作为StrBlob的接口
StrBlob以及StrBlobPtr实现
1 | |
将TextQuery和QueryResult从main.cpp中分离出来
my_TextQuery.h和my_QueryResult.h分别作为 类的声明.- 它们的定义一起实现在
my_TextQuery.cpp
my_QueryResult.h1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#ifndef MY_QUERYRESULT_H
#define MY_QUERYRESULT_H
#include <memory>
#include <string>
#include <vector>
#include <set>
#include <iostream>
#include "my_StrBlob.h"
class QueryResult {
friend std::ostream& print(std::ostream&,const QueryResult&);
public:
using line_no = std::vector<std::string>::size_type;
using line_it = std::set<line_no>::const_iterator;
QueryResult(std::string s,
std::shared_ptr<std::set<line_no>> p,
StrBlob f):
sought(s),lines(p),file(f) {}
std::set<line_no>::size_type size() const { return lines->size(); }
line_it begin() const { return lines->cbegin(); }
line_it end() const { return lines->cend(); }
StrBlob get_file() { return file; }
private:
std::string sought;
std::shared_ptr<std::set<line_no>> lines;
StrBlob file;
};
std::ostream& print(std::ostream&,const QueryResult&);
#endifmy_TextQuery.h1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#ifndef MY_TEXTQUERY_H
#define MY_TEXTQUERY_H
#include <memory>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <fstream>
#include "my_QueryResult.h"
class QueryResult;
class TextQuery {
public:
using line_no = std::vector<std::string>::size_type;
TextQuery(std::ifstream&);
QueryResult query(const std::string&) const;
void display_map();
private:
StrBlob file;
std::map<std::string,std::shared_ptr<std::set<line_no>>> wm;
static std::string cleanup_str(const std::string&);
};
#endifmy_TextQuery.cpp1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94#include "my_TextQuery.h"
#include <cstddef>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <iostream>
#include <fstream>
#include <cctype>
#include <cstring>
#include <utility>
using std::size_t;
using std::shared_ptr;
using std::istringstream;
using std::string;
using std::getline;
using std::vector;
using std::set;
using std::map;
using std::cerr;
using std::cout;
using std::cin;
using std::ostream;
using std::endl;
using std::ifstream;
using std::ispunct;
using std::tolower;
using std::strlen;
using std::pair;
TextQuery::TextQuery(ifstream& is):file(new vector<string>) {
string text;
while (getline(is,text)) {
file.push_back(text);
int n = file.size() - 1;
istringstream line(text);
string word;
while (line >> word) {
word = cleanup_str(word);
auto& lines = wm[word];
if (!lines)
lines.reset(new set<line_no>);
lines->insert(n);
}
}
}
string TextQuery::cleanup_str(const string& word) {
string ret;
for (auto it = word.begin(); it!=word.end(); ++it)
if (!ispunct(*it))
ret += tolower(*it);
return ret;
}
QueryResult TextQuery::query(const string& sought) const {
static shared_ptr<set<line_no>> nodata(new set<line_no>);
auto loc = wm.find(cleanup_str(sought));
if (loc == wm.end())
return QueryResult(sought,nodata,file);
else
return QueryResult(sought,loc->second,file);
}
ostream& print(ostream& os,const QueryResult& res) {
os << res.sought << " occurs " << res.lines->size() << " \n";
for (auto i : *res.lines)
os << " line " << i+1 << ": " << res.file.begin().deref(i) << " \n";
return os;
}
void TextQuery::display_map() {
auto iter = wm.cbegin();
auto iter_end = wm.cend();
for (; iter!=iter_end; ++iter) {
cout << " word: " << iter->first << " {";
auto& text_locs = iter->second;
auto loc_iter = text_locs->cbegin();
auto loc_iter_end = text_locs->cend();
while (loc_iter != loc_iter_end) {
cout << *loc_iter;
if (++loc_iter != loc_iter_end)
cout << ", ";
}
cout << "}\n";
}
cout << endl;
}
main.cpp1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35#include <iostream>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
#include <string>
using std::string;
#include <fstream>
using std::ifstream;
#include <cstdlib>
#include "my_TextQuery.h"
void runQueries(ifstream& infile) {
TextQuery temp(infile);
while (1) {
std::string s;
cout << "enter word to look for, or q to quit: ";
if(!(cin >> s) || s == "q") break;
print(cout,temp.query(s));
}
}
int main() {
ifstream infile("../other_code/1.in");
if (!infile)
std::cout << "fail to open the file\n";
runQueries(infile);
infile.close();
return 0;
}分析书中代码的设计思路:
TextQuery类- 处理文本数据 ,将
StrBlob类作为private成员来存储数据. query()成员函数返回处理的结果,将处理结果抽象成一个类QueryResultprint()接受 输出流 和QueryResult数据结果结合 输出QueryResult类
- 为
shared_ptr<vector<string>>封装了一系列vector<string>的操作. - 以及
StrBlobPtr作为StrBlob整个类的接口,通过StrBlobPtr StrBlob::begin()和StrBlobPtr StrBlobPtr::end()实现.StrBlobPtr类 weak_ptr<>不增加shared_ptr<>的引用计数,因此在此类的weak_ptr上定义了vector<string>的下标操作.
理解智能指针是一个类,实例化出来的对象有自己的成员函数.例如.use_count() .reset() .release()等,但是可以指针一样使用, 理解->与.的区别
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!