最近在看c++primer,第12章节中利用共享指针等操作,是西安了一个文本查询的功能,照着书敲了一遍加深自己的理解,记录一下
#include<bits/stdc++.h>
using namespace std;
//在定义头文件的时候,不把std空间进行展开
//定义存储类,仅仅是定义,函数声明分开
class QueryResult;//TextQuery类要用到
class TextQuery{
public:
using line_no=std::vector<std::string>::size_type;//行数
TextQuery(std::ifstream&);//构造函数
QueryResult query(const std::string)const;//对本TextQuery进行查询,并返回结果的函数
private:
//至少一个共享指针,指向创建出来的,存储句子的存储空间
//用共享指针,本对象销毁后可以释放内存
std::shared_ptr<std::vector<std::string>>file;
// 一个map用于保存处理过的消息
//??为什么map不用shared_ptr而set要用呢???
std::map<std::string,
std::shared_ptr<std::set<line_no>>>wm;
};
//针对类内函数进行具体定义
//↓这里表示,file这个参数直接用括号内内容进行定义
TextQuery::TextQuery(ifstream&is):file(new vector<string>)
{
string text;int f=0;
while(getline(is,text)){//从is流中,按行进行读取
file->push_back(text);
int n=file->size()-1;//当前行号
istringstream line(text);//把string变成流水
string word;
while(line>>word){//从line流中,按词进行读取
auto &lines=wm[word];//把word加到本对象的wm中,map的second是一个共享指针
f++;
if(!lines){ //如果没有加入过,则共享指针最开始为空
//如果换成了不用共享指针的版本,此处应该判断set的大小是否为
lines.reset(new set <line_no>);//如果没有,则分配新的内存保存这部分内容
}
//下一行等价于lines->insert(n);
(*lines).insert(n);//确认共享指针不为空后,添加本次的行数
//是引用哦
}
}cout<<"f="<<f<<endl;//输出检测到了多少个单词
}
//用来存储结果,方便后面输出
//使用指针,直接针对原有对象存储空间里的部分进行输出,而不是新建set
class QueryResult{
friend std::ostream&print(std::ostream&,const QueryResult&);//允许重载的print直接访问我的私有成员
public:
using line_no=std::vector<std::string>::size_type;//行数
QueryResult(std::string s,
std::shared_ptr<std::set<line_no>>p,
std::shared_ptr<std::vector<std::string>>f):
sought(s),lines(p),file(f){}
private:
std::string sought;//保存要查询的单词
std::shared_ptr<std::set<line_no>>lines;//用来指向map中的set
std::shared_ptr<std::vector<std::string>>file;//输入文件?
//在输出的时候,需要把整句进行输出,直接使用指针不占用额外的内存
//要这个干嘛?不能直接在输出的print函数里面调用吗?
//不能,对print的重载是在类外部的
};
//如何设计函数query,通过查找s获得QueryResult结果呢?
QueryResult TextQuery::query(const string sought)const
{
shared_ptr<set<line_no>>no_data(new set<line_no>);
auto loc=wm.find(sought);//使用find而不是下标,防止被直接添加进去(可以检测到但是没必要
if(loc==wm.end()){
return QueryResult(sought,no_data,file);//没找到
}
return QueryResult(sought,loc->second,file);//找到了,返回对应的set的共享指针
}
ostream &print(ostream&os,const QueryResult &qr){//对print进行重载
//放到os流中
os<<qr.sought<<"occur "<<qr.lines->size()<<" timess"<<endl;
for(auto num:*qr.lines){ //对指向对应set的共享指针进行解引用
os<<"\t(line"<<num+1<<")" //set中存放所有的行数
//不能直接用指针加,和vector一样,需要加num
<< *(qr.file->begin()+num)<<endl; //使用共享指针到元对象中的位置,取出来对应行的内容
}
return os;//为啥是返回这一类?
}
//主要函数
void runQueries(ifstream &infile){
TextQuery tq(infile);
while(true){
cout<<"enter word 2 look for,or q to quit";
string s;
if(!(cin>>s)||s=="q")break;
//此处的print是重写过后的
print(cout,tq.query(s))<<endl;
}
}
int main(){
ifstream infile;
string path="E:/postg2.1/jobjob/autumn/textcheck.txt";
infile.open(path);
runQueries(infile);
}
textcheck.txt中的内容
i love you
you love me
ee bb
bb love bb
结果展示
浅记录一下。