概述
练习
12.27
这个程序已经可以完成论文所作的功能了
class QueryResult {
//懒得重复写,所以使用类型别名
using str_vec_ptr = std::shared_ptr<vector<string>>;
using str_set_map_ptr = std::shared_ptr<map<string, set<size_t>>>;
using str_map_ptr = std::shared_ptr<map<string, size_t>>;
friend ostream& print(ostream& out, const QueryResult& result);
public:
QueryResult(string word,str_vec_ptr p1,str_set_map_ptr p2,str_map_ptr p3):query_word(word),text_content(p1),word_to_line_set_map(p2),word_count_map(p3) {
}
private:
//不使用类内初始化,使用TextQuery传入的参数进行初始化
str_vec_ptr text_content;
str_set_map_ptr word_to_line_set_map;
str_map_ptr word_count_map;
string query_word;
};
class TextQuery {
public:
//默认有50行
TextQuery(ifstream& ifile) {
string word;
while (std::getline(ifile, word)) {
text_content->push_back(word);
}
};
QueryResult query(const string&);
private:
//因为需要共享数据,所以这些数据成员全部写成智能指针的形式
//懒得在初始化列表中初始化参数了,直接使用类内初始化
std::shared_ptr<vector<string>> text_content = std::make_shared<vector<string>>();
std::shared_ptr<map<string, set<size_t>>> word_to_line_set_map = std::make_shared<map<string, set<size_t>>>();
std::shared_ptr<map<string, size_t>> word_count_map = std::make_shared<map<string, size_t>>();
};
QueryResult TextQuery::query(const string& str) {
if ((*word_count_map).find(str)!= (*word_count_map).end()) {
return QueryResult(str, text_content, word_to_line_set_map, word_count_map);
}
size_t line = 1;
size_t word_count = 0;
set<size_t> word_appear_line_set;
for (const auto& line_str : *text_content) {
string single_word;
std::istringstream single_text_stream(line_str);
while (single_text_stream >> single_word) {
if (str == single_word) {
word_appear_line_set.insert(line);
//统计次数的加一
++word_count;
}
}
++line;
}
(*word_to_line_set_map)[str] = word_appear_line_set;
(*word_count_map)[str] = word_count;
return QueryResult(str,text_content,word_to_line_set_map,word_count_map);
}
ostream& print(ostream& out,const QueryResult& result) {
string target_word = result.query_word;
out << target_word << " appear " << (*result.word_count_map)[target_word] << " times" << endl;
for (const auto & line : (*result.word_to_line_set_map)[target_word] ) {
out << "line:" << line << " " << (*result.text_content)[line - 1]<<endl;
}
return out;
}
void runQueries(ifstream &infile) {
TextQuery tq(infile);
while (true) {
cout << "输入你要查询的词" << endl;
string s;
if ((!(cin>>s)||s=="q")) {
break;
}
print(cout,tq.query(s))<<endl;
}
}
12.28
这里其实就是将上面的拆分的内容写到一个文件里面,这里就不写了
12.29
习惯使用while,如果在所有可以使用while或者do_while的地方都使用while,我就不用考虑用while还是do_while了,而且while可以完成do_while的工作,所以我倾向于使用while。
12.30
代码已经写在了12.27 和书上的区别在于,书中是在从文件中获取文本时,就已经构建好了索引。
我是在查询的时候构建索引,如果再次查询,索引已经存在则直接返回结果,如果不存在则构建索引
12.31
在我的程序中,使用vector代替set更加的麻烦,因为set本身就不允许重复的关键字存在,而vector则需要自己判断
12.32
将QueryResult和TextQuery类中的std::shared_ptr<vector>改成StrBlob就可以了,因为StrBolb内部就维护了一个std::shared_ptr<vector>,我们可以直接写StrBlob。
12.33
我目前不清楚
添加名为begin和end的成员,返回一个迭代器,指向给定查询返回的行号的set中的位置,这句话是什么意思?
如果是返回给定查询的包含所有行号的set的begin和end,那么可以写成
set<size_t>::iterator begin() {
return (*word_to_line_set_map)[query_word].begin();
};
set<size_t>::iterator end() {
return (*word_to_line_set_map)[query_word].end();
};
而get_file()返回一个shared_ptr,指向QueryResult对象中的文件。这句话,指的如果是包含所有的文本的vector<string>的话,那么可以写成下面的形式
str_vec_ptr get_file() {
return text_content;
}
最后
以上就是无心诺言为你收集整理的C++ Primer 第十二章 12.3 使用标准库:文本查询程序 练习的全部内容,希望文章能够帮你解决C++ Primer 第十二章 12.3 使用标准库:文本查询程序 练习所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复