欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++詳解Primer文本查詢程序的實(shí)現(xiàn)

 更新時(shí)間:2022年06月24日 09:41:02   作者:配的上了嗎  
這個(gè)程序還是比較復(fù)雜的,把這句話作為文章的開頭可以看出它的真實(shí)性.....這篇文章主要介紹了文本查詢程序的實(shí)現(xiàn),下面我們一起來看看

15.9的文本查詢程序是對(duì)12.3節(jié)的文本查詢程序的擴(kuò)展,而使用的主要知識(shí)也是15章的核心:繼承和多態(tài),即面向?qū)ο蟪绦蛟O(shè)計(jì)。

恩,這一節(jié)看的過程中,會(huì)有很多不理解。特別是在沒有把整個(gè)程序都看完之前,會(huì)有很多疑惑,而看完之后,再思考思考,回頭再看本節(jié)的前面所寫的程序介紹,會(huì)有一些感悟。更加清楚這個(gè)程序的原理。

TextQuery.h

#ifndef QUERY_TEXTQUERY_H
#define QUERY_TEXTQUERY_H
#include<iostream>
#include<vector>
#include<string>
#include<memory>
#include<map>
#include<set>
#include<cstdio>
#include<cstdlib>
#include<sstream>
#include<algorithm>
#include<fstream>
#include<stack>
using namespace std;
class QueryResult;
// ??????????????????????
class TextQuery
{
public:
    using line_no = vector<string>::size_type;
    TextQuery(ifstream&); // ?????????????????????????????в????????
    QueryResult query(const string&) const;  // ???????string???????string???в????
private:
    shared_ptr<vector<string>> file;  // ???????
    map<string, shared_ptr<set<line_no>>> wm;  // ???????????????????????к?set??
};
inline TextQuery::TextQuery(ifstream &is): file(new vector<string>) {
    string text;
    while (getline(is, text)) {   // ??????е?????
        file->push_back(text);    // ????????е????
        int n = file->size() - 1;  // ???浱????к???????·?????????????shared_ptr<set<line_no>> ?????????к?
        istringstream line(text);
        string word;
        while(line >> word){
            auto &lines = wm[word];  // lines?????shared_ptr
            if(!lines)   // ??????±??????????map?д????????word?????word????????shared_ptr??????shared_ptr???????nullptr;
                lines.reset(new set<line_no>);
            lines->insert(n);
        }
    }
}
class QueryResult{
    friend ostream& print(ostream& os, const QueryResult& qr);
public:
    QueryResult(string s, shared_ptr<set<TextQuery::line_no>> p, shared_ptr<vector<string>> f)
            : sought(s), lines(p), file(f) {}
    auto begin()const {return lines->begin();}
    auto end()const{return lines->end();}
    shared_ptr<vector<string>> get_file()const {return file;}
private:
    string sought; // ????????
    shared_ptr<set<TextQuery::line_no>> lines;  // ??????к?
    shared_ptr<vector<string>> file;  // ???????
};
inline QueryResult TextQuery::query(const string& s)const {
    static shared_ptr<set<line_no>> nodata(new set<line_no>()); // ?????????????к?set??shared_ptr
    auto loc = wm.find(s);
    if(loc == wm.cend())
        return QueryResult(s, nodata, file);
    else
        return QueryResult(s, loc->second, file);
}
inline ostream& print(ostream& os, const QueryResult& qr)
{
    os<<qr.sought<<" occurs "<<qr.lines->size()<<" "<<((qr.lines->size()>1)?"times":"time")<<endl;
    for(const auto& num: *(qr.lines)){
        os << "\t(lines "<<num+1<<") "<<(*(qr.file))[num]<<endl;
    }
    return os;
}
inline void runQueries(ifstream& infile)
{
    // infile?????ifstream??????????????????
    TextQuery  tq(infile);
    // ????????????????????????????????????????????
    while(true)
    {
        cout<<"enter word to look for, or q to quit: "<<endl;
        string s;
        // ?????????????s=='q'?????
        if(!(cin>>s) || s == "q")  break;
        print(cout, tq.query(s)) << endl;
    }
}
inline void independent_word_query(ifstream& ifile){
    vector<string> file;
    map<string,set<int>> word_map;
    string text;
    while(getline(ifile, text)){
        file.push_back(text);
        int n = (int)file.size()-1;  // ???push_back?????е??±?
        istringstream line(text);   // ???string text???????????
        string word;
        while(line >> word){
            word_map[word].insert(n);
        }
    }
    while(true){
        cout << "Enter word to look for, or q to quit: "<<endl;
        string s;
        if(!(cin>>s) || s=="q")  break;
        const auto& lines = word_map.find(s); // ?????????????????????pair<string,set<int>>
        cout<<s<<" occurs "<<(*lines).second.size()<<(lines->second.size()>1?" times":" time")<<endl;
        for(const auto& i:lines->second){
            cout<<"\t(lines "<<i+1<<") "<<file[i]<<endl;
        }
    }
}
#endif

