-
Notifications
You must be signed in to change notification settings - Fork 33
/
TextQuery.h
82 lines (76 loc) · 2.05 KB
/
TextQuery.h
1
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
#ifndef TEXT_QUERY_H
#define TEXT_QUERY_H
#include <fstream>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <vector>
class QueryResult;
class TextQuery {
public:
using line_no = std::vector<std::string>::size_type;
TextQuery(std::ifstream &);
QueryResult query (const std::string &) const;
private:
std::shared_ptr<std::vector<std::string>> text;
std::map<std::string, std::shared_ptr<std::set<line_no>>> words_map;
};
class QueryResult {
friend std::ostream& print(std::ostream &, const QueryResult &);
public:
QueryResult(std::shared_ptr<std::vector<std::string>> p,
std::shared_ptr<std::set<TextQuery::line_no>> ln,
std::string w, unsigned n) :
text(p), lines(ln), sought(w), count(n) {}
private:
std::shared_ptr<std::vector<std::string>> text;
std::shared_ptr<std::set<TextQuery::line_no>> lines;
std::string sought;
unsigned count = 0;
};
// constructors
TextQuery::TextQuery(std::ifstream &infile) :
text(std::make_shared<std::vector<std::string>>())
{
std::string line, word;
for (size_t lineNumber = 1; getline(infile, line); ++lineNumber) {
text->push_back(line);
std::istringstream iss(line);
while (iss >> word) {
auto &lines = words_map[word];
if (!lines)
lines = std::make_shared<std::set<line_no>>();
lines->insert(lineNumber);
}
}
}
// members
QueryResult
TextQuery::query(const std::string &s) const
{
static auto notFound = std::make_shared<std::set<line_no>>();
auto pos = words_map.find(s);
if (pos == words_map.end())
return {text, notFound, s, 0};
unsigned count = 0;
std::string word;
for (auto const &line : *text) {
std::istringstream iss(line);
while (iss >> word)
if (word == s)
++count;
}
return {text, pos->second, s, count};
}
// non-members
std::ostream&
print(std::ostream &os, const QueryResult &result)
{
os << result.sought << " occurs " << result.count
<< ((result.count > 1) ? " times" : " time") << std::endl;
for (auto const &n : *result.lines)
os << "\t(line " << n << ") " << result.text->at(n - 1) << '\n';
return os;
}
#endif