实现一个简单的文本查询程序,允许用户从该文件中查找单词,查询结果是该单词出现的次数,并列出每次出现所在的行。如果某单词在同一行中多次出现,程序将只显示该行一次,行号按升序显示。
text_query.h文件:
#if !defined __text__query__
#define __text__query__
#pragma warning(disable:4786)
#include <vector>
#include <set>
#include <map>
typedef std::vector<string>::size_type line_no;
class TextQuery {
public:
void read_file(ifstream &is){
store_file(is);
build_map();
}
std::set<line_no> run_query( const string & ) const;
std::string text_line(line_no _no) const;
private:
void store_file(std::ifstream&);
void build_map();
std::vector<std::string> lines_of_text;
std::map< std::string, std::set<line_no> > word_map;
};
#endif
TextQuery类的实现:
#pragma warning(disable:4786)
#include <string>
using namespace std;
#include <fstream>
#include <sstream>
#include "text_query.h"
std::set<line_no> TextQuery::run_query(const std::string& word) const
{
std::set<line_no> s;
size_t n = 0;
istringstream stream( word );
string _word;
while( stream >> _word ) {
++n;
}
if ( 1 < n ) {
return s;
}
map< std::string, set<line_no> >::const_iterator map_it = word_map.find( word );
if( map_it != word_map.end() ) {
return word_map.find( word )->second;
} else {
return s;
}
}
std::string TextQuery::text_line(line_no _no) const
{
string str;
if( _no > lines_of_text.size() ) {
return str;
}
return lines_of_text[ _no ];
}
void TextQuery::store_file(ifstream& file)
{
string line;
while( getline( file, line, '\n' ) ) {
lines_of_text.push_back( line );
}
}
void TextQuery::build_map()
{
std::string word;
std::string line;
for( size_t i = 0; i < lines_of_text.size(); ++i ) {
line = lines_of_text.at( i );
istringstream stream( line );
while( stream>>word ) {
//std::map<std::string, std::set<line_no> >::iterator map_it = word_map[word];
// if( word_map.count(word) ) {
word_map[word].insert( i );
}
}
}
主程序调用:
#include <iostream>
using namespace std;
#include "text_query.h"
#include <fstream>
int main()
{
TextQuery tq;
ifstream in( "test.txt" );
if( !in.is_open() ) {
cout<<" open file Error ! ";
system( "pause" );
return 0;
}
tq.read_file( in );
std::set<line_no> s = tq.run_query( "Humans" );
cout<<" element occurs "<<s.size()<<" times "<<endl;
for( set<line_no>::const_iterator temp= s.begin(); temp != s.end(); ++temp )
cout<<" ( line "<< *temp<<" )"<<endl;
return 0;
}
运行结果:
值得注意的是,我这里是文本文件,在windows下,行号是对应于记事本取消自动换行之后的行数。