Query.h

#ifndef QUERY_QUERY_H
#define QUERY_QUERY_H
#include"TextQuery.h"
class Query_base
{
    friend class Query;
protected:
    using line_no = TextQuery::line_no;   // ???????????eval?????????????????protected??
    virtual ~Query_base() = default;
private:
    // eval???????????Query????QueryResult
    virtual QueryResult eval(const TextQuery&) const = 0;
    // rep???????????string
    virtual string rep() const = 0;
};
class Query
{
    friend Query operator|(const Query&, const Query&);
    friend Query operator&(const Query&, const Query&);
    friend Query operator~(const Query&);
public:
    Query(const string&);    // ????????μ?WordQuery
public:
    QueryResult eval(const TextQuery& t)const { return q->eval(t); }
    string rep()const { return q->rep(); }
private:
    Query(shared_ptr<Query_base> query) :q(query){}
    shared_ptr<Query_base> q;
};
//ostream& operator<<(ostream& os, const Query& q)
//{
//    // Query::rep???????Query_base????rep???????????
//    return os<<q.rep();
//}
class WordQuery: public Query_base
{
    friend Query;
private:
    WordQuery(const string& s): query_word(s) {}
    virtual QueryResult eval(const TextQuery& t)const override
            { return t.query(query_word); }
    virtual string rep() const override
            { return query_word; }
    string query_word;
};
inline Query::Query(const string& s): q(new WordQuery(s)) {}  // ??Query????????????·???????
// Query q = ~Query("dog");
class NotQuery: public Query_base
{
    friend Query operator~(const Query&);
private:
    NotQuery(const Query& q): query(q) {}
    virtual QueryResult eval(const TextQuery&) const override;
    virtual string rep() const override
    { return "~("+query.rep()+")"; }
    Query query;
};
inline Query operator~(const Query &operand)
{
    return Query(shared_ptr<Query_base>(new NotQuery(operand)));
}
class BinaryQuery: public Query_base
{
protected:
    BinaryQuery(const Query& l, const Query &r, string s):
    lhs(l), rhs(r), opSym(s) {}
    // ???????BinaryQuery??????eval;
    virtual string rep()const override { return "(" + lhs.rep() + " " + opSym + + " " + rhs.rep() + ")"; }  // ???????rep??????????
    Query lhs, rhs;
    string opSym;
};
class AndQuery: public BinaryQuery
{
    friend Query operator&(const Query&, const Query&);
private:
    AndQuery(const Query& left, const Query& right): BinaryQuery(left,right,"&") {}
    // ?????rep????????eval
    QueryResult eval(const TextQuery&) const override;
};
inline Query operator&(const Query &lhs, const Query &rhs)
{
    return Query (shared_ptr<Query_base>(new AndQuery(lhs,rhs)));
}
class OrQuery: public BinaryQuery
{
    friend Query operator|(const Query&, const Query&);
private:
    OrQuery(const Query& left, const Query &right): BinaryQuery(left,right,"|") {}
    QueryResult eval(const TextQuery&)const override;
};
inline Query operator|(const Query &lhs, const Query &rhs)
{
    return Query(shared_ptr<Query_base>(new OrQuery(lhs,rhs)));
}
#endif //QUERY_QUERY_H

