1 #include<iostream>
2 #include<
string>
3 #include<fstream>
4 #include<sstream>
5 #include<vector>
6 #include<map>
7 #include<
set>
8
9 using namespace::std;
10 /*要完成简单的单词查询任务,首先需要创建一个类TextQuery来帮我们完成这个任务,在这个类中private中
11 内部调用的对象和函数,在public中创建read_file将文件读入保存在vector中并关联每个单词和行号的map容器
12 通过run_query函数查找string并返回包含单词出现的每一个行号的set对象利用text_line输出每一行*/
13 class TextQuery{
14 public:
15 typedef vector<
string>
::size_type line_no;
16 void read_file(ifstream &
is)
//该函数每次从文件中读入一行,并将它保存在容器vector中
17 //,输入完毕后,将创建关联的每个单词和行号的map容器
18 {store_file(
is);build_map(); }
19 set<line_no> run_query(
const string&)
const;
//其形参为string类型的对象,返回一个set对象,该对象包含该string对象的所有行的行号
20 string text_line(line_no)
const;
//其形参是一个行号,返回输入文本中该行号对应的文本行
21
22
23 private:
24 void store_file(ifstream &
is);
25 void build_map();
26 vector<
string>
lines_of_text;
27 map<
string,
set<line_no> >
word_map;
28 };
29
30 /*将之前输入进来的infile.txt的每行内容读到一个vector<string>对象中,包括.*/
31 void TextQuery::store_file(ifstream &
is)
32 {
33 string textline;
34 while(getline(
is,textline))
35 lines_of_text.push_back(textline);
//store 由于是在public中因此可以访问private 的对象
36 //cout<<lines_of_text[0];
37
38 }
39 /*利用istringstream 将每一行中的文本忽略空格输入到一个map容器中,word_map[word]代表的是set<line_no>对象
40 然后调用set的insert函数在set对象中添加当前的行号。如果某一个单词在同一行中反复出现,则不做任何操作*/
41 void TextQuery::build_map()
42 {
43 for(line_no line_num=
0;line_num!=lines_of_text.size();++
line_num )
44 {
45 istringstream line(lines_of_text[line_num]);
46 string word;
47 while(line>>
word)
48 word_map[word].insert(line_num);
49
50 }
51 }
52 /*run_query函数带有const string 类型对象的引用参数,并以这个参数作为下标来访问word_map对象。
53 如果找到了就返回一个对应的set(其中包含所有出现的行号),否则就返回一个空的set*/
54 set<TextQuery::line_no> TextQuery::run_query(
const string &query_word)
const
55 {
56 map<
string,
set<line_no>>
::const_iterator
57 loc=
word_map.find(query_word);
58 if(loc==
word_map.end())
59 return set<line_no>
();
60 else
61 return loc->
second;
62
63 }
64 /*运行run_query后,将获得一组所查找的单词出现的行号。除了要输出该单词出现的次数之外,
65 还要输出该单词所在的每一行。就是通过之前的vector<string> 来输出*/
66 string TextQuery::text_line(line_no line)
const
67 {
68 if(line<
lines_of_text.size())
69 return lines_of_text[line];
70 throw out_of_range(
"line number out of range");
71 }
72 /*用来读取一个文件*/
73 ifstream &open_file(ifstream &
in,
const string &
file)
74 {
75 in.close();
//close in case it was already open
76 in.clear();
//clear any exiting errors;
77 in.open(file.c_str());
//open the file we were given
78 return in;
79 }
80 /*如果输出的次数大于1那么就输出复数*/
81 string make_plural(size_t ctr,
const string &word,
const string &
ending)
82 {
83 return (ctr==
1)?word:word+
ending;
84 }
85 /*首先输出出现的次数、调用了make_plural函数,之后输出每一个出现的行号,并且调用text_line来输出每一行*/
86 void print_result(
const set<TextQuery::line_no>&locs,
const string &sought,
const TextQuery &
file)
87 {
88 typedef
set<TextQuery::line_no>
line_nums;
89 line_nums::size_type size=
locs.size();
90 cout<<
"\n"<<sought<<
" occurs "<<size<<
" "
91 <<make_plural(size,
"time",
"s")<<
endl;
92 line_nums::const_iterator it=
locs.begin();
93 for(;it!=locs.end();++
it)
94 {
95 cout<<
"\t(line"
96 <<(*it)+
1<<
")"
97 <<file.text_line(*it)<<
endl;
98 }
99
100
101 }
102
103
104 /*创建一个TextQuery对象实现简单的用户查询会话。如果需要查询,那么就调用run_query函数,返回单词
105 出现的行的集合,并且调用print_result函数来输出函数*/
106 int main(
int argc,
char**
argv)
107 {
108 ifstream infile;
109 if(!open_file(infile,
"infile.txt"))
110 throw runtime_error(
"no remove file");
111 TextQuery tq;
112 tq.read_file(infile);
113 while(
true)
114 {
115 cout<<
"enter word to look for ,or q to quit: ";
116 string s;
117 cin>>
s;
118 if(!cin||s==
"q")
break;
119 set<TextQuery::line_no> locs=
tq.run_query(s);
120 print_result(locs,s,tq);
121
122 }
123 return 0;
124 }
infile.txt 中的内容
With some (indeed, many) C compilers,
you can get away with some what
's called a 'common
'
definition of a variable too.
some some some i
转载于:https://www.cnblogs.com/lovecodepql/p/8051589.html
相关资源:最权威的C 教程_C _Primer_Plus中文第五版 C _Primer中文第四版(都含源码 习题)(共4分卷)分卷1