c++ primer( 文本查询程序)
读取用户指定的任意文本文件,然后允许用户从该文件查找单词,查询的结果是该单词出现的次数,并列出每次出现所在的行,如果某单词在同一行中多次出现,程序将只显示改行的一次。行号按升序显示(int main()&&int main(int argc,char**argv)的区别算是了解了,但是跟int mian(int argc,char**argv){}中的文件操作还不熟悉,所以文件读取出现异常还不知道从哪里处理)【原来是中文字符不可以】
code:
1 //使用以vector容器存储行号的textQuery类 2 #include "TextQuery.h" 3 4 string make_plural(size_t,const string&,const string&); 5 ifstream &open_file(ifstream&,const string&); 6 void print_results(const vector<TextQuery::line_no>& locs, 7 const string& sought,const TextQuery &file) 8 { 9 //如果找到单词sought,则输出该单词出现的行数 10 typedef vector<TextQuery::line_no >line_nums; 11 line_nums::size_type size=locs.size(); 12 cout<<"\n"<<sought<<"occurs"<<size<<" " 13 <<make_plural (size,"time","s")<<endl; 14 15 //输出出现该单词的每一行 16 line_nums::const_iterator it=locs.begin(); 17 for(;it!=locs.end();++it){ 18 cout<<"\t(line "<<(*it)+1<<")"<<file.text_line (*it)<<endl; 19 } 20 } 21 22 //main函数接受文件名为参数 23 int main(int argc,char**argv) 24 { 25 //open the file from which user will query words 26 //char fileName[]="h:\\test.txt"; 27 ifstream infile; 28 if(argc<2||!open_file(infile,argv[1])){ 29 cerr<<"No input file"<<endl; 30 cout<<"to here1"; 31 system("pause"); 32 return EXIT_FAILURE; 33 } 34 35 TextQuery tq; 36 tq.read_file(infile); //建立容器map 37 38 //循环接受用户的查询要求并输出结果 39 while(true){ 40 cout<<"enter word to look for,or q to quit:"; 41 string s; 42 cin>>s; 43 44 //将s变为小写 45 string ret; 46 for(string::const_iterator it=s.begin();it!=s.end();++it){ 47 ret+=tolower(*it); 48 } 49 s=ret; 50 51 //如果用户输入文件结束符或字符‘q’及‘Q’,则结束循环 52 if(!cin||s=="q"||s=="Q") break; 53 54 //获取出现所查询单词所有行的行号 55 vector<TextQuery::line_no>locs=tq.run_query (s); 56 57 //输出出现次数及所有相关文本行 58 print_results(locs,s,tq); 59 60 } 61 system("pause"); 62 }
1 #include "TextQuery.h" 2 #include<sstream> 3 4 string TextQuery::text_line(line_no line)const 5 { 6 if(line<lines_of_text.size()) 7 return lines_of_text[line]; 8 throw out_of_range("line number out of range"); 9 } 10 11 //读输入文件,将每行存储为lines_of_text的一个元素 12 void TextQuery::store_file (ifstream &is) 13 { 14 string textline; 15 while(getline(is,textline)) 16 lines_of_text.push_back (textline); 17 } 18 19 //在输入vector中找以空白为间隔的单词 20 //将单词以及出现该单词的行的行号一起放入word_map 21 void TextQuery ::build_map () 22 { 23 //处理输入vector中的每一行 24 for(line_no line_num=0;line_num!=lines_of_text.size();++line_num) 25 { 26 //一次读一个单词 27 istringstream line(lines_of_text[line_num]); 28 string word; 29 while(line>>word){ 30 //去掉标点 31 word=cleanup_str(word); 32 //将行号加入到vector容器中 33 if(word_map.count(word)==0)//该单词不在map容器中 34 //下标操作将加入该单词 35 word_map[word].push_back (line_num); 36 else{ 37 if(line_num!=word_map[word].back()) 38 //行号与vector容器中最后一个元素不相等 39 word_map[word].push_back (line_num); 40 } 41 } 42 } 43 } 44 45 vector<TextQuery::line_no> 46 TextQuery::run_query(const string &query_word)const 47 { 48 //注意,为了避免在word_map中加入单词,使用find函数而不用下标操作 49 map<string,vector<line_no> >::const_iterator 50 loc=word_map.find(query_word); 51 if(loc==word_map.end()) 52 return vector<line_no>(); //找不到,返回空的vector对象 53 else 54 //获取并返回与该单词关联的行号vector对象 55 return loc->second ; 56 } 57 58 //去掉标点并将字母变成小写 59 string TextQuery::cleanup_str (const string &word) 60 { 61 string ret; 62 for(string::const_iterator it=word.begin();it!=word.end();++it){ 63 if(!ispunct(*it)) 64 ret+=tolower(*it); 65 } 66 return ret; 67 } 68 69 //定义函数make_plural 和open_file的源文件如下: 70 //function.cpp 71 //定义函数make_plural和open_file 72 73 #include<fstream> 74 #include<string> 75 76 using namespace std; 77 //如果ctr不为1,返回word的复数版本 78 string make_plural(size_t ctr,const string &word,const string &ending) 79 { 80 return (ctr==1)?word:word+ending; 81 } 82 83 //打开输入文件流in并绑定到给定的文件 84 ifstream &open_file(ifstream &in,const string&file) 85 { 86 in.close(); //close in case it was already open 87 in.clear(); //clear any existing errors 88 //if the open fails,the stream will be in an invalid state 89 in.open(file.c_str ()); 90 return in ; //condition state is good if open succeeded 91 }
1 #ifndef TEXTQUERY_H 2 #define TEXTQUERY_H 3 #include<string> 4 #include<vector> 5 #include<map> 6 #include<iostream> 7 #include<fstream> 8 #include<cstring> 9 #include<cctype> 10 11 using namespace std; 12 13 class TextQuery{ 14 public: 15 typedef string::size_type str_size; 16 typedef vector<string>::size_type line_no; 17 18 //接口: 19 //read_file建立给定文件的内部数据结构 20 void read_file(ifstream &is) 21 {store_file(is);build_map();} 22 23 //run_query查询给定单词并返回该单词所在行的行号集合 24 vector<line_no> run_query(const string&)const; 25 26 //text_line返回输入文件中指定行号对应的行 27 string text_line(line_no) const; 28 private: 29 //read_file所用到辅助函数 30 void store_file(ifstream&); //存储输入文件 31 void build_map(); //将每个单词与一个行号集合相关联 32 33 //保存输入文件 34 vector<string> lines_of_text; 35 36 //将单词与出现该单词的行的行号集合相关联 37 map<string,vector<line_no> >word_map; 38 39 //去掉标点并将字母变成小写 40 static std::string cleanup_str(const std::string&); 41 }; 42 #endif