C++primer 文本查询类复现+个人理解

最近在看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

结果展示
在这里插入图片描述
浅记录一下。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值