Query.cpp

#include "Query.h"
// Query q = Query("dog") | Query("cat");
QueryResult OrQuery::eval(const TextQuery& t) const
{
    auto left = lhs.eval(t), right = rhs.eval(t);
    shared_ptr<set<line_no>> ret_lines(new set<line_no>(left.begin(),left.end()));
    ret_lines->insert(right.begin(),right.end());
    return QueryResult(rep(),ret_lines,lhs.eval(t).get_file());
}
QueryResult AndQuery::eval(const TextQuery& text) const
{
    auto left = lhs.eval(text), right = rhs.eval(text);
    auto ret_lines = make_shared<set<line_no>>();  // ????set??????????????????????
    set_intersection(left.begin(),left.end(),right.begin(),right.end(),inserter(*ret_lines,ret_lines->begin()));
    return QueryResult(rep(),ret_lines,left.get_file());
}
QueryResult NotQuery::eval(const TextQuery& text) const
{
    auto result = query.eval(text);
    auto ret_lines = make_shared<set<line_no>>();
    auto beg = result.begin(), end = result.end();
    auto sz = result.get_file()->size();
    for(size_t n = 0; n != sz; ++n){
        if(beg == end || *beg != n)
            ret_lines->insert(n);
        else
            ++beg;
    }
    return QueryResult(rep(), ret_lines, result.get_file());
}

main.cpp

void read_file(ifstream &f){
    TextQuery textquery(f);
    Query q ( Query("dog") & Query("cat"));
    print(cout,q.eval(textquery))<<endl;
    Query q2 = Query("bbb");
    print(cout, q2.eval(textquery))<<endl;
    Query q3 = ~Query("dog");
    print(cout, q3.eval(textquery))<<endl;
    system("pause");
}
int main(){
    string filename;
    cout<<"Please enter filename"<<endl;
    cin >> filename;
    ifstream file(filename);
    if(!file){
        cout<<"Filename error"<<endl;
        return -1;
    }
    read_file(file);
    return 0;
}

出現(xiàn)了一些意外,代碼中中文注釋都是亂碼。

針對(duì)程序所涉及的幾個(gè)類的介紹和理解:

TextQuery類:

可以把每個(gè)TextQuery類對(duì)象看作一個(gè)文本文件,這個(gè)類將某個(gè)文本文件的內(nèi)容保存在一個(gè)vector<string>中,并保存了每個(gè)單詞對(duì)應(yīng)的行號(hào),而query函數(shù)就是接收一個(gè)string,然后查找這個(gè)單詞。而這里的返回結(jié)果是一個(gè)QueryResult類對(duì)象。這個(gè)類只是用來保存一個(gè)查詢結(jié)果,其實(shí)后續(xù)的& | ~的結(jié)果也都是這個(gè)QueryResult類對(duì)象

在12章時(shí),我想過,為什么要設(shè)計(jì)這么一個(gè)類呢?如果直接在query函數(shù)中實(shí)現(xiàn)查找并打印不可以嗎?其實(shí)這樣是不太合適的,一個(gè)最直接的原因就是,在后方進(jìn)行word1 & word2操作時(shí),不方便,封裝一個(gè)查詢結(jié)果類更容易處理。這樣,也可以支持更多的操作,而不僅僅是打印。

QueryResult類:

表示一個(gè)查詢結(jié)果,通常與print函數(shù)聯(lián)系起來使用,print用于打印這個(gè)查詢結(jié)果。

后續(xù)的就是一些新的繼承方面的類了,也就是為了支持word1 & word2 或者 word1 | word2 或者 ~word操作。而這些查詢都建模成了相互獨(dú)立的類,即AndQuery OrQuery NotQuery 而最基本的還有一個(gè)WordQuery,這些類都繼承自一個(gè)抽象基類Query_base。

