| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1239 人关注过本帖, 1 人收藏
标题:【分享学习过程】历时一个月,终于完成了c_primer_3rd书上的这道练习作业, ...
取消只看楼主 加入收藏
laigaoat2005
Rank: 4
等 级:业余侠客
帖 子:388
专家分:226
注 册:2007-4-5
结帖率:88.89%
收藏(1)
已结贴  问题点数:20 回复次数:6 
【分享学习过程】历时一个月,终于完成了c_primer_3rd书上的这道练习作业,完成一个文本查询系统。真的好开心。拿出来分享,也希望对以后学习c primer
    新手学习的过程,学习的感想,熟手如果时间紧,敬请略过
    希望对以后看cprimer 第三版的同志们能有帮助。
    全部临时手打,没有组织思路,想到什么说什么,如有字打错了、思路不清,以后修改。欢迎各位提出各类批评意见,俺真的不会恩将仇报的。俺们知道,批评我是关心我的哦。

    先说作业要求吧:建立一个文本查询系统,从当前目录读入一个文件,然后,使用者能查询某一个单词是否存在于文件中。支持多种查询。可以带括号、And运算符'&&',Or运算符‘||’,Not运算符'!'。例如: 查询1 alice  查询2 ! alice   查询3  alice && emma   查询4    alice || emma   查询5  alice || emma && bird  查询6 alice || ( emma && bird )等等。为简化设计,可做假设: 用户的每一个查询词 及所有符号间都用一个空格间隔。一条查询语句用空格加点表示结束。单独输入点程序结束。

    呵呵,真的历时一个多月,每天除了工作、必要的休息外的所有时间都投入到这个作业上了。终于算是基本完成了c_primer_3rd这道作业。这是我第一次写这么长的代码(不全是我写的,有很多部分代码都借用了书上的,可惜的是书上没有完整的程序,只是说完整的程序在那个什么网上能找到,我去看了看,啊!全英语的,俺相当于初中文化,看不懂,闪人)。以前最多就是一百行吧,次数都不超过2次。一般都是十几二十行。

    回忆这一个月,真难啊。基础差,底子薄,别人可能一看就明白的东西,我要反复看好多次。呵呵,翻开自己用电脑打印的cprimer教材,最多的我画了三个正字(成功读完一次就画一笔)

    个人觉得,最难的就是cprimer中的类派生那些章节。但难的不是知知识有多难,难的是知识的运用。因为,这章是以开发一个文本查询系统的过程,来说明c++类派生机制及其用法,同时还说明了一些基本的理论。要学习这些章节,我们不但要学习C++的语言要素及其“简单”原理(对于我来说真不简单),还要全面理解这个文本查询系统功能、结构、组成、实现……,如果不这样,感觉新手是看不懂的。同时,它也是前面所有知积的综合运用,前面的不十分清楚,这里就要出问题的。(我在处理静态成员相关的内容时就出现了这个问题),要为了学习这书的类派生部分,我反复的看前面的章节,最后,还是重新找了一本简单的 C++教程 学习了上面的类派生部分后,再反过来学习cprimer的类派生部分。
   
    终于是完成了啊。真的好开心。拿出来分享,希望对以后学习c primer 3rd的朋友们有一定的用处。
    当然,程序中肯定还有一些bug,只是现在没有发现。以后发现再修改吧。程序中,我保留了部分bug的调试过程记录,舍不得全删除。我觉得那些调试记录是我学习的过程,是我进步的过程,记录了我写代码时出现的错误及出错的原因,呵呵,就让它保留吧。以后看到时,会反复提醒我在哪些方面要小心。。当然,都是新手的错误,学长们不要见笑
   
    程序还在调试中。作业后面还有作业,还在学习中……   

    全文由七个文件组成。但我给的是八个文件(有一个是用于被查询的文件text.txt)为我测试方便,我在程序中默认打开这个文件(可以修改的)。

    本代码用在c-free5中编译通过,运行基本正常。还有些bug,比如,在and查询时,如果第一行的最后一个词和下一行的第一个词匹配时,程序会运行时错误。这几天忙,空了修改。   

    楼下附上程序代码:



粗心啊,忘了发头文件了;
这里补上。对不起了。
head.h
程序代码:
// 标准库头文件
#include <algorithm>
#include <string>
#include <vector>
#include <utility> 
#include <map>
#include <set>
#include <iterator>
#include <iostream>
#include <fstream>
#include <stack>
// 标准 C 头文件
#include <stddef.h>
#include <ctype.h>
    using namespace std;
// typedefs 使声明更简单
typedef pair<short,short> location;
typedef vector<location> loc; // typedef vector<location> loc;
typedef vector<string> text;
typedef pair<text*,loc*> text_loc;



[ 本帖最后由 laigaoat2005 于 2011-5-26 10:08 编辑 ]
搜索更多相关主题的帖子: alice 时间 
2011-05-22 11:22
laigaoat2005
Rank: 4
等 级:业余侠客
帖 子:388
专家分:226
注 册:2007-4-5
收藏
得分:0 
main.cpp
程序代码:
// BUG    记录,运行and运算时,如果第一行的末词和第二行的首词 查询,会运行错误。
#include "head.h"
#include "TextQuery.h"
#include "Query.h"
#include "UserQuery.h"


