我是编程新手,第一次写。注释很详细,都是自己的理解,错了也合理。。。呵呵
#include<iostream>#include<map>#include<vector>#include<string>#include<set>#include<sstream>using namespace std;// 类定义class TextQuery{public: typedef vector<string>::size_type line_no; void read_file() // 该函数每次从文件中读取一行,并将它保存在vector容器中。输入完毕后,将创建关联每个单词及其所在行的map容器 { store_file(); // 调用‘存储输入文件函数’ build_map(); // 调用‘建立单词map容器函数’ } set<line_no> run_query(const string &) const; // 定义‘查询单词函数’:返回的set对象包含形参string对象的所有行的行号 string text_line(line_no) const; // 返回输入文本中该行号对应的文本行private: void store_file(); // 将文件内容存储在vector容器中 void build_map(); // 将每行分解为各个单词,创建map容器对象,同时记录每个单词出现的行号 vector<string> lines_of_text; map<string,set<line_no>> word_map;};// 存储读入文件 store_filevoid TextQuery::store_file(){ string textline; while(getline(cin,textline)) // 我们希望每次存储文件的一行内容,所以使用getline读取输入,每读一行就添加到vector容器中 { lines_of_text.push_back(textline); if(textline == "q") break; }}// 建立单词map容器 build_mapvoid TextQuery::build_map() // 该函数用到8.5节描述的istringstream,及用map写的单词统计程序{ for(line_no line_num = 0;line_num != lines_of_text.size();++line_num) { istringstream line(lines_of_text[line_num]); // 将每行作为副本赋值给line (此处用到包含istringstream的头文件<sstream>) string word; while(line >> word) // while循环将对该行进行逐个单词处理(即将一行分解为各个单词) word_map[word].insert(line_num); // 用insert给该单词添加关联行号(该map容器的下标操作将返回set对象) }} // 支持查询 run_queryset<TextQuery::line_no> TextQuery::run_query(const string &query_word) const // 此函数实现单词查询{ map<string,set<line_no>>::const_iterator loc = word_map.find(query_word); // 查找文本中是否有该单词,有则返回指向它的指针 if(loc == word_map.end()) return set<line_no>(); // 返回一个空set对象 else return loc->second; // 返回该单词的set对象(即存储了该单词所关联的行数)}// 还回值的使用 text_linestring TextQuery::text_line(line_no line) const{ if(line < lines_of_text.size()) return lines_of_text[line]; // 返回该行号所对应的文本行 throw out_of_range("line number out of range");}// 函数 print_results 形参:被查询单词对应set对象的指针,被查询的单词,一个TextQuery类型对象的引用(即输入文本)void print_results(const set<TextQuery::line_no>& locs,const string &sought,const TextQuery &file){ typedef set<TextQuery::line_no> line_nums; line_nums::size_type size = locs.size(); // 对应单词所关联的行数(即出现次数) cout << "/n" << sought << " 出现 " << size << " 次:" << endl; // 输出:‘某单词’出现 N 次。(make_plural函数作用:若N大于1,则为times,否则为time) line_nums::const_iterator it = locs.begin(); // 指向该set对象的首元素指针 for( ; it != locs.end(); ++it) { cout << "/t(line " << (*it) + 1 << ") " << file.text_line(*it) << endl; // 输出:(line 数字) 该行文字内容。 }}// 主函数int main(){ cout << "请输入文本(按 q 键终止输入 ):" << endl; TextQuery tq; // 声明TextQuery对象 tq.read_file(); // 调用成员函数,读取文件 while(true) { cout << "请输入要查询的单词,或按 q 键退出程序: "; string s; cin >> s; if(!cin || s == "q") break; set<TextQuery::line_no> locs = tq.run_query(s); // 被查询单词所关联的行数 print_results(locs,s,tq); // 输出结果 } return 0;}// 其实还可以更加节简,请大家自己动手更改。
// 这是手动输入文本形式的。
