• C++之文本查询系统


    1. 整体需求

    使用标准库实现一个简单的文本查询系统。允许用户在一个给定的文件中查询单词。查询结果是单词在文件中出现的次数以及所在行的列表。如果一个单词在一行中出现多次,该行也只列出一次,但是出现的次数得统计在内。行序号按照升序输出。

    2. 程序需要完成的功能和实现效果

    需要完成的功能:

    1.从文件按行读入信息,并将单词分离开来。
    2.必须提取到每一个单词所出现的行号 
    3.行号按照升序排列且不重复
    4.必须打印给定文本中的文字
    5.必须统计出一个单词所出现的所有次数
    

    实现效果:

    这里写图片描述

    3. 程序架构设计

    <1> 因为要打印文本中所出现的文字,所以就意味着需要保存 ,那么我们选择vector<string> 来保存它,另外行号还可以作为它的下标来提取文字。

    <2>使用istringstream 来分离单词 。

    <3>对于每一个单词,我们使用一个multiset来保存它在文本中出现的行号 。这就自然保证了升序的特点,至于重复的问题,我们只要在输出时解决一下就行了,反正multiset中只存储了行号,不会有很多重复的数据 。

    <4>使用一个map来将每个单词和它所对应的set关联起来,以便提取。

    <5> 使用智能指针!! 这是为什么呐?因为QueryResult 要查询到的数据原先全在 TextQuery 中的,如果将其拷贝到 QueryResult 类中,会花费很多的时间,那么我们通过指针来减少这种花费。考虑到两个对象的同步问题(比如在QueryResult 用到TextQuery之前,TextQuery对象已经销毁了),我们通过使用智能指针来解决这种矛盾 。

    4.实现代码:

    /*test.txt 文件中的内容 */
    liu
    sheng
    xi
    zui
    shuai 
    哦哦
    liu 
    liu liu liu 
    lu 
    liy
    bnglbn
    bkngbgmn blnblgnb ;ng;f f;gfg; nfnbdn 
     bbdnbkkbnbnonb 
      bntlobntol 
      liu liu
      liu 
      liull
      gmrlnrgliu
      liu shen xi
    /*************************************************************************
        > File Name: main.cpp
        > Author: 
        > Mail: 
        > Created Time: 2018年04月01日 星期日 11时42分31秒
     ************************************************************************/
    #include<iostream>
    #include<vector>
    #include<string>
    #include<set>
    #include<map>
    #include<memory> //shared_ptr 
    #include<fstream> 
    #include<sstream> //istringstream 
    using namespace std ;
    using line_no = vector<string>::size_type ; // 行号
    
    
    class DegbugDelete{ // 我们在这里自定义一个删除器
    public:
        DegbugDelete(ostream &s= cerr):os(s){  }
        template<typename T> 
        void operator()(T *p) const{
            os<< "deleteing shared_ptr " << endl ;
            delete  p;
        }
    private:
        ostream &os ;
    };
    class QueryResult{
        friend ostream& print(ostream& os , const QueryResult &TT ){ 
            os <<  TT.sought << "   occurs " << TT.lines->size()  << "  times  "<< endl ;
            if(TT.lines->size() == 0 ) 
                return os ;
            auto tag  = TT.lines->begin() ;
            decltype(tag) temp = tag ;
            tag++ ;
            while( temp != TT.lines->end()){
                if( *tag != *temp  ){
                     os << " 行 "<<*temp+1 << " : " <<  (*TT.file)[*temp] << endl ;
                }
                temp++ ;
                tag++  ;
            }
            return os  ;
        }
        public:
        QueryResult() = default ;
        QueryResult(string s ,
        shared_ptr<multiset<line_no>> p , 
        shared_ptr<vector<string>> f ):sought(s),lines(p),file(f){}
        private:
        string sought ;
        shared_ptr<multiset<line_no>> lines ; 
        shared_ptr<vector<string>> file ;
    };
    class TextQuery {
        public:
        TextQuery(ifstream &infile): file ( new vector<string> ,DegbugDelete() ) //定义删除器
        {   
            //读取文件数据到 vector<string> 中 ,分离各个单词 
            string text ,word ;
            while( getline(infile,text  )){ 
                file->push_back(text) ;
                int n = file->size() - 1 ;
                istringstream line(text) ; 
                while( line >> word ){ 
                    auto &lines = wm[word] ; //当我们这样使用时,加入没有的单词,就已经创建了,只不过指针是空的而已
                    if( ! lines )
                        lines.reset( new multiset<line_no> ,DegbugDelete() ) ; // 初始化 shared_ptr 
                    lines->insert(n) ; //插入n 
                }
            }
        }
        QueryResult query( const string &temp ) const { 
            static shared_ptr<multiset<line_no>> nodata(new multiset<line_no>,DegbugDelete()) ; 
            //emmmm ,如果不构造此空 set 使用默认的 default,就会出现段错误 
            auto loc = wm.find(temp);
            if( loc == wm.end() ){
                cout <<  temp << "  is not in test.txt  file " << endl ;
                return QueryResult(temp ,nodata ,file);
            }
            else 
                return QueryResult(temp, loc->second,file ) ;
        }
        private:
        shared_ptr< vector<string> > file ; //输入文件 ,智能指针 
        map<string,shared_ptr<multiset<line_no> > >  wm ; //每一个单词到行号的映射 
    };
    int fun(ifstream &infile){
            const TextQuery tq(infile);
            string word ;
            while(1) {
                cout << "    请 输 入 你 想 要 查 询 的 单 词 :" ;
                cin >> word ; 
                if(word == "q")
                    return 0 ;
                print(cout,tq.query(word)) << endl  ;
    
            }
            return 0 ;
    }
    int main(void){
        cout << "    你将在文件:test.txt 中查询你想要查询的单词 
    
    " << endl ;
        ifstream infile("test.txt");
        if( !infile.is_open()){
            cout << " 未 成 功 打 开 文 件!!" << endl ;
            return -1 ;
        }
        fun(infile);
        infile.close() ;
        return 0 ;
    }
    

    5.运行结果:

    这里写图片描述

  • 相关阅读:
    HTTP请求 GET POST 网络编程实现(转)
    较老版本 AFNetworking 使用心得
    优秀java开源项目与解决方案推荐与概论
    URL的格式scheme
    用MATLAB实现字符串分割
    matlab search path
    matlab中的字符串数组与函数调用
    全新重装win8.1系统后 配置开发及办公环境步骤
    html图片上下翻滚展示代码
    html目录树的操作
  • 原文地址:https://www.cnblogs.com/Tattoo-Welkin/p/10335298.html
Copyright © 2020-2023  润新知