#include "query.cpp"
#include "TextQuery.cpp"
#include "UserQuery.cpp"


int main()
{
    TextQuery tq;
    tq.build_text_map();
    //tq.display_map_text();
    tq.query_text();
     return 0;
} 




Query.h
程序代码:
//BUG 修正记录。因 基类的私有构造函数(专由NameQuery调用的构造函数。)未初始化 左右括号数,导致程序在打印结果时出错。现在已经添加了默认值0,执行正常。 

//比较函数对象
class less_than_pair
{
public:
    bool operator()(location loc1,location loc2)
    {
        return  (
                    (loc1.first<loc2.first) || (loc1.first==loc2.first)
                    &&(loc1.second <loc2.second)       
                 );
    }
} ;

//抽象基类
class Query{
    friend class NameQuery;
public:
    virtual void eval()=0;//纯虚函数 
    virtual Query* clone()=0;// 纯虚函数  代理 new操作符
    virtual ostream& print(ostream& os=cout)const=0;
    virtual void add_op(Query*)=0; //添加操作数
    virtual ~Query(){delete _solution;}
    void display()const;  //显示查询结果
    const set <short>* solution();   //读取_solution
    const loc * locations() const{    return & _loc;    }  // 读取_loc
    void lparentheses(short lp){ _lparentheses=lp; }
    void rparentheses(short rp){ _rparentheses=rp; }
    short lparentheses(){ return _lparentheses; }
    short rparentheses(){ return _rparentheses; }
    void print_lparentheses(short cnt,ostream& os)const;//打印左括号
    void print_rparentheses(short cnt,ostream& os)const;//打印右括号
    static const vector<string> *text_file(){ return _text_file; }
protected:
    //默认构造函数
    Query():_solution(0),_lparentheses(0),_rparentheses(0){}
   
    //拷贝构造函数
    Query(const Query& rhs):_solution(0),_loc(rhs._loc),
                 _lparentheses(rhs._lparentheses),_rparentheses(rhs._rparentheses){
    }
    //重载=   拷贝赋值操作符
    Query& operator=(const Query&);
    //根据查出的行列位置对计算唯一行结果集 (未定义)
    set<short>* _vec2set(const vector <location>*);   
    short _lparentheses; //左括号数   构造函数未初始化
    short _rparentheses; //右括号数   构造函数未初始化
    static vector <string>* _text_file;  //以行为单位存贮的文本文件
protected:
    set <short>* _solution;    // 唯一行结果集合    对于NotQuery应该是没有出现的行。应该用所有行减去出现的行。
    vector<location> _loc;     // 所查对象的行列位置对向量
private:
    //专属NameQuery类调用的构造函数
    Query(const loc & rel_loc ):_lparentheses(0),_rparentheses(0),_solution(0),_loc(rel_loc){}

};



//NameQuery类
class NameQuery:public Query{
public:
    //默认构造函数
    explicit NameQuery(const string& name):_name(name){}
    NameQuery(const string& name, loc* ploc ):Query(*ploc),_name(name){}
    virtual void eval();   //改写eval虚函数
    virtual NameQuery* clone()
    {
        //cout<<"踪virtual NameQuery clone()开始\n";
        return new NameQuery(*this); // 未定义显示的拷贝构造函数,就按成员初始化
        //转先执行Query拷贝构造函数
        //cout<<"踪virtual NameQuery clone()结束\n";       
    }
    virtual ostream& print(ostream&)const; //改写print函数 未定义
    virtual void add_op(Query*){}         //NameQuery 不用添加操作数,所以,这里定义为空函数。
    string name() const { return _name;    }  //读单词
    static const map<string,loc*> *word_map(){return _word_map;}//读单词位置映射表
protected:
    string _name;      //所查单词。
    static map<string,loc*> * _word_map; //单词位置映射表
private:
};



//NotQuery
class NotQuery:public Query
{
public:
    //默认构造函数
    NotQuery(Query* not_op):_op(not_op){}
    //因为后面的UserQuery类要求 定义一个不完整的查询对象,所以这里添加一个构造函数。
    //**********
    NotQuery():Query()//调用基类构造函数
    {
        _op=0;//构造操作数。因为是定义不完整的操作数,所以,这里把操作数指针定义为0
    }
   
    //拷贝构造函数
    NotQuery(const NotQuery& rhs):Query(rhs)
    {
        //cout<<"踪Not拷贝\n";//ok,正常执行
        //日得美哦,下面这句有错的嘛,都改好了。原来的错误语句是rhs._op->clone().根本没有构造到_op. 
        _op = rhs._op->clone();   //证实无错,错误在于本类的析构函数delete _op;
        //分析:上行应该是调用 NameQuery的clone();转其分析        
        //cout << "踪Not拷贝结束\n";    
    }
    virtual ~NotQuery()
    {
        delete _op;
    }
    //重载= 拷贝赋值操作符
    NotQuery& operator=(const NotQuery&);
    virtual void eval();
   
    //下行书上是后面的代码,但有运行时错误。 virtual NotQuery* clone(){    return new NotQuery(*this);    }
    virtual NotQuery* clone();//{    return new NotQuery(*this);    }
    virtual void add_op(Query*);
    virtual ostream& print(ostream&)const;
    const Query* op()const{    return _op;    }
    static const loc* all_locs(){    return _all_locs;    }
    //自己添加的静态成员函数
    static void all_locs(loc*);
protected:
    Query* _op;
    static const loc* _all_locs;
private:   
   
};

