1 #include<iostream> 2 #include<string> 3 #include<fstream> 4 #include<sstream> 5 #include<vector> 6 #include<map> 7 #include<set> 8 9 using namespace::std; 10 /*要完成简单的单词查询任务,首先需要创建一个类TextQuery来帮我们完成这个任务,在这个类中private中 11 内部调用的对象和函数,在public中创建read_file将文件读入保存在vector中并关联每个单词和行号的map容器 12 通过run_query函数查找string并返回包含单词出现的每一个行号的set对象利用text_line输出每一行*/ 13 class TextQuery{ 14 public: 15 typedef vector<string>::size_type line_no; 16 void read_file(ifstream &is) //该函数每次从文件中读入一行,并将它保存在容器vector中 17 //,输入完毕后,将创建关联的每个单词和行号的map容器 18 {store_file(is);build_map(); } 19 set<line_no> run_query(const string&) const; //其形参为string类型的对象,返回一个set对象,该对象包含该string对象的所有行的行号 20 string text_line(line_no) const;//其形参是一个行号,返回输入文本中该行号对应的文本行 21 22 23 private: 24 void store_file(ifstream &is); 25 void build_map(); 26 vector<string> lines_of_text; 27 map<string,set<line_no> > word_map; 28 }; 29 30 /*将之前输入进来的infile.txt的每行内容读到一个vector<string>对象中,包括.*/ 31 void TextQuery::store_file(ifstream &is) 32 { 33 string textline; 34 while(getline(is,textline)) 35 lines_of_text.push_back(textline); //store 由于是在public中因此可以访问private 的对象 36 //cout<<lines_of_text[0]; 37 38 } 39 /*利用istringstream 将每一行中的文本忽略空格输入到一个map容器中,word_map[word]代表的是set<line_no>对象 40 然后调用set的insert函数在set对象中添加当前的行号。如果某一个单词在同一行中反复出现,则不做任何操作*/ 41 void TextQuery::build_map() 42 { 43 for(line_no line_num=0;line_num!=lines_of_text.size();++line_num ) 44 { 45 istringstream line(lines_of_text[line_num]); 46 string word; 47 while(line>>word) 48 word_map[word].insert(line_num); 49 50 } 51 } 52 /*run_query函数带有const string 类型对象的引用参数,并以这个参数作为下标来访问word_map对象。 53 如果找到了就返回一个对应的set(其中包含所有出现的行号),否则就返回一个空的set*/ 54 set<TextQuery::line_no> TextQuery::run_query(const string &query_word) const 55 { 56 map<string,set<line_no>>::const_iterator 57 loc=word_map.find(query_word); 58 if(loc==word_map.end()) 59 return set<line_no>(); 60 else 61 return loc->second; 62 63 } 64 /*运行run_query后,将获得一组所查找的单词出现的行号。除了要输出该单词出现的次数之外, 65 还要输出该单词所在的每一行。就是通过之前的vector<string> 来输出*/ 66 string TextQuery::text_line(line_no line) const 67 { 68 if(line<lines_of_text.size()) 69 return lines_of_text[line]; 70 throw out_of_range("line number out of range"); 71 } 72 /*用来读取一个文件*/ 73 ifstream &open_file(ifstream &in,const string &file) 74 { 75 in.close();//close in case it was already open 76 in.clear();//clear any exiting errors; 77 in.open(file.c_str());//open the file we were given 78 return in; 79 } 80 /*如果输出的次数大于1那么就输出复数*/ 81 string make_plural(size_t ctr,const string &word,const string &ending) 82 { 83 return (ctr==1)?word:word+ending; 84 } 85 /*首先输出出现的次数、调用了make_plural函数,之后输出每一个出现的行号,并且调用text_line来输出每一行*/ 86 void print_result(const set<TextQuery::line_no>&locs,const string &sought,const TextQuery &file) 87 { 88 typedef set<TextQuery::line_no> line_nums; 89 line_nums::size_type size=locs.size(); 90 cout<<"\n"<<sought<<" occurs "<<size<<" " 91 <<make_plural(size,"time","s")<<endl; 92 line_nums::const_iterator it=locs.begin(); 93 for(;it!=locs.end();++it) 94 { 95 cout<<"\t(line" 96 <<(*it)+1<<")" 97 <<file.text_line(*it)<<endl; 98 } 99 100 101 } 102 103 104 /*创建一个TextQuery对象实现简单的用户查询会话。如果需要查询,那么就调用run_query函数,返回单词 105 出现的行的集合,并且调用print_result函数来输出函数*/ 106 int main(int argc,char**argv) 107 { 108 ifstream infile; 109 if(!open_file(infile,"infile.txt")) 110 throw runtime_error("no remove file"); 111 TextQuery tq; 112 tq.read_file(infile); 113 while(true) 114 { 115 cout<<"enter word to look for ,or q to quit: "; 116 string s; 117 cin>>s; 118 if(!cin||s=="q") break; 119 set<TextQuery::line_no> locs=tq.run_query(s); 120 print_result(locs,s,tq); 121 122 } 123 return 0; 124 }
infile.txt 中的内容 With some (indeed, many) C compilers, you can get away with some what‘s called a ‘common‘ definition of a variable too. some some some i