代码很长,直接给出解决方案:
//The definition of class StrBlob、StrBlobPtr、ConstStrBlobPtr
#pragma once
#include<vector>
#include<string>
#include<initializer_list>
#include<memory>
#include<stdexcept>
// class StrBlob
class StrBlobPtr;
class ConstStrBlobPtr;
class StrBlob {
friend class StrBlobPtr;
friend class ConstStrBlobPtr;
public:
using size_type = std::vector<std::string>::size_type;
StrBlob();
StrBlob(std::initializer_list<std::string> i1);
size_type size() const { return data->size(); }
bool empty() const { return data->empty(); }
StrBlobPtr begin();
StrBlobPtr end();
ConstStrBlobPtr begin_c() const;
ConstStrBlobPtr end_c() const;
void push_back(const std::string &t) { data->push_back(t); }
void pop_back();
std::string& front();
std::string& back();
const std::string& front() const;
const std::string& back() const;
private:
std::shared_ptr<std::vector<std::string>> data;
void check(size_type t, const std::string &msg) const;
};
StrBlob::StrBlob() : data(std::make_shared<std::vector<std::string>>()) {}
StrBlob::StrBlob(std::initializer_list<std::string> i1) :
data(std::make_shared<std::vector<std::string>>(i1)) {};
void StrBlob::check(size_type t, const std::string& msg) const {
if (t >= data->size())
throw std::out_of_range(msg);
}
void StrBlob::pop_back() {
check(0, "pop_back on empty StrBlob");
data->pop_back();
}
std::string& StrBlob::front() {
check(0, "front on empty StrBlob");
return data->front();
}
const std::string& StrBlob::front() const {
check(0, "front on empty StrBlob");
return data->front();
}
std::string& StrBlob::back() {
check(0, "back on empty StrBlob");
return data->back();
}
const std::string& StrBlob::back() const {
check(0, "back on empty StrBlob");
return data->back();
}
class StrBlobPtr {
public:
StrBlobPtr() :curr(0) {};
StrBlobPtr(StrBlob &a, size_t sz = 0) :wptr(a.data), curr(sz) {};
std::string deref() const;
StrBlobPtr& incr();
bool operator!=(const StrBlobPtr& p) { return p.curr != curr; }
private:
std::weak_ptr<std::vector<std::string>> wptr;
std::size_t curr;
std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
};
std::shared_ptr<std::vector<std::string>>
StrBlobPtr::check(std::size_t i, const std::string& msg) const {
auto ret = wptr.lock();
if (!ret)
throw std::runtime_error("unbound StrBlobPtr");
if (i >= ret->size())
throw std::out_of_range(msg);
return ret;
}
std::string StrBlobPtr::deref() const {
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
StrBlobPtr& StrBlobPtr::incr() {
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
StrBlobPtr StrBlob::begin()
{ return StrBlobPtr(*this); }
StrBlobPtr StrBlob::end() {
auto ret = StrBlobPtr(*this, data->size());
return ret;
}
class ConstStrBlobPtr {
public:
ConstStrBlobPtr() :curr(0) {};
ConstStrBlobPtr(const StrBlob &a, size_t sz = 0) :wptr(a.data), curr(sz) {};
const std::string deref() const;
ConstStrBlobPtr& incr();
bool operator!=(const ConstStrBlobPtr& p) { return p.curr != curr; }
private:
std::weak_ptr<std::vector<std::string>> wptr;
std::size_t curr;
std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const;
};
std::shared_ptr<std::vector<std::string>> ConstStrBlobPtr::check(std::size_t i, const std::string&msg) const {
auto ret = wptr.lock();
if (!ret)
throw std::runtime_error("unbound StrBlobPtr");
if (i >= ret->size())
throw std::out_of_range(msg);
return ret;
}
const std::string ConstStrBlobPtr::deref() const {
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
ConstStrBlobPtr& ConstStrBlobPtr::incr() {
check(curr, "increment past end of StrBlobPtr");
++curr;
return *this;
}
ConstStrBlobPtr StrBlob::begin_c() const {
return ConstStrBlobPtr(*this);
}
ConstStrBlobPtr StrBlob::end_c() const{
auto ret = ConstStrBlobPtr(*this, data->size());
return ret;
}
//the main function
#include<iostream>
#include<fstream>
#include<vector>
#include"StrBlob.h"
using std::cout; using std::endl;
int main() {
std::ifstream input("F:/testData/text.txt");
StrBlob sb;
StrBlobPtr psb(sb);
std::string s;
while (getline(input, s))
sb.push_back(s);
for (StrBlobPtr pbeg(sb.begin()), pend(sb.end());pbeg != pend;pbeg.incr())
cout << pbeg.deref()<< endl;
const StrBlob csb({"hello","test","aha"});
for (ConstStrBlobPtr pbeg_c(csb.begin_c()), pend_c(csb.end_c());pbeg_c != pend_c;pbeg_c.incr())
cout << pbeg_c.deref()<< endl;
return 0;
}
初学者所写,欢迎指正。
本文介绍了一个自定义字符串容器StrBlob的实现,包括其迭代器StrBlobPtr和ConstStrBlobPtr。StrBlob使用智能指针管理数据,提供了类似STL容器的功能。

269

被折叠的 条评论
为什么被折叠?