Query_base類:

最主要的就是兩個(gè)成員函數(shù):eval 和 rep,說真的,我覺得這兩個(gè)名字起的并不好,當(dāng)然受限于我的英文水平,其實(shí)eval就相當(dāng)于TextQuery類的query函數(shù),參數(shù)是TextQuery,即一個(gè)文本文件,然后在這個(gè)文本文件中執(zhí)行查詢操作,返回一個(gè)查詢結(jié)果QueryResult。rep函數(shù)用于返回查詢的string表示形式,比如~(word1 & word2)。

Query類:

這個(gè)類是很重要的,當(dāng)然這句話是句廢話.... 這個(gè)類的數(shù)據(jù)成員是一個(gè)基類的指針,而這也是這個(gè)程序支持面向?qū)ο缶幊毯投鄳B(tài)的根本原因。

這是一個(gè)接口類,它的成員函數(shù)仍然是eval和rep,調(diào)用的是基類指針?biāo)赶驅(qū)ο蟮膃val和rep,基類指針或引用調(diào)用虛函數(shù)發(fā)生動(dòng)態(tài)綁定。所以,Query類基類指針指向的對(duì)象,可能是繼承體系中任何一種類型的對(duì)象。比如: Query q = Query("dog") & Query("cat"); 而這里的q的基類指針指向的就是一個(gè)AndQuery類的對(duì)象,調(diào)用的eval和rep也都是AndQuery類版本的eval和rep,而這個(gè)AndQuery類的數(shù)據(jù)成員就包括著右邊&運(yùn)算符左右兩邊的兩個(gè)WordQuery類的對(duì)象,這里是使用了&運(yùn)算符重載。operator& 返回的就是一個(gè)基類指針綁定到AndQuery類對(duì)象的Query類對(duì)象。返回值用于初始化q。這里調(diào)用的應(yīng)該是Query類的拷貝構(gòu)造函數(shù)吧

WordQuery類:

Query_base類的派生類,表示對(duì)于某個(gè)單詞最直接的查詢,覆蓋了eval和rep,為什么說eval相當(dāng)于query呢?這里的eval就是最明顯的證明:這里的eval直接返回參數(shù)TextQuery類的query結(jié)果,就是對(duì)某個(gè)單詞的查詢結(jié)果。而后方的Not And Or,都沒有調(diào)用這個(gè)query操作,他們操作的是Query類對(duì)象的查詢結(jié)果。

NotQuery類:

這個(gè)類也是Query_base的派生類,表示~查詢方式。~運(yùn)算符重載之后,返回的就是一個(gè)綁定到NotQuery類對(duì)象上的Query類對(duì)象,而~作用的就是另一個(gè)Query類對(duì)象的eval查詢結(jié)果。

AndQuery OrQuery類:

因?yàn)檫@兩個(gè)類都操作兩個(gè)Query類對(duì)象,所以又實(shí)現(xiàn)了一個(gè)BinaryQuery抽象基類,這個(gè)基類繼承自Query_base,多了兩個(gè)Query類對(duì)象的成員,以及一個(gè)操作符成員,用于表示& 還是 |。

這兩個(gè)類所關(guān)聯(lián)的是& |運(yùn)算符,operator& 返回的分別是是基類指針綁定到AndQuery類對(duì)象上的Query類對(duì)象 。operator | 返回的是基類指針綁定到OrQuery類對(duì)象上的Query類對(duì)象,而這兩個(gè)類的rep函數(shù)很簡(jiǎn)單,對(duì)于兩個(gè)成員的rep函數(shù)進(jìn)行一些簡(jiǎn)單加工即可,而eval函數(shù),參數(shù)仍然是一個(gè)TextQuery類,在兩個(gè)Query成員返回的QueryResult上進(jìn)行處理,然后返回一個(gè)新的QueryResult對(duì)象。代表著一種& 或者 |操作之后的查詢結(jié)果。

