C++ 第十章 TextQuery类 文本查询程序

来源:互联网 发布:手机空调遥控器软件 编辑:程序博客网 时间:2024/06/07 00:55
/*
 *目的:一个简单的文本查询程序
 *作用:程序将读取用户指定的任意文本文件,然后允许用户从该文件中查找单词。
 *查询的结果是该单词出现的次数,并列出每次出现所在的行。
 *如果某单词在同一行中多次出现,程序将只显示该行一次。
 *行号按升序显示,即第 7 行应该在第 9 行之前输出,依此类推。

 */


/*思路:
 *1.使用一个 vector<string> 类型的对象存储整个输入文件的副本。
 *   输入文件的每一行是该 vector 对象的一个元素。
 *   因而,在希望输出某一行时,只需以行号为下标获取该行所在的元素即可。
 *2.将每个单词所在的行号存储在一个 set 容器对象中。
 *   使用 set 就可确保每行只有一个条目,而且行号将自动按升序排列。
 *3.使用一个 map 容器将每个单词与一个 set 容器对象关联起来,
 *   该 set 容器对象记录此单词所在的行号。
 
*/


源代码::

#include<set>
#include<iostream>
#include<fstream>
#include<map>
#include<string>
#include<sstream>
#include<vector>
#include<exception>
#include<stdexcept>
using namespace std;


using namespace std;


class TextQuery
{
public:
// TextQuery(arguments);
// ~TextQuery();
typedef std::vector<string>::size_type line_no;
void read_file(ifstream &is)
{
store_file(is);
build_map();
}


set<line_no> run_query(const string&) const;
string text_line(line_no) const;


private:
void store_file(ifstream &);
void build_map();
vector<string> lines_of_text;
map<string, set<line_no> > word_map;
};


void TextQuery::store_file(ifstream &is)
{
string textline;
while(getline(is,textline))
{
lines_of_text.push_back(textline);
}
}


void TextQuery::build_map()
{
for(line_no line_num=0;line_num!=lines_of_text.size();line_num++)
{
istringstream line(lines_of_text[line_num]);
string word;
while (line>>word)
{
word_map[word].insert(line_num);
}
}
}




set<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 loc->second;//the set has sth 
}
else
{
return set<line_no>();//mpty set;
}
}






string TextQuery::text_line(line_no line) const
{
if(line < lines_of_text.size())
return lines_of_text[line];
throw out_of_range("The line_no out_of_range");
}




ifstream& open_file(ifstream &in,const string &file)
{
    in.close();
    in.clear();
    in.open(file.c_str());
    
    return in;
}


string make_plural(int size,const string &s1,const string &s2)
{
if (size==1)
{
return s1;
}
else
{
return s1+s2;
}
}
void print_result(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<<"occur"
<<size<<" "
<<make_plural(size,"time","s")<<endl;


line_nums::const_iterator it =locs.begin();
for(;it!=locs.end();++it)
{
cout<<"\t (line"<<(*it)+1<<")"
<<file.text_line(*it) <<endl;
}
}


int main(int argc, char const *argv[])
{
ifstream infile;
if (argc<2 || !open_file(infile,argv[1]))
{
cerr<<"No input file"<<endl;
return 0;
}


TextQuery tq;
tq.read_file(infile);


while(true)
{
cout<<"enter a word or 'q' to quit"<<endl;
string s;
cin>>s;
if (!cin || s == "q") break;

set<TextQuery::line_no> locs=tq.run_query(s);
print_result(locs,s,tq);
}


return 0;
}

0 0