关闭

C++ Primer 第15章例子-文本查询程序

3076人阅读 评论(3) 收藏 举报

1. Main.cpp

#include "TextQuery.h"
#include <fstream>
#include "QueryAll.h"

using namespace std;

void print_result(const set<TextQuery::line_no>& locs, const string& sought, const TextQuery& file)
{
	typedef set<TextQuery::line_no> line_nums;
	line_nums::size_type size = locs.size();
	cout<<"\n"<<sought<<" occurs "<<size<<(size>1?"Times":"Time")<<endl;
	line_nums::const_iterator it = locs.begin();
	for(; it!=locs.end(); ++it)
		cout<<(*it)+1<<"\t"<<file.text_line(*it)<<endl;
}

int main()
{
    ifstream is("text.txt");
    TextQuery tq;
    tq.read_file(is);
    Query q = Query("The") & Query("of") | Query("the");
    std::set<TextQuery::line_no> locs = q.eval(tq);
    string s("((fiery & bird) | wind)");
    print_result(locs, s, tq);
/*	ifstream infile("text.txt");
	if(!infile)
	{
		cout<<"No Input File!"<<endl;
		return -1;
	}
	TextQuery tq;
	tq.read_file(infile);
	while(true) {
		cout<<"Enter word to query, or q to quit: ";
		string s;
		cin>>s;
		if(!cin || s=="q")
			break;
		set<TextQuery::line_no> locs = tq.run_query(s);
		print_result(locs, s, tq);
	}*/
	while(true) {
        int i;
        cin>>i;
    };
	return 0;
}

2. TextQuery.h

#pragma once

#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>

class TextQuery {
public:
	typedef std::vector<std::string>::size_type line_no;
	void read_file(std::ifstream &is) {store_file(is); build_map();}
	std::set<line_no> run_query(const std::string&) const;
	std::string text_line(line_no) const;
	line_no size() const { return lines_of_text.size(); }

private:
	void store_file(std::ifstream&);
	void build_map();
	std::vector<std::string> lines_of_text;
	std::map<std::string, std::set<line_no> > word_map;
};

3. TextQuery.cpp

#include "TextQuery.h"
#include <fstream>
#include <sstream>

using namespace std;

void TextQuery::store_file(ifstream &is)
{
	string textline;
	while(getline(is,textline))
		lines_of_text.push_back(textline);
}

void TextQuery::build_map()
{
	for(line_no line_num=0; line_num!=lines_of_text.size(); ++line_num)
	{
		istringstream line(lines_of_text[line_num]);
		string word;
		while(line>>word)
		{
			word_map[word].insert(line_num);
		}
	}
}

set<TextQuery::line_no> TextQuery::run_query(const string &query_word) const
{
	map<string, set<line_no> >::const_iterator loc = word_map.find(query_word);
	if(loc==word_map.end())
		return set<line_no>();
	else
		return loc->second;
}

string TextQuery::text_line(line_no line) const
{
	if(line < lines_of_text.size())
		return lines_of_text[line];
	return NULL;
}

4. QueryAll.h

// Query.h

#ifndef QUERY_H
#define QUERY_H

#include "TextQuery.h"
#include <string>
#include <set>
#include <iostream>
#include <fstream>

///////////////////////////////////////////////////////////////////////////////////
// class QueryBase: private, abstract class acts as a base for concrete query types
class QueryBase
{
    friend class Query;
protected:
    typedef TextQuery::line_no line_no;
    virtual ~QueryBase() {}
private:
    // eval returns the |set| of lines that this Query matches
    virtual std::set<line_no> eval(const TextQuery&) const = 0;
    virtual std::ostream& display(std::ostream& = std::cout) const = 0;
};

///////////////////////////////////////////////////////////////////////////////////
// class Query
class Query
{
    // these operators need access to the QueryBase's constructor
    friend Query operator~ (const Query&);
    friend Query operator| (const Query&, const Query&);
    friend Query operator& (const Query&, const Query&);
    
public:
    // builds a new WordQuery
    Query(const std::string&);
    // copy control to manage pointers and reference counting
    Query(const Query &c): q(c.q), use(c.use) {
        ++*use;
    }
    ~Query() {
        decr_use();
    }
    Query& operator= (const Query&);
    // interface functions: will call corresponding QueryBase operations
    std::set<TextQuery::line_no> eval(const TextQuery &t) const {
        return q->eval(t);
    }
    std::ostream& display(std::ostream &os) const {
        return q->display(os);
    }
private:
    Query(QueryBase *query): q(query), use(new std::size_t(1)) {}
    QueryBase * q;
    std::size_t *use;
    void decr_use() {
        if (--*use == 0) {
            delete q;
            delete use;
        }
    }
};

