頭文件StrBlob以及StrBlobPtr
//根據題目要求用自己定義的StrBlob來代替vector<string>來保存輸入文件
//可以更加安全的共享底層數據
#include<iostream>
#include<vector>
#include<string>
#include<memory>
#include<fstream>
using namespace std;
class StrBlob { //自定義管理動態vector<string>的類,可以讓其對象共享同一個data
friend class StrBlobPtr;
public:
typedef vector<string>::size_type size_type;
StrBlob() : data(make_shared<vector<string>>()) {}
StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {}
~StrBlob() { cout << " ~ Blob success " << endl; }
size_type size() const { return data->size(); }
bool empty()const { return data->empty(); }
void push_back(const string &st) const { data->push_back(st); }
void pop_back() const;
string &front() const;
string &back() const;
StrBlobPtr begin();
StrBlobPtr end();
private:
shared_ptr<vector<string>> data;
void check(size_type t, const string &msg) const;
};
//檢查一個給定的索引值是否在合法範圍內
void StrBlob::check(size_type t, const string &msg) const {
if (t >= data->size())
throw out_of_range(msg);
}
void StrBlob::pop_back() const {
check(0, "pop back on empty StrBlob");
data->pop_back();
}
string & StrBlob::front() const {
check(0, "pop back on empty StrBlob");
return data->front();
}
string & StrBlob::back() const {
check(0, "pop back on empty StrBlob");
return data->back();
}
class StrBlobPtr { //爲StrBlob提供保護,指向Blob的data防止我們訪問其可能產生的空懸指針
public:
//默認情況下StrBlobPtr指向data的第一個下標
StrBlobPtr() :curr(0) { }
StrBlobPtr(StrBlob &a, size_t sz = 0) :wptr(a.data), curr(sz) { }
~StrBlobPtr(){ cout << " ~ BlobPtr success " << endl; }
string &deref() const; //用來解引用
StrBlobPtr& incr();//用來遞增
bool operator != (const StrBlobPtr &x) { return this->curr != x.curr; }
private:
size_t curr;
//check要檢查指針指向的vector是否還存在
shared_ptr<vector<string>> check(size_t, const string&) const;
weak_ptr<vector<string>> wptr;
};
shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const {
auto ret = wptr.lock();
if (!ret) {
throw runtime_error("unbound StrBlobPtr");
}
if (i >= ret->size()) {
throw out_of_range(msg);
}
return ret;
}
string & StrBlobPtr::deref() const {
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
StrBlobPtr& StrBlobPtr::incr() {
auto p = check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
StrBlobPtr StrBlob::begin() {
return StrBlobPtr(*this);
}
StrBlobPtr StrBlob::end() {
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
頭文件TextQuery以及QueryResult
#include<iostream>
#include<vector>
#include<new>
#include<set>
#include<map>
#include<fstream>
#include<algorithm>
#include<memory>
#include<sstream>
#include<string>
#include<iterator>
#include<iterator>
#include"Blob.h"
using namespace std;
class QueryResult;
class TextQuery { //保存輸入文件
public:
using LineNo = vector<string>::size_type;
TextQuery();
TextQuery(ifstream &infile);
~TextQuery(){ cout << " ~ TextQuery success " << endl; }
QueryResult query(const string &s) const;//返回一個查詢結果
private:
map<string, shared_ptr<set<LineNo>>> result; //通過字符串來查找對應的行號
//shared_ptr<vector<string>> data;
StrBlob data;//按行保存輸入的文件
};
class QueryResult { //保存查詢結果
friend ostream& print(ostream &os, QueryResult &qr);
public:
QueryResult(const string &s, StrBlob vec, shared_ptr<set<TextQuery::LineNo>> n) :
word(s),data(vec),nos(n){
}
~QueryResult(){ cout << " ~ QueryResult success " << endl; }
//以下三個是根據12.33題目要求擴展,暫時未用到
set<TextQuery::LineNo>::iterator begin() const { return nos->begin(); }
set<TextQuery::LineNo>::iterator end() const { return nos->end(); }
StrBlob get_file() const { return data; }
private:
string word;
//shared_ptr<vector<string>> data;
StrBlob data; //與TextQuery共享data數據
shared_ptr<set<TextQuery::LineNo>> nos;//保存與給定單詞關聯的行號
};
TextQuery::TextQuery(ifstream &infile) : data(){
LineNo lineNo = 0;
for (string line; getline(infile, line); ++lineNo) {
data.push_back(line);
istringstream line_stream(line);
for (string lineword; line_stream >> lineword; ) {
auto &nos = result[lineword];
if (!nos) //當行號第一次出現時此指針爲空
nos.reset(new set<LineNo>);//分配一個新的set
nos->insert(lineNo);
}
}
/*string text;
while (getline(infile, text)) {
data->push_back(text);
int n = data->size() - 1;
istringstream line(text);
string word;
while (line >> word) {
auto &lines = result[word];
if (!lines)
lines.reset(new set<LineNo>);
lines->insert(n);
}
}*/
}
QueryResult TextQuery::query(const string& s) const {
shared_ptr<set<TextQuery::LineNo>> nodata(make_shared<set<LineNo>>());
auto found = result.find(s);
if (found != result.end())
return QueryResult(s, data, found->second);
else
return QueryResult(s, data, nodata);
}
ostream& print(ostream &out, QueryResult &qr) {
out << qr.word << " occurs " << qr.nos->size() << (qr.nos->size() > 1 ? "time" : "times") << endl;
for (auto i : *qr.nos) {
StrBlobPtr p(qr.data, i);
out << "( line " << i + 1 << ")" << p.deref() << endl;
}
return out;
}
主函數
#include<iostream>
#include<vector>
#include<new>
#include<set>
#include<algorithm>
#include<memory>
#include<sstream>
#include<string>
#include"ClassTQ.h"
using namespace std;
void runQueries(ifstream &infile) {
TextQuery tq(infile);
string s;
while (cin >> s && s != "q") {
cout << "請輸入要查詢的字符串或者輸入q來退出查詢:" << endl;
print(cout, tq.query(s));
}
}
int main() {
ifstream txt1;
txt1.open("1.txt", ios::in);
cout << "open 1.txt success" << endl;
runQueries(txt1);
txt1.close();
return 0;
}