//OrQuery
class OrQuery:public Query
{
public:
    //默认构造函数
    OrQuery(Query* lop,Query* rop):_left_op(lop),_right_op(rop){}
    //为了构造不完整的查询(只有左操作数)
    OrQuery(Query* lop):_left_op(lop),_right_op(0){}
    //拷贝构造函数
    OrQuery(const OrQuery& rhs):Query(rhs){ _left_op = rhs._left_op->clone();_right_op = rhs._right_op->clone(); }
    //重载=  拷贝赋值操作符
    OrQuery& operator=(const OrQuery&);
    virtual ~OrQuery(){delete _left_op; delete _right_op;}
    virtual void eval();
    virtual OrQuery* clone(){    return new OrQuery(*this);    }
    virtual void add_op(Query*);
    virtual ostream& print(ostream&)const;
    const Query* left_op()const{    return _left_op;    }
    const Query* right_op()const{    return _right_op;    }
protected:
    Query* _left_op;
    Query* _right_op;
private:   
   
};


//AndQuery
class AndQuery:public Query
{
public:
    //构造函数
    AndQuery(Query* lop, Query* rop):_left_op(lop),_right_op(rop){}
   
    //下面的构造函数是为了构造不完成的查询(只有左操作数)
    AndQuery(Query* lop):_left_op(lop),_right_op(0){}
   
    //拷贝构造函数
    AndQuery(const AndQuery& rhs):Query(rhs){ _left_op = rhs._left_op->clone();_right_op = rhs._right_op->clone(); }
    //拷贝赋值操作符
    AndQuery& operator=(const AndQuery&);
    virtual ~AndQuery(){delete _left_op;delete _right_op;}
    virtual void eval();
    virtual AndQuery* clone(){    return new AndQuery(*this);    }
    virtual void add_op(Query*);
    virtual ostream& print(ostream&)const;
    const Query* left_op()  const{    return _left_op;    }//访问左操作数
    const Query* right_op() const{    return _right_op;    } //访问右操作数
    static void max_col(const vector<int>*pcol){ if(!_max_col) _max_col=pcol;}//设置每一行的最大列vector
protected:
    Query* _left_op;  // 左操作数
    Query* _right_op;  //右操作数
    static const vector<int>* _max_col; //每一行的最大列数
};


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



Query.cpp
程序代码:
inline const set<short>* Query:: solution()
{
    return _solution ? _solution : _solution=_vec2set(&_loc);
}
inline void Query::print_lparentheses(short cnt,ostream &os)const
{
    for (int i=0;i<cnt;i++)
        os<<"(";
}
inline void Query::print_rparentheses(short cnt,ostream& os)const
{
    for (int i=0;i<cnt;i++)
        os<<")";   
}

set<short>* Query:: _vec2set(const loc* ploc)
{
    set<short>*p_set=new set<short>;
    loc::const_iterator iter=ploc->begin(),iter_end=ploc->end();
    while( iter != iter_end )
    {
        p_set->insert((*iter).first); //按顺序插入行号到set
        iter++;
    }
    //下面对p_set排序           呵呵,早就排序好了。
    //set<short>::iterator s_iter=p_set->begin(),s_iter_end=p_set->end();
    //sort(s_iter,s_iter_end) ;//对p_set排序   
    //sort(p_set->begin(),p_set->end());
    //经测试,发现set是自动排序的。用了sort算法就会出错。也就是说,sort()算法不能用于set
    return p_set; //这里用局部变量。如果不是抽象基类调用,用完了应该delete防止内存泄露
}

inline Query& Query::operator=(const Query& rhs)
{
    if( this != &rhs )//防止自我赋值
    {
        _loc=rhs._loc;
        delete _solution;
        _solution=0;
    }
    return *this;
}





inline ostream& NameQuery::print(ostream& os)const
{
    if(_lparentheses) print_lparentheses(_lparentheses,os);
    os << _name;
    if(_rparentheses) print_rparentheses(_rparentheses,os);
    return os;   
}

void NameQuery::eval(){}//查询工作在构建单词map时已经完成。在构造NameQuery时已经初初始化 


//程序完成到一定程度时应该进行正确的初始化。 现在开始设计正确的初始化  应该是下面这样了。
//const loc* NotQuery:: _all_locs=0;    //_all_locs 是指向const对象的指针。不能改变其值 

/********************************************************************************************
void NotQuery::all_locs(loc* all_loc)
{
    loc* _all_locs = new loc(*all_loc); //用接受到的loc指针所指的对象来初始化_all_locs
}

***********************************************************************/
//下面只是为了语义正确进行的虚拟初始化,
const loc* NotQuery:: _all_locs = new loc;
void NotQuery::all_locs(loc* p_loc)
{
    _all_locs = new loc(*p_loc);
}


inline ostream& NotQuery::print(ostream& os)const
{
    os<<"! ";
    if(_lparentheses) print_lparentheses(_lparentheses,os);
    _op->print(os);
    if(_rparentheses) print_rparentheses(_rparentheses,os);
    return os;
}

