#ifndef _TEXTQUERY_H_
#define _TEXTQUERY_H_
#include <vector>
#include <fstream>
#include <iostream>
#include <string>
#include <set>
#include <map>
class TextQuery{
public:
typedef std::vector<std::string>::size_type line_no;
void read_file(std::ifstream &is)
{
store_file(is);
build_map();
}
std::set<line_no> run_query(const std::string&) const;
std::string text_line(line_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.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include "textquery.h"
#include <iostream>
#include <sstream>
#include <utility>
using std::string;
using std::vector;
using std::set;
using std::map;
using std::istringstream;
std::set<TextQuery::line_no> TextQuery::run_query(const std::string &word) const
{
map< string, set<line_no> >::const_iterator iter = word_map.find(word);
if (iter != word_map.end())
{
return iter->second;
}
else
{
set<line_no> temp;
return temp;
//return set<line_no>();//书上使用这种方法,简明了许多
}
}
std::string TextQuery::text_line(line_no linenumber) const
{
return lines_of_text[linenumber];
}
void TextQuery::store_file(std::ifstream &is)
{
string line;
while (getline(is, line))
{
lines_of_text.push_back(line);
}
}
void TextQuery::build_map()
{
string word;
map< string, set<line_no> >::iterator iter;
for (line_no ix = 0; ix != lines_of_text.size(); ++ix)
{
istringstream stream(lines_of_text[ix]);
//istringstream stream;
//stream.str(lines_of_text[ix]);//有两种将string转换为istringstream的方法
while (stream >> word)
{
//word_map[word].insert(ix);//书上用了这种写法,只需一句简单明了多了
iter = word_map.find(word);
if (iter != word_map.end())
{
iter->second.insert(ix);
}
else
{
set<line_no> lineset;
lineset.insert(ix);
word_map.insert(make_pair(word, lineset));
}
}
}
}
//test.cpp
#include"stdafx.h"
#include "textquery.h"
#include <iostream>
#include <string>
#include <set>
#include <fstream>
#include <utility>
using std::ifstream;
using std::cerr;
using std::cout;
using std::cin;
using std::string;
using std::endl;
using std::set;
using std::runtime_error;
ifstream& open_file(ifstream& in, const string& file)
{
in.close();
in.clear();
in.open(file.c_str());
return in;
}
void print_results(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 << " occurs "
<< size << " "
<< "times" << endl;
line_nums::const_iterator iter = locs.begin();
for ( ; iter != locs.end(); ++iter)
{
cout << "\t(line "
<< (*iter) + 1 << ") "
<< file.text_line(*iter) << endl;
}
}
int main(int argc, char **argv)
{
/*下面两种文件的读取方式均可。运行程序有两种方法
方法一:利用cmd命令到命令行窗口,进入到可执行文件所在的目录
输入xxx.exe yyy.txt
方法二:利用vs2008属性-调试-命令参数中填写yyy.txt
然后在工作目录中填写可执行程序所在目录,将yyy.txt也放入此目录中
要注意的是对于win7系统,文件名后缀是不显示的,所以在命名文件时
不需要写yyy.txt,这样会出现文件全名变成yyy.txt.txt的情况*/
#if 0
ifstream infile;
if (argc < 2 || !open_file(infile, argv[1]))
{
cerr << "No input file!" << endl;
//return EXIT_FAILURE;
}
//open_file(infile, argv[1]);
#endif
#if 1
if (argc != 2)
{
throw runtime_error("wrong number of arguments");
}
ifstream infile;
if (!open_file(infile, argv[1]))
{
throw runtime_error("no input file");
}
#endif
TextQuery tq;
tq.read_file(infile);
while (true)
{
cout << "enter word to look for, or q to quit: ";
string s;
cin >> s;
if (!cin || s == "q")
{
break;
}
set<TextQuery::line_no> locs = tq.run_query(s);
print_results(locs, s, tq);
}
return 0;
}