還有一個(gè)比較有趣的是:

如下代碼:

Query q = Query("Dog") & Query("Cat") | Query("Bird");

Print( cout, q.eval(textquery) );

一共創(chuàng)建了三個(gè)WordQuery,一個(gè)AndQuery,一個(gè)OrQuery。先后順序不太清楚。。。但是其實(shí)創(chuàng)建好q對(duì)象之后,這里面并沒有什么查詢結(jié)果,保存的只是這些單詞,還有一些沒有調(diào)用的成員函數(shù)eval和rep。

根據(jù)運(yùn)算符優(yōu)先級(jí)規(guī)則,q是一個(gè)基類指針指向OrQuery類對(duì)象的Query對(duì)象,而如果想打印出這個(gè)查詢結(jié)果,必然是要調(diào)用eval函數(shù)的,參數(shù)表示,在這個(gè)文件里查找這三個(gè)單詞。在OrQuery的eval調(diào)用的最開始,兩個(gè)Query類對(duì)象數(shù)據(jù)成員的查詢結(jié)果還沒有出來,而在eval函數(shù)內(nèi)部,計(jì)算了兩個(gè)查詢結(jié)果,一個(gè)是rhs數(shù)據(jù)成員的對(duì)Bird單詞的查詢,查詢的位置就是那個(gè)textquery保存的文件內(nèi)容。另一個(gè)是AndQuery的eval函數(shù)的返回結(jié)果,這個(gè)結(jié)果是對(duì)兩個(gè)WordQuery類對(duì)象查詢結(jié)果的&操作之后的結(jié)果。最后才對(duì)這兩個(gè)QueryResult結(jié)果進(jìn)行合并處理。然后返回一個(gè)新的查詢結(jié)果。

現(xiàn)在看來,只有WordQuery類對(duì)象調(diào)用了TextQuery的query操作。而其余的Or Not And都是對(duì)其他的Query對(duì)象的查詢結(jié)果進(jìn)行加工。當(dāng)然這些eval函數(shù)的參數(shù)都是同一個(gè)TextQuery。并且都是返回的QueryResult。

說真的,之前比較疑惑的是,我感覺這些eval函數(shù)的TextQuery參數(shù)的傳遞有些奇怪。對(duì)比之前12章的文本查詢程序,最后封裝的對(duì)文件的查詢的函數(shù),看上去就舒服多了,它是把ifstream類對(duì)象傳遞給TextQuery類的構(gòu)造函數(shù)的參數(shù),然后后面調(diào)用query函數(shù)進(jìn)行查詢,返回一個(gè)QueryResult對(duì)象。調(diào)用print函數(shù)打印。

但是這里再探的程序就有點(diǎn)不一樣和奇怪了,你也可以封裝一個(gè)完整的查詢函數(shù),但是如果不那樣做的話,進(jìn)行的操作就是。

Query q = Query("Dog") & Query("Cat") | Query("Bird");

Print( cout, q.eval(textquery) );

這種操作,相比于 TextQuery tq(ifile); print(cout, tq.query("Dog")); 就有點(diǎn)奇怪了。

上方的main.cpp主函數(shù),并沒有實(shí)現(xiàn)完善的查詢函數(shù),即實(shí)時(shí)查詢操作,如輸入Dog & Cat | Bird。然后打印查詢結(jié)果,之后有能力實(shí)現(xiàn)的話可能會(huì)補(bǔ)上。

就以這篇文章作為大一學(xué)習(xí)生活的結(jié)束吧。