void NotQuery::eval()
{
    _op->eval();
    loc::const_iterator iter=_all_locs->begin(),iter_end=_all_locs->end();     //
     set<short>*ps = _vec2set(_op->locations()) ;//用完了应该delete防止内存泄露
     while(iter!=iter_end)
    {
         if ( 0 == ps->count(iter->first) )   //也可以写成  ( ! ps->count(iter->first) )
         {
            _loc.push_back(*iter);   
        }
        iter++;
     }
     delete ps;
}
inline NotQuery* NotQuery:: clone()
{   
    return new NotQuery(*this);   
}
inline NotQuery& NotQuery::operator=(const NotQuery& rhs)
{
    if(this != &rhs)
    {
        //调用基类赋拷贝值操作符
        this->Query::operator=(rhs);
        //下面有运行时错误
        _op = rhs._op->clone();
    }
    return *this;
}




//虚拟add_op操作,未正式定义
void NotQuery:: add_op(Query* addop)
{
    _op=addop->clone();           //后续添加操作数。
} 

inline ostream& OrQuery::print(ostream& os)const
{
    if(_lparentheses) print_lparentheses(_lparentheses,os);
    _left_op->print(os);
    os<<" || ";
    _right_op->print(os);
    if(_rparentheses) print_rparentheses(_rparentheses,os);
    return os;
}

void OrQuery::eval()
{
    _left_op->eval();
    _right_op->eval();
    loc::const_iterator left_iter=_left_op->locations()->begin(),
                       left_iter_end=_left_op->locations()->end(),
                       right_iter=_right_op->locations()->begin(),
                       right_iter_end=_right_op->locations()->end();
    merge(        left_iter,left_iter_end,right_iter,right_iter_end,
                inserter(_loc,_loc.begin()),less_than_pair()
            );
} 

//虚拟Add_op操作,未正式定义
void OrQuery:: add_op(Query* addop)
{
    _right_op =  addop->clone();         //添加右操作数
}

inline OrQuery& OrQuery:: operator=(const OrQuery& rhs)
{
    if( &rhs != this)//禁止自我赋值
    {
        this->Query::operator=(rhs);
        _left_op = rhs._left_op->clone();
        _right_op = rhs._left_op->clone();
    }
    return *this;
}


//下面只是为了语言意义正确而设置的静态初始化
/*************************************************************************************************/
const vector<int>* AndQuery:: _max_col = new vector<int>;

inline ostream& AndQuery::print(ostream& os)const
{
    if(_lparentheses) print_lparentheses(_lparentheses,os);   
    _left_op->print(os);
    os<<" && ";
    _right_op->print(os);   
    if(_rparentheses) print_rparentheses(_rparentheses,os);
    return os;
}

void AndQuery::eval()
{
    _left_op->eval();
    _right_op->eval();
    loc::const_iterator left_iter=_left_op->locations()->begin(),
                       left_iter_end=_left_op->locations()->end(),
                       right_iter=_right_op->locations()->begin(),
                       right_iter_end=_right_op->locations()->end();
    while(    left_iter!=left_iter_end  && right_iter!=right_iter_end    )   
    {
       
        while(  (left_iter->first) > (right_iter->first)  )
        {
            right_iter++;
            if(right_iter==right_iter_end)
                return;           
        }
       
        while(  (*left_iter).first < (*right_iter).first  )
        {
            if(      (  (left_iter->first+1) == (right_iter->first)  )
                 &&  (   0 == right_iter->second   )
                 &&  (  left_iter->second == (*_max_col)[left_iter->first]  )      
               )
            {
                _loc.push_back(*left_iter);
                //left_iter++; //为什么这里不后移left_iter?
                _loc.push_back(*right_iter);
                right_iter++;
                if( right_iter == right_iter_end )
                    return;
            }
            ++left_iter;
            if(left_iter == left_iter_end)
                return;
        }
       
        while(    left_iter->first  ==  right_iter->first    )
        {
            if(    left_iter->second+1 == right_iter->second    )
            {
                _loc.push_back(*left_iter);
                left_iter++;
                _loc.push_back(*right_iter);
                right_iter++;
            }
            else
            {
                if(   left_iter->second  <=  right_iter->second    )
                    left_iter++;
                else
                    right_iter++;
                if (  left_iter==left_iter_end   ||  right_iter==right_iter_end   )
                    return;
            }
        }
       
    }
}

//虚拟add_op操作
void AndQuery:: add_op(Query* addop)
{
    _right_op = addop->clone();    //添加右操作数
}
inline AndQuery& AndQuery::operator=(const AndQuery& rhs)
{
    if ( this != &rhs )
    {
        this->Query::operator=(rhs);
        _left_op = rhs._left_op->clone();
        _right_op = rhs._right_op->clone();       
    }
    return *this;
}