inline Query& Query::operator=(const Query &rhs)
{
    ++*rhs.use; 
    decr_use(); 
    q = rhs.q; 
    use = rhs.use; 
    return *this; 
}

inline std::ostream& operator<<(std::ostream &os, const Query &q)
{
    return q.display(os);
}

/////////////////////////////////////////////////////////////////////////////////
// class WordQuery
class WordQuery: public QueryBase
{
    friend class Query; // Query uses the WordQuery constructor
private:
    WordQuery(const std::string &s): query_word(s) { }
    // concrete class: WordQuery defines all inherited pure virtual functions
    std::set<line_no> eval(const TextQuery &t) const {
        return t.run_query(query_word);
    }
    std::ostream& display(std::ostream &os) const {
        return os << query_word;
    }
    std::string query_word; // word for which to search
};

inline Query::Query(const std::string& word): q(new WordQuery(word)), use(new std::size_t(1)) {}

///////////////////////////////////////////////////////////////////////////////////
// class NotQuery
class NotQuery: public QueryBase
{
    friend Query operator~ (const Query &);
    NotQuery(const Query &q): query(q){}
    // concrete class: NotQuery defines all inherited pure virtual functions
    std::set<line_no> eval(const TextQuery&) const;
    std::ostream& display(std::ostream &os) const {
        return os << "~(" << query << ")";
    }
    const Query query;
};

///////////////////////////////////////////////////////////////////////////////////
// class BinaryQuery
class BinaryQuery: public QueryBase
{
protected:
    BinaryQuery(const Query &left, const Query &right, const std::string &op):
        lhs(left), rhs(right), oper(op) {}
    // abstract class: BinaryQuery doesn't define eval
    std::ostream& display(std::ostream &os) const {
        return os << "(" << lhs << " " << oper << " " << rhs << ")";
    }
    const Query lhs, rhs; 
    const std::string oper;
};

//////////////////////////////////////////////////////////////////////////////////////
// class AndQuery
class AndQuery: public BinaryQuery
{
    friend Query operator& (const Query&, const Query&);
    AndQuery(const Query &left, const Query &right): BinaryQuery(left, right, "&") {}
    // concrete class: AndQuery inherits display and defines remaining pure virtual

    std::set<line_no> eval(const TextQuery&) const;
};

//////////////////////////////////////////////////////////////////////////////////////
// class OrQuery
class OrQuery: public BinaryQuery
{
    friend Query operator| (const Query&, const Query&);
    OrQuery(const Query &left, const Query &right): BinaryQuery(left, right, "|") {}
    // concrete class: OrQuery inherits display and defines remaining pure virtual
    std::set<line_no> eval(const TextQuery&) const;
};

////////////////////////////////////////////////////////////////////////////////////////
inline Query operator& (const Query &lhs, const Query &rhs)
{
    return new AndQuery(lhs, rhs);
}

inline Query operator| (const Query &lhs, const Query &rhs)
{
    return new OrQuery(lhs, rhs);
}

inline Query operator~ (const Query & q)
{
    return new NotQuery(q);
}

#endif

4. QueryAll.cpp

// Query.cpp

#include "QueryAll.h"
#include "TextQuery.h"
#include <map>
#include <algorithm>
using namespace std;

set<TextQuery::line_no> NotQuery::eval(const TextQuery &file) const
{
    // virtual call through the Query handle to eval
    set<line_no> has_val = query.eval(file);
    set<line_no> ret;
    // for each line in the input file, check whether that line is in has_val
    for (line_no n = 0; n != file.size(); ++n)
        if (has_val.find(n) == has_val.end())
            ret.insert(n);
    return ret;
}

set<TextQuery::line_no> AndQuery::eval(const TextQuery &file) const 
{
    // virtual calls through the Query handle to get result sets for operands
    set<line_no> left = lhs.eval(file);
    set<line_no> right = rhs.eval(file);
    set<line_no> ret;
    set_intersection(left.begin(), left.end(), right.begin(), right.end(), inserter(ret, ret.begin()));
    return ret;
}

