• 【C++ Primer 】第十二章 TextQuery 文本查询程序


    这个玩意搞了三天 , 实现了俩个版本 , 一个是单文件 , 一个多文件合并的 ,其中多文件这个遇到很多bug ,搞了好久,总体来说这个程序帮助还是很大的, 对前面的章节合并了,实现的过程也不断的去翻前面的笔记。

    程序介绍

    结合智能指针 实现一个单词文本查询程序。
    在这里插入图片描述

    程序思路

    考虑到这两个类概念上“共享”了数据,可以使用shared_ptr。
    开始一个程序的设计的一种好方法是列出程序的操作。了解需要哪些操作会帮助我们分析出需要什么样的数据结构。从需求入手,我们的文本查询程序需要完成如下任务:
    · 当程序读取输入文件时,它必须记住单词出现的每一行。因此,程序需要逐行读取输入文件,并将每一行分解为独立的单词
    · 当程序生成输出时:
    — 它必须能提取每个单词所关联的行号
    — 行号必须按升序出现且无重复
    — 它必须能打印给定行号中的文本。
    在这里插入图片描述

    先看多文件版本 注释多 好理解一点

    多文件版本

    实现过程中遇到俩个BUG : 一个就是print 这个名字是标准库的名字, 报错根本找不到, 应该换一个。
    另一个就是 头文件的定义, 声明了类,但是并没有声明它的构造函数,所以还是需要声明一下类的头文件!

    main.cpp

    #include<iostream>
    #include<fstream>
    #include<sstream>
    #include<string>
    #include<vector>
    #include<memory>
    #include<map>
    #include<set>
    #include "QueryResult.h"
    #include "TextQuery.h"
    using namespace std;
    
    
    void runQueries(ifstream& infile) {
        TextQuery tq(infile);
        while (true) {
            cout << "enter word  or Q to quit ! : ";
            string s;
            //输入单词查询 or 输入Q 退出 
            if (cin >> s && (s != "q" && s != "Q")) myprint(cout, tq.query(s)) << endl;
            else break;
        }
    }
    
    int main() {
        ifstream in("Text.txt");//打开文件
        if (in.is_open()) { // 如果打开了
            runQueries(in);  //  查询
        }
        else {
            cout << " open file error" << endl;
        }
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    QueryResult.h

    #include<iostream>
    #include<fstream>
    #include<sstream>
    #include<string>
    #include<vector>
    #include<memory>
    #include<map>
    #include<set>
    using namespace std;
    
    class QueryResult {
    private:
        string sought;  // 查询的单词
        shared_ptr<vector<string>> file; // 读入文件
        shared_ptr<set<unsigned int>> lines; // 出现的行号
    public:
        friend ostream& myprint(ostream&, const QueryResult&); //不能用书上的print  不然运行不了
        //QueryRestlt(){}
        QueryResult(string s, shared_ptr<set<unsigned int>> p, shared_ptr<vector<string>> f)
            : sought(s), file(f), lines(p) { }   // 构造
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    TextQuery.h

    #include<iostream>
    #include<fstream>
    #include<sstream>
    #include<string>
    #include<vector>
    #include<memory>
    #include<map>
    #include<set>
    //#include "QueryResult.h"
    using namespace std;
    class QueryResult;
    class TextQuery {
    private:
        shared_ptr<vector<string>> file;  //  用于接收传入的文件 的每一行字符串
        map<string, shared_ptr<set<unsigned int>>>  wm; // 每个单词映射到对应的行号
    public:
        // TextQuery(){ };
        TextQuery(ifstream& infile); //   构造函数
        QueryResult query(const string&);  // 查询
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    TextQuery.cpp

    #include<iostream>
    #include<fstream>
    #include<sstream>
    #include<string>
    #include<vector>
    #include<memory>
    #include<map>
    #include<set>
    #include "QueryResult.h" //  还是需要声明头文件 
    #include "TextQuery.h"//里面只声明类  但是没有构造函数 
    using namespace std;
    class QueryResult;
    
    TextQuery::TextQuery(ifstream& infile) : file(new vector<string>) {
        string tmp;
        while (getline(infile, tmp)) {  //读入文件  的每一行
            file->push_back(tmp);    // 存入 vs
            int lineNo = (int)file->size() - 1; // 当前行号
            istringstream line(tmp); // 转化为 is
            string word;
            while (line >> word) {  // is ——》 每个单词
                shared_ptr<set<unsigned int>>& lines = wm[word];  // 注意这是个指针,要new开辟空间
                if (!lines) //  如果这个单词没有的话  为空  需要开辟空间
                    lines.reset(new set<unsigned int>);  //分配一个新的set
                else
                    lines->insert(lineNo); // 向set中插入行号
            }
        }
    }
    
    QueryResult TextQuery::query(const string& s) {   //查询单词
        static shared_ptr<set<unsigned int>> nodata(new set<unsigned int>);   
        auto loc = wm.find(s);  
        if (loc == wm.end()) { // 如果没有找到
            return QueryResult(s, nodata, file);
        }
        else { //  如果找到了
            return QueryResult(s, loc->second, file);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    QueryResult.cpp

    #include<iostream>
    #include<fstream>
    #include<sstream>
    #include<string>
    #include<vector>
    #include<memory>
    #include<map>
    #include<set>
    #include "QueryResult.h"
    using namespace std;
    
    ostream& myprint(ostream& out, const QueryResult& qr) { // 第一个是参数IO   第二个参数 查询的QueryResult对象
        out << qr.sought << " occurs " << qr.lines->size() << ' ' << "times"
            << endl;
        for (auto num : *(qr.lines)) { // 遍历输出  如果没有这个单词  解引用为空
            out << "\t(line" << num + 1 << ") " << *(qr.file->begin() + num) << endl;  // 打印行号和
        }
        return out;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    单文件版本

    单文件就不需要考虑那么多了, 只需要把函数整合一起

    #include<iostream>
    #include<fstream>
    #include<sstream>
    #include<string>
    #include<vector>
    #include<memory>
    #include<map>
    #include<set>
    
    using namespace std;
    
    
    class QueryResult{
        private:
            string sought;
            shared_ptr<vector<string>> file;
            shared_ptr<set<unsigned int>> lines;
        public:
            friend ostream& print(ostream& out,const QueryResult& qr);
            QueryResult(string s,shared_ptr<set<unsigned int>> p,shared_ptr<vector<string>> f)
            : sought(s),file(f),lines(p)  { }
        
    };
    ostream& print(ostream& out,const QueryResult& qr){
        out << qr.sought << " occurs " << qr.lines->size() << ' ' << "times"
             << endl;
        for(auto num : *(qr.lines)){
            out<<"\t(line"<< num+1 <<") " << *(qr.file->begin()+num) <<endl;
        }
        return out;
    }
    class TextQuery{
        private:
            shared_ptr<vector<string>> file;    
            map<string,shared_ptr<set<unsigned int>>>  wm;
        public:
            TextQuery(){ }
            TextQuery(ifstream &infile): file(new vector<string>)
            {
                string tmp;
                while(getline(infile,tmp)){
                    file->push_back(tmp);
                    int lineNo = file->size()-1; // 当前行号
                    istringstream line(tmp);
                    string word;
                    while(line>>word){
                        shared_ptr<set<unsigned int>> &lines = wm[word];  // 注意这是个指针,要new开辟空间
                        if(!lines) // 看set中是否已经有了
                            lines.reset(new set<unsigned int>);
                        lines->insert(lineNo); // 向set中插入行号
                    }
                }
                
            }
            QueryResult query(const string &s){
                static shared_ptr<set<unsigned int>> nodata(new set<unsigned int>);
                auto loc = wm.find(s);
                if(loc == wm.end()){
                    return QueryResult(s,nodata,file);
                }
                else {
                    return QueryResult(s,loc->second,file);
                }
            }
    };
    
    void runQueries(ifstream &infile)
    {
        TextQuery tq(infile);
        while (true)
        {
            cout<<"enter word  or Q to quit ! : ";
            string s;
            if(cin>>s && (s!="q" && s!="Q")) print(cout, tq.query(s)) <<endl;
            else break;
        }
        
    }
    
    int main()
    {
        string fileName = "Text.txt";
        ifstream in(fileName);
        if(in.is_open()){
            runQueries(in);
        }
        else cout<< " open file error" <<endl;
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91

    运行结果

    Text.txt 内容可以自己加
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    JDBC笔记
    【探索排序算法的魅力:优化、性能与实用技巧】
    【Sklearn学习】Sklearn的数据集介绍
    存储大实验,游戏A Slower Speed of Light的开发
    Java开发学习(四十)----MyBatisPlus入门案例与简介
    9. python的if语句
    CSS样式:轮播图
    用Rust和Scraper库编写图像爬虫的建议
    【物理应用】Matlab模拟水中声呐模型
    HTML+CSS+JS电影网页设计 DW个人网页制作 Hbuilder制作简单的电影网页 在线电影网页设计与制作 web前端大作业
  • 原文地址:https://blog.csdn.net/weixin_49486457/article/details/125502275