TextQuery.h
程序代码:
class TextQuery {
public:
    //将this所指向的某一块内存中的每个字节的内容全部设置为ASCII值0, 块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向S的指针。
    TextQuery() {    memset( this, 0, sizeof( TextQuery ));     }
    ~TextQuery(){    delete _line_cnt;    }
    static void filter_elements( string felems ) { filt_elems = felems; }
    void query_text();
    void display_map_text();
    void display_text_locations();
    void display_solution();
    void build_text_map()//// 原来 的 doit()
    {
        retrieve_text();
        separate_words();
        filter_text();
        suffix_text();
        strip_caps();
        build_word_map();
        //all_locs();
    }
    static void line_cnt(text_loc*);   //为了设置AndQuery静态成员,所有单词的最大列数 的静态成员函数
private:
    void retrieve_text();
    void separate_words();
    void filter_text();
    void strip_caps();
    void suffix_text();
    void suffix_s( string& );
    void build_word_map();
private:
    vector<string> *lines_of_text;
    text_loc *text_locations;       //所有单词和所有单词的行列位置  typedef pair<text*,loc*> text_loc;
    map< string,loc*> *word_map;
    static const vector<int>* _line_cnt; //为了AndQuery准备的静态成员 所有单词的最大列数
    static string filt_elems;
    Query* query;   //为了 TextQuery.cpp中的一条语句  query->eval();   !!!!1而加了数据成员。构造函数中还没有涉及。
};







 

[ 本帖最后由 laigaoat2005 于 2011-5-22 11:34 编辑 ]
2011-05-22 11:32
laigaoat2005
Rank: 4
等 级:业余侠客
帖 子:388
专家分:226
注 册:2007-4-5
收藏
得分:0 
TextQuery.cpp
程序代码:
//BUG疑问: 1 还没有初始化 Query中的静态变量   static vector <string>* _text_file ;
// //BUG:      // 现在定义了_line_cnt,但是动态分配的。不知道delete了没有。把括号问题解决了再看看看。  



//查询入口
void TextQuery::query_text()
{
    string text;                                     //局部变量:text: 按顺序存放查询中的每个单词
    string caps( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );     //局部变量:caps: 支持 "把大写转换为小写" 的过滤器
    vector<string> _query_text;                      //局部变量:query_text: 保存用户查询的 vector
    UserQuery user_query;                           //局部变量:user_query : UserQuery 对象, 封装了用户查询的实际计算过程
   
    // 初始化 UserQuery 的静态数据成员
    NotQuery::all_locs( text_locations->second ); 
    // 现在定义了_line_cnt,但是动态分配的。不知道delete了没有。把括号问题解决了再看看看。
    AndQuery::max_col( _line_cnt ); //line_cnt未定义。它是一个vector<int>对象。代表所有单词的每一行的最大列数。应该在textquery中。
    UserQuery::word_map( word_map );
   
   
    do
    {
        // 如果有的话, 删除以前的查询
        _query_text.clear();
        cout << "请输入一条查询,每个单词或符号用空格间隔,并用点'.'做为查询语句的结束\n如果要结束程序,请输入一个单独的点\n\n "
        << "输入查询语句==> ";
        //     * 从标准输入获取查询,     * 删除所有的大写字母     * 大量输入 query_text ...     * 注意: 应该完成用户查询的所有处理     */
        while( cin >> text )
        {
            if ( text == "." )
            break;
            string::size_type pos = 0;
            while (( pos = text.find_first_of( caps, pos ))
            != string::npos )
            text[pos] = tolower( text[pos] );
            _query_text.push_back( text );
        }
        // ok: 如果有查询, 处理它...
        if ( ! _query_text.empty() )
        {        
            // 把查询传递给 UserQuery 对象
            user_query.query( &_query_text );
       
            // 计算 UserQuery
            // 返回 Query* 层次结构
            // 17.7 节描述了这一点
            // query 是 TextQuery 的 Query* 成员
           
            //多了括号 从这里就开始了。               
            query = user_query.eval_query();
    
            //cout << *query << endl;
           
            // 计算 Query 层次结构    
            query->eval();       
            // ok: 显示结果
            // 一个 TextQuery 成员函数
            display_solution();            
            // 在用户终端上给出额外一行
            cout << endl;
        }
    }
    while ( ! _query_text.empty() );
    cout << "Ok, bye!\n";
} 


string TextQuery::filt_elems( "\",.;:!<<)(\\/" );
const vector<int>* TextQuery::_line_cnt = new vector<int>();



void TextQuery::line_cnt(text_loc*  words_and_locs) //为了设置AndQuery静态成员,所有单词的最大列数 的静态成员函数
{
    //typedef pair<text*,loc*> text_loc;
    //typedef vector<location> loc;
    loc*  p_locs=words_and_locs->second;//获取所有单词的行列位置
    loc::iterator iter=p_locs->begin(),iter_end=p_locs->end();
    vector<int> line_cnt_temp;
    while(iter != iter_end)
    {
        line_cnt_temp.push_back((*iter).second);
        iter++;
    }
    _line_cnt = new vector<int> (line_cnt_temp.begin(),line_cnt_temp.end());
}


void TextQuery:: retrieve_text()
{
    //程序自动打开处理文件 text.txt
    string file_name("text.txt");
    //cout << "please enter file name: ";
    //cin >> file_name;
   
    ifstream infile( file_name.c_str(), ios::in );
    if ( !infile )
    {
        cerr << "oops! unable to open file "
        << file_name << " -- bailing out!\n";
        exit( - 1 );
    }
    else cout << "\n";
    lines_of_text = new vector<string>;
    string textline;
    while ( getline( infile, textline, '\n' ))
    lines_of_text->push_back( textline );
}

