一、设计思路
数据结构:
1、读取文件时,要记住文件的每一行,并且要将每一行分解为独立的单词
vector<string> vec; istringstream
2、输出时提供每个单词与其关联的行号,且用map将单词与行号关联
map<string, set<int>> m_dit;
类的设计
1、设计保存输入文件的类TextQuery,设计QueryResult来保存查询结果。
TextQuery类中的query将返回这个结果
class TextQuery{ public: vector<string> file; map<stirng, set<int>> wm; QueryResult query(cosnt string &ought) const; };
2、类之间共享数据,QueryResult要表达的查询结果,数据保存在TextQuery对象中,返回指向
TextQuery对象内部的迭代器,可以避免拷贝操作,使用shared_ptr反映共享关系
shared_ptr<vector<string>> m_file; map<string, shared_ptr<set<int>>> wm;
3、QueryResult类
class QueryResult{ string sought; //单词 shared_ptr<set<int>> lines; //行号 shared_ptr<vector<string>> file; //输入文件 };
一些难点
1、TextQuery构造函数
class TextQuery{ TestQuery(ifstream &ifs):file(new vector<string>()){ //构造 //vector<string>为智能指针,所以要new .... while(iss >> word){ //单词不在wm中,以word为下标添加一项 auto &lines = wm[word]; //返回一个shared_ptr指针 if(!lines) lines.reset(new set<int>()); //指针为空,新建一个set放行号 lines->insertt(n); //不管是否为空指针,都将行号添加到set中 } } };
TextQuery构造完成后,结果便存到了数据结构中,之后创建TextQuery对象tq,执行query函数
2、query函数
接受一个string参数,找到后,构造一个QueryResult保存string、m_file以及从wm中提取的set
string未找到:定义一个static对象,指向空set的shared_ptr,返回此对象的一个拷贝
QueryResult query(const string &sought) const{ //未找到,返回一个指向该set的指针 static shard_ptr<set<<int>> nodata(new set<int>()); auto loc = find(sought); //不用下标运算符,避免插入 if(loc == wm.end()){ return QueryResult(sought, nodeta, file); }else{ return QueryResult(sought, loc->second, file); } }
3、QueryResult重载<<
os << rhs.sought << " occurs " << rhs.lines->size() << " " << ((rhs.lines->size() > 1) ? "times" : "time") << endl; //set的size成员说明单词出现多少次 for(auto num : *rhs.lines){ os << "\t(line " << num + 1 << ")" //避免行号从0开始给用户的困惑 << *(rhs.file()->begin() + num) << endl; }
单词未找到情况:set为空,第一条输出语句输出单词出现0次,*rhs.lines为空,for一次也不执行
源代码:1 #include <iostream> 2 #include<vector> 3 #include<string> 4 #include<map> 5 #include<memory> 6 #include<set> 7 #include<fstream> 8 #include<sstream> 9 10 using std::istringstream; 11 using std::ifstream; 12 using std::ofstream; 13 using std::vector; 14 using std::string; 15 using std::map; 16 using std::shared_ptr; 17 using std::set; 18 using std::cin; 19 using std::cout; 20 using std::endl; 21 22 /*借助智能指针实现文本查询程序*/ 23 24 class QueryResult{ 25 public: 26 QueryResult(string s, shared_ptr<set<int>> p, shared_ptr<vector<string>> f):sought(s), lines(p), file(f){ 27 28 } 29 30 friend std::ostream &operator<<(std::ostream &os, const QueryResult &rhs); 31 private: 32 string sought; 33 shared_ptr<set<int>> lines; 34 shared_ptr<vector<string>> file; 35 }; 36 37 38 std::ostream &operator<<(std::ostream &os, const QueryResult &rhs){ 39 os << rhs.sought << " occurs " << rhs.lines->size() << " " 40 << ((rhs.lines->size() > 1) ? "times" : "time") << endl; 41 42 for(auto num : *rhs.lines){ //遍历set中的行号,通过行号打印vector中的内容 43 os << "\t(line )" << num + 1 << ")" 44 << *(rhs.file->begin() + num) << endl; 45 } 46 47 return os; 48 } 49 50 //读取文件,存到数据结构中 51 class TextQuery{ 52 public: 53 TextQuery(ifstream &ifs); 54 55 QueryResult query(const string &ought) const; //查询,查询得到的结果返回给QueryResult 56 57 shared_ptr<vector<string>> m_file; 58 map<string, shared_ptr<set<int>>> m_dict; 59 }; 60 61 TextQuery::TextQuery(ifstream &ifs):m_file(new vector<string>){ 62 string line; 63 while(getline(ifs, line)){ 64 int n = m_file->size() - 1;//当前行号 65 m_file->push_back(line); 66 67 string word; 68 istringstream iss(line); 69 while(iss >> word){ 70 auto &relationship = m_dict[word]; //单词与行号之间的关系,返回的是一个shared_ptr 71 if(!relationship) relationship.reset(new set<int>()); //指针为空,新建一个set存放行号 72 relationship->insert(n); //指针不为空,说明记录该单词次数的set存在,将行号存起来 73 } 74 } 75 } 76 77 QueryResult TextQuery::query(const string &ought) const{ //打印结果 78 79 auto loc = m_dict.find(ought); //寻找该单词 80 shared_ptr<set<int>> nodata(new set<int>()); 81 82 if(loc != m_dict.end()){ 83 return QueryResult(ought, loc->second, m_file); //用QueryResult类存放结果 84 }else{ 85 return QueryResult(ought, nodata, m_file); 86 } 87 88 } 89 90 void runQueries(ifstream &ifs){ 91 TextQuery tq(ifs); 92 93 while(1){ 94 cout << "enter word to look for, or q to quit:"; 95 96 string s; 97 if(!(cin >> s) || s == "q"){ 98 break; 99 } 100 cout << tq.query(s) << endl; 101 } 102 103 } 104 105 int main(int argc, char **argv) 106 { 107 ifstream ifs("china_daily.txt"); 108 runQueries(ifs); 109 110 return 0; 111 }
标签:std,set,QueryResult,TextQuery,C++,查询,Day14,file,ptr From: https://www.cnblogs.com/YongSir/p/17092692.html