*目的:一个简单的文本查询程序
*作用:程序将读取用户指定的任意文本文件,然后允许用户从该文件中查找单词。
*查询的结果是该单词出现的次数,并列出每次出现所在的行。
*如果某单词在同一行中多次出现,程序将只显示该行一次。
*行号按升序显示,即第 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;
}