set<TextQuery::line_no> OrQuery::eval(const TextQuery &file) const 
{
    // virtual calls through the Query handle to get result sets for operands
    set<line_no> right = rhs.eval(file);
    set<line_no> ret = lhs.eval(file);
    ret.insert(right.begin(), right.end());
    return ret;
}


4
0
查看评论

【C++ Primer】文本查询程序再探

textquery.h #ifndef _TEXTQUERY_H #define _TEXTQUERY_H #include #include #include #include #include #include #include #include #include clas...
  • hbtj_1216
  • hbtj_1216
  • 2017-03-05 15:40
  • 334

C++ Primer 第五版 文本查询程序

新手,代码从官网下载的,自己调试,
  • zhyi0802
  • zhyi0802
  • 2014-05-11 20:03
  • 1504

C++ Primer Plus第六版 第十五章 编程练习答案

//第一题 //main.cpp #include "TV.h" int main() { Tv s42; std::cout << "Initial settings for 42\" TV:\n"; s42.settings(...
  • zhaoshu01234
  • zhaoshu01234
  • 2015-12-10 15:31
  • 1139

《C++primer(第五版)》学习之路-第十五章:面向对象程序设计

【 声明:版权所有,转载请标明出处,请勿用于商业用途。  联系信箱:libin493073668@sina.com】 15.1 OOP:概述 1.面向对象程序设计的核心思想是数据抽象,继承和动态绑定。通过使用数据抽象,我们可以将类的接口与实现分离;使用继承,可以...
  • libin1105
  • libin1105
  • 2015-10-02 23:12
  • 1628

C++primer学习:面向对象程序设计(5):再探文本查询程序

这一节初步探讨了如何设计一个继承类体系。为我们前面所写的文本探测程序添加以下功能:(1):可以将查询结果进行|,&,~的运算.运算的优先级按照C++规定的表达式来进行.如Query(“hair”)|Query(“bird”);(2) : 添加一个历史系统,能够查询前面的进行的某个查询.并可以...
  • pp634077956
  • pp634077956
  • 2015-10-30 17:28
  • 315

C++ Primer文本查询程序(TextQuery)的实现(2014.5.24)

详见书的10.6节。      按行查找文件,并且按照顺序进行显示,同时对单词出现的次数进行统计。同一行出现多次,只按照一次进行计算。 1.头文件 #include #include #include #include #include #in...
  • lrj3763292194
  • lrj3763292194
  • 2014-07-01 09:52
  • 467

C++A Text-Query Program Design(文本查询程序设计)

前言       本文内容是基于C++Primer 5th一个文本查询程序。中文版(参见12.3节,第430页),英文版($12.3 p.484)。 我为什么会选择记录这个文章?       因为作者对这个程序进行了很全面的分析(...
  • qq_33850438
  • qq_33850438
  • 2016-10-31 20:30
  • 654

文本查询程序(C++primer5th)

书上的一个比较简单的例题,可以输出文本中单词总共出现的次数,所在的行数及所在行的内容。主要的思路是创建一个vector来分行存储文本,然后将单词及单词出现行数(set)创建一个map。通过查询单词获得其映射的set。set的size为出现的次数,set的元素为出现的行数,通过set元素作为vecto...
  • blubluhao
  • blubluhao
  • 2016-12-05 12:53
  • 460

C++Primer 【笔记】文本查询程序 TextQuery

《c++ primer》容器这一部分有一个综合应用的小程序设计。要求:程序将读取用户指定的任意文本文件,然后允许用户从该文件中查找单词。查询的结果是该单词出现的次数,并列出每次出现所在的行。如果某单词在同一行中多次出现,程序将只显示该行一次。行号按升序显示,即第 7 行应该在第 9 行之前输出,依此...
  • wangbingcsu
  • wangbingcsu
  • 2015-08-14 16:03
  • 400

C++ Primer中文本查询示例Query的实现

最近在看C++ Primer复习C++的语法,看到书中15.9章中的文本查询示例时,觉得设计得非常不错,于是便动手照着实现了一个,修改了很久终于运行成功了,从中也学习到了很多的语法。下面把实现与总结分享给大家
  • zhaoxy2850
  • zhaoxy2850
  • 2014-07-20 19:12
  • 2216
    个人资料
    • 访问:603909次
    • 积分:7743
    • 等级:
    • 排名:第3261名
    • 原创:192篇
    • 转载:6篇
    • 译文:0篇
    • 评论:99条
    博客专栏
    文章分类
    最新评论