void     TextQuery::     separate_words()
{
    vector<string> *words = new vector<string>;
    vector<location> *locations =
    new vector<location>;
   
    for ( short line_pos = 0; line_pos < lines_of_text->size();
    line_pos++ )
    {
        short word_pos = 0;
        string textline = (*lines_of_text)[ line_pos ];
        string::size_type eol = textline.length();
        string::size_type pos = 0, prev_pos = 0;
        while (( pos = textline.find_first_of( ' ', pos ))
        != string::npos )
        {
            words->push_back(
            textline.substr( prev_pos, pos - prev_pos ));
            locations->push_back(
            make_pair( line_pos, word_pos ));
            word_pos++; pos++; prev_pos = pos;
        }
        words->push_back(
        textline.substr( prev_pos, pos - prev_pos ));
        locations ->push_back(make_pair(line_pos,word_pos));
    }
    text_locations = new text_loc( words, locations );
}

void TextQuery:: filter_text()
{
    if ( filt_elems.empty() )
    return;
    vector<string> *words = text_locations ->first;
   
    vector<string>::iterator iter = words ->begin();
    vector<string>::iterator iter_end = words ->end();
   
    while ( iter != iter_end )
    {
        string::size_type pos = 0;
        while (( pos = (*iter).find_first_of( filt_elems, pos ))
        != string::npos )
        (*iter).erase(pos,1);
        ++iter;
    }
}

void TextQuery:: suffix_text()
{
    vector<string> *words = text_locations ->first; 
    vector<string>::iterator iter = words ->begin();
    vector<string>::iterator iter_end = words ->end(); 
    while ( iter != iter_end )
    {
        if ( (*iter).size() <= 3 )
        {
            iter++;
            continue;
        }
        if ( (*iter)[ (*iter).size()- 1 ] == 's' )
        suffix_s( *iter );        
        // 其他的后缀处理放在这里
        iter++;
    }
} 

void TextQuery:: suffix_s( string &word )
{
    string::size_type spos = 0;
    string::size_type pos3 = word.size()- 3;
    // "ous", "ss", "is", "ius"
    string suffixes( "oussisius" );
    if ( ! ( pos3, 3, suffixes, spos, 3) ||
    ! ( pos3, 3, suffixes, spos+6, 3 ) ||
    ! ( pos3+1, 2, suffixes, spos+2, 2 ) ||
    ! ( pos3+1, 2, suffixes, spos+4, 2 ))
    return;
    string ies( "ies" );
    if ( ! ( pos3, 3, ies ))
    {
        word.replace( pos3, 3, 1, 'y' );
        return;
    }
    string ses( "ses" );
    if ( ! ( pos3, 3, ses ))
    {
    word.erase( pos3+1, 2 );
    return;
    }    
    // 去掉尾部的 's'
    word.erase( pos3+2 );    
    // watch out for "'s"
    if ( word[ pos3+1 ] == '\'' )
    word.erase( pos3+1 );
}

