12.32 重写TextQuery和QueryResult类,用StrBlob代替vector<string>保存输入文件。
TextQuery.h
#ifndef TEXTQUERY_H #define TEXTQUERY_H #include<iostream> #include<string> #include<fstream> #include<vector> #include<memory> #include<map> #include<set> #include<new> #include"StrBlob.h" using namespace std; class QueryResult; class TextQuery { public: using line_no=vector<string>::size_type; TextQuery(StrBlob&); QueryResult query(const string&) const; private: shared_ptr<vector<string>> file; map<string,shared_ptr<set<line_no>>> wm; }; #endif // TEXTQUERY_H
TextQuery.cpp
#include"TextQuery.h" #include"QueryResult.h" #include<sstream> TextQuery::TextQuery(StrBlob& is):file(is.data) { string text; auto vec=(is.data)->begin(); int n=0; while(vec!=(is.data)->end()) { text=*vec++; //file->push_back(text); string word; istringstream line(text); while(line>>word) { auto &lines=wm[word]; if(!lines) lines.reset(new set<line_no>); lines->insert(n); } ++n; } } QueryResult TextQuery::query(const string& sought) const { static shared_ptr<set<line_no>> nodata(new set<line_no>); auto loc=wm.find(sought); if(loc!=wm.end()) return QueryResult(sought,loc->second,file); else return QueryResult(sought,nodata,file); }
QueryResult.h
#ifndef QUERYRESULT_H #define QUERYRESULT_H #include <iostream> #include<memory> #include<vector> #include<string> #include<set> #include"TextQuery.h" using namespace std; class QueryResult { friend ostream& print(ostream& ,const QueryResult&); public: QueryResult(string s,shared_ptr<set<TextQuery::line_no>> p,shared_ptr<vector<string>> f):sought(s),lines(p),file(f){} private: string sought; shared_ptr<set<TextQuery::line_no>> lines; shared_ptr<vector<string>> file; }; ostream& print(ostream& ,const QueryResult&); #endif
QueryResult.cpp
#include"QueryResult.h" ostream &print(ostream &os,const QueryResult &qr) { os<<qr.sought<<" occurs "<<qr.lines->size()<<" times "<<endl; for(auto num:*qr.lines) os<<"\t(line "<<num+1<<" ) " <<(*qr.file)[num]<<endl; return os; }
StrBlob.h
#ifndef STRBLOB_H #define STRBLOB_H #include<iostream> #include<string> #include<vector> #include<memory> using namespace std; class StrBlobPtr; class StrBlob { friend class StrBlobPtr; friend class TextQuery; public: typedef string::size_type size_type; //构造函数 StrBlob(); explicit StrBlob(initializer_list<string> il); size_type size() const { return data->size(); } bool empty() const { return data->empty();} void push_back(const string &t) { data->push_back(t);} void pop_back(); string& front(); string& back(); string& front() const; string& back() const; size_type count() { return data.use_count(); } StrBlobPtr begin(); StrBlobPtr end(); private: shared_ptr<vector<string>> data; void check(size_type i,const string msg) const; }; #endif // STRBLOB_H
StrBlob.cpp
#include"StrBlob.h" #include"StrBlobPtr.h" StrBlob::StrBlob():data(new vector<string>) { } StrBlob::StrBlob(initializer_list<string> il):data(make_shared<vector<string>>(il)) { } void StrBlob::pop_back() { check(0,"pop_back"); data->pop_back(); } string& StrBlob::back() { check(0,"back"); return data->back(); } string& StrBlob::front() { check(0,"front"); return data->front(); } string& StrBlob::back() const { check(0,"back"); return data->back(); } string& StrBlob::front() const { check(0,"front"); return data->front(); } void StrBlob::check(size_type i, const string msg) const { if(i>=data->size()) throw out_of_range(msg); } StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); } StrBlobPtr StrBlob::end() { return StrBlobPtr(*this,data->size()); }
StrBlobPtr.h
#ifndef STRBLOBPTR_H #define STRBLOBPTR_H #include<string> #include<vector> #include<memory> using namespace std; class StrBlobPtr { public: StrBlobPtr():curr(0) {} StrBlobPtr(const StrBlob &a,size_t sz=0):wptr(a.data),curr(sz) {} string& deref() const; StrBlobPtr& incr(); private: shared_ptr<vector<string>> check(size_t,const string &) const; weak_ptr<vector<string>> wptr; size_t curr; }; #endif
StrBlobPtr.cpp
#include"StrBlob.h" #include"StrBlobPtr.h" shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string& msg) const { shared_ptr<vector<string>> 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 ret=check(curr,"deference"); return (*ret)[curr]; } StrBlobPtr& StrBlobPtr::incr() { check(curr,"increment"); ++curr; return *this; }
main.cpp
#include "TextQuery.h" #include "QueryResult.h" #include"StrBlob.h" void runQueries(StrBlob &Str) { // infile is an ifstream that is the file we want to query TextQuery tq(Str); // store the file and build the query map // iterate with the user: prompt for a word to find and print results while (true) { cout << "enter word to look for, or q to quit: "; string s; // stop if we hit end-of-file on the input or if a 'q' is entered if (!(cin >> s) || s == "q") break; // run the query and print the results print(cout, tq.query(s)) << endl; } } // program takes single argument specifying the file to query int main(int argc, char **argv) { // open the file from which user will query words ifstream infile("1.txt"); // open returns void, so we use the comma operator XREF(commaOp) // to check the state of infile after the open StrBlob Str; string tmp; while(getline(infile,tmp)) { Str.push_back(tmp); } runQueries(Str); return 0; }
1.txt
Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he tells her, magical but untamed. "Daddy, shush, there is no such thing," she tells him, at the same time wanting him to tell her more. Shyly, she asks, "I mean, Daddy, is there?" Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he tells her, magical but untamed. "Daddy, shush, there is no such thing," she tells him, at the same time wanting him to tell her more. Shyly, she asks, "I mean, Daddy, is there?" Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he tells her, magical but untamed. "Daddy, shush, there is no such thing," she tells him, at the same time wanting him to tell her more. Shyly, she asks, "I mean, Daddy, is there?"