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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
| #include<iostream> #include<memory> #include<set> #include<map> #include<string> #include<vector> #include<fstream> #include<sstream>
using namespace std; using line_no=vector<string>::size_type;
class QueryResult;
inline string make_plural(size_t ctr,const string &word, const string &endi); ostream& print(ostream&,const QueryResult&);
class TextQuery { public: TextQuery(ifstream&); QueryResult query(const string&) const; private: shared_ptr<vector<string>> file; map<string,shared_ptr<set<line_no>>> wm; };
class QueryResult { friend ostream& print(ostream&,const QueryResult&); public: QueryResult(string s,shared_ptr<set<line_no>> p, shared_ptr<vector<string>> f); private: string search; shared_ptr<set<line_no>> lines; shared_ptr<vector<string>> file; };
QueryResult::QueryResult(string s,shared_ptr<set<line_no>> p, shared_ptr<vector<string>> f) : search(s), lines(p), file(f) {}
TextQuery::TextQuery(ifstream &ifs) : file(new vector<string>) { string text; while(getline(ifs,text)) { file->push_back(text); int n=file->size(); istringstream line(text); string word; while(line>>word) { auto &lines=wm[word]; if(!lines) lines.reset(new set<line_no>); lines->insert(n-1); } } }
QueryResult TextQuery::query(const string &search) const { static shared_ptr<set<line_no>> nodata(new set<line_no>); auto loc=wm.find(search); if(loc==wm.end()) return QueryResult(search,nodata,file); else return QueryResult(search,loc->second,file); }
inline string make_plural(size_t ctr,const string &word, const string &endi) { return (ctr>1) ? word+endi : word; }
ostream& print(ostream &cout,const QueryResult &qr) { cout<<qr.search<<" occurs "<<qr.lines->size() <<" "<<make_plural(qr.lines->size(),"time","s") <<endl; for(auto num: *(qr.lines)) cout<<"\t(line "<<num+1<<") "<< *(qr.file->begin()+num)<<endl; return cout; }
void runQueries(ifstream &ifs) { TextQuery tq(ifs); while(true) { printf("enter word to look for, or q to quit\n"); string tmp; if(!(cin>>tmp)||tmp=="q") break; print(cout,tq.query(tmp))<<endl; } }
int main() { ifstream ifs; ifs.open("C:\\test\\tst.txt",ios::in); runQueries(ifs); return 0; }
|