void TextQuery:: strip_caps()
{
    vector<string> *words = text_locations ->first;
   
    vector<string>::iterator iter = words ->begin();
    vector<string>::iterator iter_end = words ->end();
    string caps( "ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
    while ( iter != iter_end )
    {
        string::size_type pos = 0;
        while (( pos = (*iter).find_first_of( caps, pos ))     != string::npos )
        (*iter)[ pos ] = tolower( (*iter)[pos] );
        ++iter;
    }
}

void TextQuery:: build_word_map()
{
    word_map = new map< string, loc*>;    
    typedef map<string,loc*>::value_type value_type;    
    typedef set<string>::difference_type diff_type;    
    set<string> exclusion_set;
    ifstream infile( "exclusion_set" );    
    if ( !infile )
    {
        static string default_excluded_words[25] = {
        "the","and","but","that","then","are","been",
        "can","can't","cannot","could","did","for",
        "had","have","him","his","her","its","into",
        "were","which","when","with","would" };
        cerr << "warning! unable to open word exclusion file! -- "
        << "using default set\n";
        copy( default_excluded_words, default_excluded_words+25,
        inserter( exclusion_set, exclusion_set.begin() ));
    }
    else
    {
        istream_iterator< string>
        input_set( infile ), eos;
        copy( input_set, eos,
        inserter( exclusion_set, exclusion_set.begin() ));
    }    
    // 遍历单词, 输入键/值对
    vector<string> *text_words = text_locations ->first;
    vector<location> *text_locs = text_locations ->second;    
    register int elem_cnt = text_words ->size();
    for ( int ix = 0; ix < elem_cnt; ++ix )
    {
        string textword = ( *text_words )[ ix ];
        if ( textword.size() < 3 || exclusion_set.count( textword ))
            continue;
        if ( ! word_map->count((*text_words)[ix] ))
        { // 没有, 添加:
            loc *ploc = new vector<location>;
            ploc->push_back( (*text_locs)[ix] );
            word_map->insert( value_type( (*text_words)[ix], ploc ));
        }
        else (*word_map)[(*text_words)[ix]]->
        push_back( (*text_locs)[ix] );
    }
}

 


void TextQuery:: display_map_text()
{
    typedef map<string,loc*> map_text;
    map_text::iterator iter = word_map->begin(),
    iter_end = word_map->end();
    while ( iter != iter_end )
    {
        cout << "word: " << (*iter).first << " (";
        int loc_cnt = 0;
        loc *text_locs = (*iter).second;    
        loc::iterator liter = text_locs->begin(),
        liter_end = text_locs->end();    
        while ( liter != liter_end )
        {
            if ( loc_cnt )
                cout << ",";
            else ++loc_cnt;        
            cout << "(" << (*liter).first << "," << (*liter).second << ")";
            ++liter;
        }
        cout << ")\n";
        ++iter;
    }    
    cout << endl;
}

void TextQuery:: display_text_locations()
{
    vector<string> *text_words = text_locations ->first;
    vector<location> *text_locs = text_locations ->second;    
    register int elem_cnt = text_words ->size();    
    if ( elem_cnt != text_locs->size() )
    {
        cerr << "oops! internal error: word and position vectors "
        << "are of unequal size \n"
        << "words: " << elem_cnt << " "
        << "locs: " << text_locs->size()
        << " -- bailing out!\n";
        exit( - 2 );
    }
   
    for ( int ix = 0; ix < elem_cnt; ix++ )
    {
        cout << "word: " << (*text_words)[ ix ] << "\t"
        << "location: ("
        << (*text_locs)[ix].first << ","
        << (*text_locs)[ix].second << ")"
        << "\n";
    }
    cout << endl;
}


void TextQuery:: display_solution()
{
      cout << "\n"
    << "Requested query: "
    //下面的查询语句为什么多了个右括号?
    << *query << "\n\n";
     //cout << "跟踪gggg" << endl;    /**********************************************************************************/
     const set<short> *solution = query->solution();
      if ( ! solution->size() )
    {
    cout << "\n\tSorry, "
          << " no matching lines were found in text.\n"
        << endl;
      return;
     }

     set<short>::const_iterator
    it = solution->begin(),
    end_it = solution->end();

      for ( ; it != end_it; ++it )
    {
    int line = *it;
      // 文本行从 0 开始 别把用户弄糊涂了 ...
    cout << "( " << line+1 << " ) "
          << (*lines_of_text)[line] << '\n';
    }
      cout << endl;
} 



UserQuery.h
程序代码:
//#ifndef USER_QUERY_H
//#define USER_QUERY_H


class UserQuery
{
public: 

    UserQuery( vector< string > *pquery = 0 ):_query( pquery ),_eval( 0 ),_paren( 0 ){} //构造函数
    void query( vector< string > *pq ); //接收传递用户查询字串向量 地址
    void displayQuery();       //显示查询    
   
    Query *eval_query();   // 建立层次结构    
   
    static void word_map( map<string,loc*> *pwm ) {/* if ( !_word_map )*/ _word_map = pwm; } //设置map
   
private:
    enum QueryType { WORD = 1, AND, OR, NOT, RPAREN, LPAREN };     //定义 枚举类型名 QueryType 
   
    QueryType  evalQueryString( const string &query );         //声明一个函数,用于 计算 查询字串中每一个字串的枚举类型 
   
   
   
    void  evalWord( const string &query );        
    void  evalNot();    
    void  evalOr();
    void  evalAnd();
    void  evalRParen();
   
    bool  integrity_check();     

    vector<string> *_query; //实际的用户查询 字串向量   
       
    int  _paren;            //帮助我们改变操作符计算的缺省优先级
    Query  *_eval;          //指向在 eval_query()中建立起来的查询层次表示

    stack<Query*,vector<Query*> > _query_stack; //存放复合查询中的完整操作数(我们放置 NameQuery对象的地方)
    stack<Query*,vector<Query*> > _current_op;     //存放缺少右操作数的不完整操作符,即:当前要完成的操作
    static short _lparenOn, _rparenOn; //记录了与当前查询节点相关联的括号的种类和数目
    static map<string,loc*> *_word_map;
}; 

// #endif
UserQuery.cpp
程序代码:
//BUG 1   
//下面的函数有问题。查询语句多了个括号。
// 跟踪发现在双参数构造函数构造的namequery多了一个右括号 


//定义static 变量  左右括号数 
short UserQuery::_lparenOn = 0;
short UserQuery::_rparenOn = 0;
//定义 static 变量  new map
map<string,loc*> * UserQuery::_word_map=new map<string,loc*>();


//下面的函数有问题。查询语句多了个括号。
inline void UserQuery:: evalWord( const string &query )
{
    NameQuery *pq; //定义一个NameQuery指针
    loc *ploc;      //定义一个  vector<  pair< short, short >  > 指针  typedef vector<location> loc;
    /************      /检测_word_map是否为空 ,
    map<string,loc*>::iterator it = _word_map->begin(),it_end=_word_map->end();
    while  ( it != it_end )
    {
        cout << it->first << ":" << it->second << endl;
        it++;
    }
    //*/   
    if ( ! _word_map->count( query ))  //如果map中不存在当前单词
        pq = new NameQuery( query );      //用单参数构造函数  建立一个当前单词的 NameQuery 并由pq指向它
    else                             //如果map中 存在当前单词
    { 
        //构造函数可能有问题。
        ploc = ( *_word_map )[ query ];      //则让 ploc指向 map中的当前单词的 位置vector (vector< pair<short,short> > )
        //这里构造时是不是多了个括号?
        pq = new NameQuery( query, ploc );   //用双参数构造函数   用当前单词的位置vector 新建一个NameQuery
        //下面开始检测pq指向的NameQuery
        /*cout << "<< pq->name()" << pq->name() << "\n"
             << "pq->lparentheses()" << pq->lparentheses() << "\n"
             << "pq->rparentheses()" << pq->rparentheses() << "\n"
             << "pq->solution()" << pq->solution() << "\n"            
             << endl;
     检测出结果:专由NameQuery调用的基类构造函数未初始化左右括号数。已经修正。
         //*/
    }
   
    if ( _current_op.size() <= _paren )
    {
        _query_stack.push( pq );        
    }
    else
    {
        Query *pop = _current_op.top();
        _current_op.pop();
        pop->add_op( pq );
        _query_stack.push( pop );
    }
    

} 






inline void UserQuery:: evalAnd()
{
  Query *pop = _query_stack.top(); _query_stack.pop();
  AndQuery *pq = new AndQuery( pop );

  if ( _lparenOn )
    { pq->lparentheses( _lparenOn ); _lparenOn = 0; }

  if ( _rparenOn )
    { pq->rparentheses( _rparenOn ); _rparenOn = 0; }

  _current_op.push( pq );
} 


inline void UserQuery:: evalOr()
{
  Query *pop = _query_stack.top(); _query_stack.pop();
  OrQuery *pq = new OrQuery( pop );

  if ( _lparenOn )
    { pq->lparentheses( _lparenOn ); _lparenOn = 0; }

  if ( _rparenOn )
    { pq->rparentheses( _rparenOn ); _rparenOn = 0; }

  _current_op.push( pq );
} 


inline void UserQuery:: evalNot()
{
  NotQuery *pq = new NotQuery;
  if ( _lparenOn )
    { pq->lparentheses( _lparenOn ); _lparenOn = 0; }

  if ( _rparenOn )
    { pq->rparentheses( _rparenOn ); _rparenOn = 0; }
  _current_op.push( pq );
} 

inline void UserQuery:: evalRParen()
{
    if ( _paren < _current_op.size() )
    {
        Query *poperand = _query_stack.top();
        _query_stack.pop();
        Query *pop = _current_op.top();
        _current_op.pop();
        pop->add_op( poperand );
        _query_stack.push( pop );
    }
}

//计算返回 字串枚举类型
inline UserQuery::QueryType UserQuery::evalQueryString(const string& q_str)
{
    QueryType the_type = WORD;
    if( "(" == q_str    ) the_type = LPAREN;
    if(    ")" == q_str    ) the_type = RPAREN;   
    if(    "||"== q_str    ) the_type = OR;
    if(    "&&"== q_str    ) the_type = AND;
    if(    "!" == q_str    ) the_type = NOT;   
    return the_type;
} 


Query* UserQuery::eval_query()
{   
    vector<string >::iterator it = _query->begin(),end_it = _query->end(); 
    for ( ; it != end_it; ++it ) //迭代访问查询中的 每一个字串
    {   
        switch(      evalQueryString( *it )     )
        {
            case WORD:
            evalWord( *it ); //带一个string参数 
            break;
           
            case AND:
            evalAnd();
            break;
           
            case OR:
            evalOr();
            break;
           
            case NOT:
            evalNot();
            break;
           
            case LPAREN:
            ++_paren;
            ++_lparenOn;
            break;
           
            case RPAREN:
            --_paren;
            ++_rparenOn;
            evalRParen();
            break;
        }
    }
    return _query_stack.top() ;
}

void UserQuery::query( vector< string > *pq )
{
    delete _query;
    _query = new vector< string >(*pq);
}



还有一个记事本文件,用来被查询的。

text.txt

Alice Emma has long flowing red hair. Her Daddy says
when the wind blows through her hair, it looks almost alive,
like a fiery bird in flight. A beautiful fiery bird, he tells her,
magical but untamed. "Daddy, shush, there is no such thing,"
she tells him, at the same time wanting him to tell her more.
Shyly, she asks, "I mean, Daddy, is there?"




2011-05-22 11:37
laigaoat2005
Rank: 4
等 级:业余侠客
帖 子:388
专家分:226
注 册:2007-4-5
收藏
得分:0 
呵呵,终于发完了。重发了好多次。说超过字数。
哎,今天 终于可以给自己放一会假了。昨天调试了15小时,到晚上十二点半才调出来……现在感觉真辛苦
2011-05-22 11:41
laigaoat2005
Rank: 4
等 级:业余侠客
帖 子:388
专家分:226
注 册:2007-4-5
收藏
得分:0 
谢谢。一起进步吧。
2011-05-22 20:33
laigaoat2005
Rank: 4
等 级:业余侠客
帖 子:388
专家分:226
注 册:2007-4-5
收藏
得分:0 
回11楼
头文件如何包含?head.h
呵呵,为了简单,我建立了一个 head.h 文件,里面全是 #include 系列,包含了我所有要用的头文件
2011-05-26 09:55
laigaoat2005
Rank: 4
等 级:业余侠客
帖 子:388
专家分:226
注 册:2007-4-5
收藏
得分:0 
回13楼:
在什么环境下运行的啊,是win32吗
我对什么环境的概念还不太清楚。我还没有学其它好多东西,所以我只能说,我用C free5.0编译通过,运行“基本”正常。感觉应该是win32吧。
2011-05-26 09:58
快速回复:【分享学习过程】历时一个月,终于完成了c_primer_3rd书上的这道练习作 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.067951 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved