C++Primer第五版 12.1.6节练习

练习12.19:定义你自己版本的StrBlobPtr,更新StrBlob类,加入恰当的friend声明及begin和end成员。

/*
*练习12.19 
*2016/1/22
*问题描述:
练习12.19:定义你自己版本的StrBlobPtr,更新StrBlob类,加入恰当的friend声明及

begin和end成员。 
*参考:http://blog.csdn.net/sunhero2010/article/details/49882993 
*作者:Nick Feng
*邮箱:nickgreen23@163.com 
*/ 

/*
*练习12.7 
*2015/11/2
*问题描述:
练习12.7:重做上一题,这次使用shared_ptr而不是内置指针。
练习12.6:编写函数,返回一个动态分配的int的vector。将此vector传递给另一个函数

,这个函数读取标准输入,将读入的值保存在vector元素中。再将vector
传递给另一个函数,打印读入的值。记得在恰当的时刻delete vector。 
*说明:指针学习 fun(),fun2(),fun3() 分别实现三个函数的要求 ,和12.7不一样的

地方在于,只能指针的内存管理不要你烦了 
*作者:Nick Feng
*邮箱:nickgreen23@163.com 
*/ 
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <fstream>
using namespace std;

class StrBlobPtr;

class StrBlob{
    friend class StrBlobPtr;
public:

    typedef std::vector<std::string>::size_type size_type;
    StrBlob();
    StrBlob(std::initializer_list<std::string> il);
    size_type size() const { return data->size();}
    bool empty() const { return data->empty();}
    void push_back(const std::string &t) { data->push_back(t);}
    void pop_back();
    const std::string& front();
    const std::string& back();

    StrBlobPtr begin();
    StrBlobPtr end();
private:
    std::shared_ptr<std::vector<std::string>> data;
    void check(size_type i, const std::string &msg) const;
};

StrBlob::StrBlob() : data(make_shared<vector<string>>()) { }

StrBlob::StrBlob(initializer_list<string> il) : data

(make_shared<vector<string>>(il)){ }

void StrBlob::check(size_type i, const string &msg) const
{
    if(i >= data->size())
        throw out_of_range(msg);
}

const string& StrBlob::front()
{
    check(0,"front on empty StrBlob");
    return data->front();
}

const string& StrBlob::back()
{
    check(0,"back on empty StrBlob");
    return data->back();    
}

void StrBlob::pop_back()
{
    check(0,"pop_back on empty StrBlob");
    data->pop_back();
}



class StrBlobPtr{
    friend bool eq(const StrBlobPtr&, const StrBlobPtr&); 
    public:
        StrBlobPtr() : curr(0) { }
        StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr

(sz) { }
        std::string& deref() const;
        StrBlobPtr& incr(); //前缀递增 
    private:
        //若检查成功,check返回一个指向vector的shared_ptr 
        std::shared_ptr<std::vector<std::string>> check(std::size_t, 

const std::string&) const;
        //保存一个weak_ptr,意味着底层vector可能被销毁 
        std::weak_ptr<std::vector<std::string>> wptr;
        std::size_t curr;//在数组中的当前位置 
};

std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(std::size_t i, 

const std::string &msg) const
{
    auto ret = wptr.lock(); //vector 还存在吗? 
    if(!ret)
        throw std::runtime_error("unbound StrBlobPtr");
    if(i >= ret->size())
        throw std::out_of_range(msg);
    return ret; //否则,返回指向vector的shared_ptr 
}

std::string&  StrBlobPtr::deref() const
{
    auto p = check(curr,"dereference past end");
    return (*p)[curr];  //(*p)是对象所指向的vector 
}

//前缀递增:返回递增后的对象的引用 
StrBlobPtr& StrBlobPtr::incr()
{
    //如果curr 已经指向容器的尾后位置,就不能递增它 
    check(curr,"increment past end of StrBlobPtr");
    ++curr;   //推进当前位置 
    return *this;
}


inline StrBlobPtr StrBlob::begin()  
{  
    return StrBlobPtr(*this);  
}  

inline StrBlobPtr StrBlob::end()  
{  
    auto ret = StrBlobPtr(*this, data->size());  
    return ret;  
}  

/*重载等于号*/
inline bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)  
{  
    auto l = lhs.wptr.lock(), r = rhs.wptr.lock();  
    if (l == r)  
        return (!r || lhs.curr == rhs.curr);  
    else  
        return false;  
}  

/*重载不等于号*/ 
inline bool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)  
{  
    return !eq(lhs, rhs);  
}  

int main()
{
StrBlob b1;  
    {  
        StrBlob b2 = {"a", "an", "the"};  
        b1 = b2;  
        b2.push_back("about");  
        cout<<b2.size()<<endl;  
    }  

    cout<<b1.size()<<endl;  
    cout<<b1.front()<<" "<<b1.back()<<endl;  


    for (auto it = b1.begin(); neq(it, b1.end()); it.incr())  
        cout<<it.deref()<<endl;  

        return 0;
}  

练习12.20:编写程序,逐行读入一个输入文件,将内容存入一个StrBlob中,用一个StrBlobPtr打印出StrBlob中的每个元素。

