最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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í)現(xiàn)學(xué)生管理系統(tǒng)總結(jié)

    C語言實(shí)現(xiàn)學(xué)生管理系統(tǒng)總結(jié)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • C/C++中虛函數(shù)詳解及其作用介紹

    C/C++中虛函數(shù)詳解及其作用介紹

    這篇文章主要介紹了C/C++中虛函數(shù)詳解及其作用介紹,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • 利用Matlab繪制好看的弦圖

    利用Matlab繪制好看的弦圖

    弦圖在python中以及R中非常常見,但是MATLAB中卻始終沒有相關(guān)函數(shù)。本文就來用Matlab繪制一些好看的弦圖,感興趣的小伙伴可以了解一下
    2022-08-08
  • C++中字符串與整型及浮點(diǎn)型轉(zhuǎn)換全攻略

    C++中字符串與整型及浮點(diǎn)型轉(zhuǎn)換全攻略

    C++算法刷題等過程中經(jīng)常會(huì)遇到字符串與數(shù)字類型的轉(zhuǎn)換,在這其中雖然樸素的算法有不少,但是對(duì)于double等類型還是可以說遇到一些麻煩,所以今天就來說說使用C++標(biāo)準(zhǔn)庫中的函數(shù)實(shí)現(xiàn)這些功能。感興趣的小伙伴一起參與閱讀吧
    2021-09-09
  • C++調(diào)用Matlab函數(shù)求特征值

    C++調(diào)用Matlab函數(shù)求特征值

    這篇文章主要為大家詳細(xì)介紹了C++調(diào)用Matlab函數(shù)求特征值,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • C語言版約瑟夫問題算法實(shí)現(xiàn)

    C語言版約瑟夫問題算法實(shí)現(xiàn)

    大家好,本篇文章主要講的是C語言版約瑟夫問題算法實(shí)現(xiàn),感興趣的同學(xué)趕快來看一看吧,對(duì)你又幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • C語言項(xiàng)目小學(xué)生數(shù)學(xué)考試系統(tǒng)參考

    C語言項(xiàng)目小學(xué)生數(shù)學(xué)考試系統(tǒng)參考

    今天小編就為大家分享一篇關(guān)于C語言項(xiàng)目小學(xué)生數(shù)學(xué)考試系統(tǒng)參考,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • c++11多種格式時(shí)間轉(zhuǎn)化為字符串的方法實(shí)現(xiàn)

    c++11多種格式時(shí)間轉(zhuǎn)化為字符串的方法實(shí)現(xiàn)

    本文主要介紹了c++11多種格式時(shí)間轉(zhuǎn)化為字符串的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • C語言GetStdHandle函數(shù)使用方法

    C語言GetStdHandle函數(shù)使用方法

    這篇文章介紹了C語言GetStdHandle函數(shù)的使用方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • C++消息隊(duì)列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收)

    C++消息隊(duì)列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收)

    這篇文章主要介紹了C++消息隊(duì)列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收),消息隊(duì)列是一種先進(jìn)先出的隊(duì)列型數(shù)據(jù)結(jié)構(gòu),實(shí)際上是系統(tǒng)內(nèi)核中的一個(gè)內(nèi)部鏈表
    2022-08-08

最新評(píng)論

含山县| 五河县| 三明市| 且末县| 奎屯市| 喜德县| 玛沁县| 广州市| 凭祥市| 崇仁县| 兴安盟| 伊宁市| 兴山县| 滦平县| 长沙县| 遂川县| 泽普县| 盐城市| 镇康县| 股票| 广元市| 安庆市| 雷山县| 濉溪县| 和平县| 武定县| 邹平县| 临城县| 镇赉县| 鹤岗市| 邹城市| 嘉义市| 蒙城县| 休宁县| 东至县| 滨州市| 滁州市| 铜陵市| 高淳县| 乌拉特前旗| 奎屯市|