zoukankan      html  css  js  c++  java
  • C++ Primer : 第十二章 : 文本查询程序

    C++ Primer书上这个例子讲的很不错,写写帮助自己理解标准库和智能指针。


    .h 文件内容

    #include <fstream>
    #include <iostream>
    #include <vector>
    #include <string>
    #include <map>
    #include <set>
    #include <sstream>
    #include <memory>
    
    class QueryResult;
    
    class TextQuery {
    
    public:
    
    	using line_no = std::vector<std::string>::size_type;
    
    	TextQuery(std::ifstream& ifs);
    
    	// 返回string的信息
    	QueryResult query(const std::string&) const;
    
    private:
    
    	std::shared_ptr<std::vector<std::string>> words_file;
    	std::map<std::string, std::shared_ptr<std::set<line_no>>> wm;
    
    };
    
    
    class QueryResult {
    
    	friend std::ostream& print(std::ostream&, const QueryResult&);
    public:
    	
    	QueryResult(std::string s, std::shared_ptr<std::vector<std::string>> wf, std::shared_ptr<std::set<size_t>> l) : sought(s), file(wf), lines(l){}
    
    
    private:
    	std::string sought; // 要查询的单词
    	std::shared_ptr<std::vector<std::string>> file; // 输入文件
    	std::shared_ptr<std::set<size_t>> lines; // 保存出现的行号
    
    };

    .cpp 文件内容

    #include "TextQuery.h"
    
    
    TextQuery::TextQuery(std::ifstream& ifs) : words_file(new std::vector<std::string>)
    {
    	std::string text;
    	while (getline(ifs, text)){
    
    		words_file->push_back(text);
    		// 记录当前行号
    		size_t n = words_file->size() - 1;
    
    		// 获取每行每个单词
    		std::istringstream line(text);
    		std::string word;
    		while (line >> word){
    
    			auto &ckeck = wm[word];
    			if (nullptr == ckeck)
    				ckeck.reset(new std::set<line_no>);
    
    			ckeck->insert(n);
    
    		}
    	}
    
    }
    
    QueryResult TextQuery::query(const std::string& s) const {
    
    	// 保存一个静态对象  如果未能找到单词,返回此对象
    	static std::shared_ptr<std::set<size_t>> nodata(new std::set<size_t>);
    
    	auto location = wm.find(s);
    
    	if (location == wm.end())
    		return QueryResult(s, words_file, nodata);
    	else
    		return QueryResult(s, words_file, location->second);
    }
    
    std::ostream& print(std::ostream& os, const QueryResult& qr){
    
    	os << qr.sought << " occurs " << qr.lines->size() << " "
    	   << (qr.lines->size() > 1 ? "times" : "time")   << std::endl;
    
    	for (auto num : *qr.lines)
    		os << "	(line " << num + 1 << ")"
    		   << *(qr.file->begin() + num)  << std::endl;
    	return os;
    }


    将TextQuery的word_file成员和wm的值set都放在智能指针内,以便QueryResult类可以在正常访问。


    TextQuery类:

    TextqUuery的构造函数接受一个ifstream,用来读取文件,构造函数的初始化列表中,并且将word_file初始化为一个空的vector, getline从文件中读取一行存入string text中,首先将这一行的内容储存在word_file中,然后计算该行的行号,即就是word_file的大小size() - 1,istringstream对象用来读取string text中的每个单词,如果单词不在wm中,将这个单词对应的set申请一个新的内存空间, 然后将这个单词存入wm的string中,并将它所在的行号存入wm的set中,如果这个单词存在wm中,即使这个单词是第二次或第二次之后出现在同一行,lines->insert(n)并不会执行,因为set不允许重复关键字出现。


    QueryResult类中,print函数将查找到的结果输出到屏幕。

    QueryResult的构造函数接受一个string,一个shared_ptr,类型为set<size_t>, 还有一个shared_ptr,类型为vector<string>,参数string表示要查询的单词,sett的shared_ptr指向TextQuery的wm中的set,vector的shared_ptr指向TextQuery中的word_file。



    TextQuerty中的query函数接受一个string,表示要查询的单词,在函数里声明了一个静态智能指针类型,用来表示未找到单词的set,表示没有该单词的行数可显示,然后在wm中查找该单词。


    print函数用于打印给定的QueryResult对象:如果找到了单词,先打印这个单词和出现的次数,qr.lines->size();表示这个set的大小,即就是表示这个单词出现的次数;

    然后在for循环中,num依次获取到这个单词出现的行数,由于我们习惯从1开始计数,因此将num + 1;然后在file中找到这一行的数据,*(qr.file->begin() + num), 从file这个vector的首元素开始向后便宜num个元素,即就是我们这个单词出现的那一行,然后我们解引用获得这给一行的string,并将它打印出来。



  • 相关阅读:
    边界值分析
    等价类划分
    手工检测SQL注入(安全性测试)
    Web安全性测试
    Jmeter使用流程及简单分析监控
    使用可视化工具redisclient连接redis
    Java ThreadLocal的使用
    jvm中的新生代Eden和survivor区
    策略模式和工厂模式的区别
    java将一数组乱序排列
  • 原文地址:https://www.cnblogs.com/averson/p/5150015.html
Copyright © 2011-2022 走看看