/*
*练习12.20 
*2016/1/22
*问题描述:
练习12.20:编写程序,逐行读入一个输入文件,将内容存入一个StrBlob中,用一个

StrBlobPtr打印出StrBlob中的每个元素。 
*参考:http://blog.csdn.net/sunhero2010/article/details/49882993 
*作者:Nick Feng
*邮箱:nickgreen23@163.com 
*/ 

/*
*练习12.7 
*2015/11/2
*问题描述:
练习12.7:重做上一题,这次使用shared_ptr而不是内置指针。
练习12.6:编写函数,返回一个动态分配的int的vector。将此vector传递给另一个函数

,这个函数读取标准输入,将读入的值保存在vector元素中。再将vector
传递给另一个函数,打印读入的值。记得在恰当的时刻delete vector。 
*说明:指针学习 fun(),fun2(),fun3() 分别实现三个函数的要求 ,和12.7不一样的

地方在于,只能指针的内存管理不要你烦了 
*作者:Nick Feng
*邮箱:nickgreen23@163.com 
*/ 
#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <fstream>
using namespace std;

class StrBlobPtr;

class StrBlob{
    friend class StrBlobPtr;
public:

    typedef std::vector<std::string>::size_type size_type;
    StrBlob();
    StrBlob(std::initializer_list<std::string> il);
    size_type size() const { return data->size();}
    bool empty() const { return data->empty();}
    void push_back(const std::string &t) { data->push_back(t);}
    void pop_back();
    const std::string& front();
    const std::string& back();

    StrBlobPtr begin();
    StrBlobPtr end();
private:
    std::shared_ptr<std::vector<std::string>> data;
    void check(size_type i, const std::string &msg) const;
};

StrBlob::StrBlob() : data(make_shared<vector<string>>()) { }

StrBlob::StrBlob(initializer_list<string> il) : data

(make_shared<vector<string>>(il)){ }

void StrBlob::check(size_type i, const string &msg) const
{
    if(i >= data->size())
        throw out_of_range(msg);
}

const string& StrBlob::front()
{
    check(0,"front on empty StrBlob");
    return data->front();
}

const string& StrBlob::back()
{
    check(0,"back on empty StrBlob");
    return data->back();    
}

void StrBlob::pop_back()
{
    check(0,"pop_back on empty StrBlob");
    data->pop_back();
}



class StrBlobPtr{
    friend bool eq(const StrBlobPtr&, const StrBlobPtr&); 
    public:
        StrBlobPtr() : curr(0) { }
        StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr

(sz) { }
        std::string& deref() const;
        StrBlobPtr& incr(); //前缀递增 
    private:
        //若检查成功,check返回一个指向vector的shared_ptr 
        std::shared_ptr<std::vector<std::string>> check(std::size_t, 

const std::string&) const;
        //保存一个weak_ptr,意味着底层vector可能被销毁 
        std::weak_ptr<std::vector<std::string>> wptr;
        std::size_t curr;//在数组中的当前位置 
};

std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(std::size_t i, 

const std::string &msg) const
{
    auto ret = wptr.lock(); //vector 还存在吗? 
    if(!ret)
        throw std::runtime_error("unbound StrBlobPtr");
    if(i >= ret->size())
        throw std::out_of_range(msg);
    return ret; //否则,返回指向vector的shared_ptr 
}

std::string&  StrBlobPtr::deref() const
{
    auto p = check(curr,"dereference past end");
    return (*p)[curr];  //(*p)是对象所指向的vector 
}

//前缀递增:返回递增后的对象的引用 
StrBlobPtr& StrBlobPtr::incr()
{
    //如果curr 已经指向容器的尾后位置,就不能递增它 
    check(curr,"increment past end of StrBlobPtr");
    ++curr;   //推进当前位置 
    return *this;
}


inline StrBlobPtr StrBlob::begin()  
{  
    return StrBlobPtr(*this);  
}  

inline StrBlobPtr StrBlob::end()  
{  
    auto ret = StrBlobPtr(*this, data->size());  
    return ret;  
}  

/*重载等于号*/
inline bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)  
{  
    auto l = lhs.wptr.lock(), r = rhs.wptr.lock();  
    if (l == r)  
        return (!r || lhs.curr == rhs.curr);  
    else  
        return false;  
}  

/*重载不等于号*/ 
inline bool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs)  
{  
    return !eq(lhs, rhs);  
}  

int main()
{
ifstream in("test.txt");  
    if (!in) {  
        cout<<"Open input file failed"<<endl;  
        return -1;  
    }  

    StrBlob b;  
    string s;  
    while (getline(in, s))  
        b.push_back(s);  

    for (auto it = b.begin(); neq(it, b.end()); it.incr())  
        cout<<it.deref()<<endl;  

        return 0;
}  

练习12.21:也可以这样编写StrBlobPtr的deref成员:

std:string & deref() const
{ return (*check(curr,"dereference past end"))[curr];}

你认为哪个版本更好?为什么?

答书上的版本更好,分开写,清晰易于理解。
参考
http://blog.csdn.net/sunhero2010/article/details/49882993

练习12.22: 为了能让StrBlobPtr使用const StrBlob,你觉得应该如何修改?定义一个名为ConstStrBlobStr的类,使其能够指向const StrBlob。

答:对StrBlobPtr的构造函数做点修改即可

StrBlobStr(const StrBlob &a, size_t sz = 0) :wptr(a.data), curr(sz){} 

参考:http://blog.csdn.net/chxw098/article/details/39035885

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值