【足迹C++primer】41、文本查询程序
/** * 功能:使用标准库:文本查询程序 * 时间:2014年7月10日09:10:15 * 作者:cutter_point */ #include<iostream> #include<map> #include<set> #include<fstream> #include<sstream> #include<string> #include<vector> #include<memory> using namespace std; using line_no=vector<string>::size_type; /************************************** 定义TextQuery类 **************************************/ class QueryResult; //为了定义函数query的返回类型,前向申明 class TextQuery { public: TextQuery(ifstream&); QueryResult query(const string&) const; private: shared_ptr<vector<string>> file; //输入文件 //每个单词到它所在的行数的集合映射 map<string, shared_ptr<set<line_no>>> wm; }; /* 读取输入文件并建立单词到行号的映射 */ 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); //将文本分解为单词,istringstream是以空格为结束 string word; while(line>>word) //对应每行的每个单词 { //如果单词不再wm中,就以它为下标在wm中添加一项 auto &lines=wm[word]; //lines是一个shared_ptr,有了key值,但是没有value if(!lines) //当我们第一次遇到这个单词的时候,此指针为空 { lines.reset(new set<line_no>); //吧a指向的内置指针b,否则置空,a.reset(b) } lines->insert(n); //将此行插入set中 } } } /************************************** QueryResult类 **************************************/ class QueryResult { friend ostream& print(ostream&, const QueryResult&); public: QueryResult(string s, shared_ptr<set<line_no>> p, shared_ptr<vector<string>> f):sought(s),lines(p),file(f){} private: string sought; //查询单词 shared_ptr<set<line_no>> lines; //出现的行号 shared_ptr<vector<string>> file; //输入文件 }; //make_plural判断是否有元素的函数 inline string make_plural(size_t ctr, const string &word, const string &ending) { return (ctr>1) ? word+ending : ending; } /* 友元函数实现 */ ostream& print(ostream & os, const QueryResult & qr) { //如果找到了单词,打印出现的次数,和出现的位置 //如果找到了单词,打印出现的次数 os<<qr.sought<<" occurs "<<qr.lines->size()<<" "<<make_plural(qr.lines->size(), "time", "s")<<endl; //打印单词出现的每一行 for(auto num : *qr.lines) //对set中每个单词 { //避免重0行开始给用户带来困惑 os<<"\t(line "<<num<<")"<<*(qr.file->begin()+num-1)<<endl; } return os; } /* 用QueryResult中的数据定义TextQuery中的函数 */ QueryResult TextQuery::query(const string &sought) const { //如果未找到sought,我们将返回一个指向此set的指针 static shared_ptr<set<line_no>> nodata(new set<line_no>); //使用find而不是下标运算来查找单词,避免将单词添加进去了 auto loc=wm.find(sought); if(loc == wm.end()) return QueryResult(sought, nodata, file); //未找到 else return QueryResult(sought, loc->second, file); } /************************************** 使用TextQuery类 **************************************/ void runQueries(ifstream &infile) { //infile是一个ifstream,指向我们要处理的文件 TextQuery tq(infile); //保存文件并建立查询map //与用户交互:提示用户输入要查询的单词,完成查询并打印结果 while(true) { cout<<"enter word to look for , or q to quit: "; string s; //若遇到文件结尾或输入'q'时结束循环 if(!(cin>>s) || s == "q") break; //指向查询并打印结果 print(cout, tq.query(s))<<endl; } } int main() { ifstream infile("test.txt"); runQueries(infile); return 0; }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。