到此這篇關(guān)于C++詳解Primer文本查詢程序的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++文本查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 通過C++程序示例理解設(shè)計(jì)模式中的外觀模式

    通過C++程序示例理解設(shè)計(jì)模式中的外觀模式

    這篇文章主要介紹了通過設(shè)計(jì)模式中的外觀模式及相關(guān)的C++程序示例,外觀模式在高層提供了一個(gè)統(tǒng)一的接口實(shí)現(xiàn)一定程度上的解耦,需要的朋友可以參考下
    2016-03-03
  • C++中簡(jiǎn)單讀寫文本文件的實(shí)現(xiàn)方法

    C++中簡(jiǎn)單讀寫文本文件的實(shí)現(xiàn)方法

    本篇文章是對(duì)C++中簡(jiǎn)單讀寫文本文件的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++在vscode中的多文件編程問題解讀

    C++在vscode中的多文件編程問題解讀

    這篇文章主要介紹了C++在vscode中的多文件編程問題解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 一文帶你入木三分地理解字符串KMP算法以及C++實(shí)現(xiàn)

    一文帶你入木三分地理解字符串KMP算法以及C++實(shí)現(xiàn)

    KMP算法是一種改進(jìn)的字符串匹配算法,KMP算法的核心是利用匹配失敗后的信息,盡量減少模式串與主串的匹配次數(shù)以達(dá)到快速匹配的目的。本文就來和大家聊聊KMP算法的原理與實(shí)現(xiàn),需要的可以參考一下
    2022-12-12
  • C++中std::construct()與std::destroy()的使用

    C++中std::construct()與std::destroy()的使用

    std::construct()和std::destroy()是C++ STL中的函數(shù)模板,用于在已分配的存儲(chǔ)區(qū)域中構(gòu)造或銷毀對(duì)象,本文主要介紹了C++中std::construct()與std::destroy()的使用,感興趣的可以了解一下
    2024-02-02
  • C/C++的各種字符串函數(shù)你知道幾個(gè)

    C/C++的各種字符串函數(shù)你知道幾個(gè)

    這篇文章主要為大家詳細(xì)介紹了C/C++的各種字符串函數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • C++深復(fù)制和淺復(fù)制講解

    C++深復(fù)制和淺復(fù)制講解

    這篇文章主要介紹了C++深復(fù)制和淺復(fù)制講解,C++中深復(fù)制和淺復(fù)制最大的區(qū)別在“類包含指針類型的數(shù)據(jù)成員”時(shí),下面感興趣的小伙伴和小編一起進(jìn)入文章了解更多相關(guān)內(nèi)容吧
    2022-03-03
  • 基于C語言實(shí)現(xiàn)簡(jiǎn)單的走迷宮游戲

    基于C語言實(shí)現(xiàn)簡(jiǎn)單的走迷宮游戲

    這篇文章主要介紹了基于C語言實(shí)現(xiàn)簡(jiǎn)單的走迷宮游戲,用到雙向隊(duì)列,方便在運(yùn)行完畢后輸出經(jīng)過的點(diǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-04-04
  • C語言?超詳細(xì)介紹與實(shí)現(xiàn)線性表中的無頭單向非循環(huán)鏈表

    C語言?超詳細(xì)介紹與實(shí)現(xiàn)線性表中的無頭單向非循環(huán)鏈表

    無頭單向非循環(huán)鏈表:結(jié)構(gòu)簡(jiǎn)單,一般不會(huì)單獨(dú)用來存數(shù)據(jù)。實(shí)際中更多是作為其他數(shù)據(jù)結(jié)構(gòu)的子結(jié)構(gòu),如哈希桶、圖的鄰接表等等。另外這種結(jié)構(gòu)在筆試面試中出現(xiàn)很多
    2022-03-03
  • C語言中關(guān)于動(dòng)態(tài)內(nèi)存分配的詳解

    C語言中關(guān)于動(dòng)態(tài)內(nèi)存分配的詳解

    動(dòng)態(tài)內(nèi)存是指在堆上分配的內(nèi)存,而靜態(tài)內(nèi)存是指在棧上分配的內(nèi)存。棧上分配的內(nèi)存是由系統(tǒng)分配和釋放的,空間有限,在復(fù)合語句或函數(shù)運(yùn)行結(jié)束后就會(huì)被系統(tǒng)自動(dòng)釋放而堆上分配的內(nèi)存則不會(huì)有這個(gè)問題。
    2021-09-09

最新評(píng)論