?? 15-2,3,4.cpp
字號:
#include<iostream>
#include<memory>
#include<iterator>
#include<string>
#include<vector>
using std::cout;
using std::endl;
using std::cin;
template <class T> class Vec
{
public:
typedef T* iterator;
typedef const T* const_iterator;
typedef size_t size_type;
typedef T value_type;
Vec() { create(); }
explicit Vec(size_type n,const T& t=T()) { create(n,t);}
Vec(const Vec& v) { create(v.begin(),v.end()); }
Vec& operator=(const Vec&);
~Vec() { uncreate();}
T& operator[](size_type i) { return data[i]; }
const T& operator[](size_type i) const {return data[i];}
void push_back(const T& t)
{
if(avail==limit)
grow();
unchecked_append(t);
}
iterator erase(iterator);
void clear();
size_type size() const {return avail-data;}
iterator begin() { return data;}
const_iterator begin() const { return data;}
iterator end() { return avail;}
const_iterator end() const { return avail; }
private:
iterator data; //first element in the Vec
iterator avail; //(one past) the last of element in the Vec
iterator limit; //(one past) the allocated menory
//facilities for memory allocation
std::allocator<T> alloc; //object to handle memory allocation
//allocation and initialize the underlying array
void create();
void create(size_type,const T&);
void create(const_iterator, const_iterator);
//destroy the element in the array and free the memory
void uncreate();
//support funcions for push_back
void grow();
void unchecked_append(const T&);
};
template<class T>
Vec<T>& Vec<T>::operator =(const Vec& rhs)
{
//check for self-assignment
if(&rhs!=this)
{
//free the array in the left-hand side
uncreate();
//copy elements from the right-hand to the left-hand side
create(rhs.begin(),rhs.end());
}
return *this;
}
template <class T> void Vec<T>::create()
{
data=avail=limit=0;
}
template <class T> void Vec<T>::create(size_type n, const T& val)
{
data=alloc.allocate(n,0);
limit=avail=data+n;
std::uninitialized_fill(data,limit,val);
}
template <class T>
void Vec<T>::create(const_iterator i,const_iterator j)
{
data=alloc.allocate(j-i,0);
limit=avail=std::uninitialized_copy(i,j,data);
}
template <class T> void Vec<T>::uncreate()
{
if(data)
{
//destroy (in reverse orde) the elements that were constructed
iterator it=avail;
while(it!=data)
alloc.destroy(--it);
//return all the space that was allocated
alloc.deallocate(data,limit-data);
}
//reset pointers to indicate that the Vec is empty again
data=limit=avail=0;
}
template <class T> void Vec<T>::grow()
{
//when growing, allocate twice as much space as currently in use
size_type new_size=std::_MAX(2*(limit-data),ptrdiff_t(1));
//allocate new space and copy existing elements to the new space
iterator new_data=alloc.allocate(new_size,0);
iterator new_avail=std::uninitialized_copy(data,avail,new_data);
//return the old space
uncreate();
//reset pointers to point to the newly allocate space
data=new_data;
avail=new_avail;
limit=data+new_size;
}
template <class T> void Vec<T>::unchecked_append(const T& val)
{
alloc.construct(avail++,val);
}
template <class T> Vec<T>::iterator Vec<T>::erase(iterator i)
{
std::copy(i+1,avail,i);
--avail;
return i;
}
template <class T> void Vec<T>::clear()
{
uncreate();
}
template<class T> class Ptr
{
public:
//to copy the object conditionally when needed
void make_unique()
{
if(*refptr!=1)
{
--*refptr;
refptr=new size_t(1);
p=p?clone(p):0;
}
}
Ptr():refptr(new size_t(1)),p(0){}
Ptr(T* t):refptr(new size_t(1)),p(t){}
Ptr(const Ptr& h):refptr(h.refptr),p(h.p){++*refptr;}
Ptr& operator=(const Ptr&);
~Ptr();
operator bool() const { return p;}
T& operator*() const;
T* operator->() const;
private:
T* p;
size_t* refptr;
};
template<class T>
T& Ptr<T>::operator *() const
{
if(p)
return *p;
throw std::runtime_error("unbound Ptr");
}
template<class T>
T* Ptr<T>::operator ->() const
{
if(p)
return p;
throw std::runtime_error("unbound Ptr");
}
template<class T>
Ptr<T>& Ptr<T>::operator =(const Ptr& rhs)
{
++*rhs.refptr;
//free the left-hand side, destorying pointers if appropriate
if(--*refptr==0)
{
delete refptr;
delete p;
}
//copy in values from the right-hand side
refptr=rhs.refptr;
p=rhs.p;
return *this;
}
template<class T>
Ptr<T>::~Ptr()
{
if(--*refptr==0)
{
delete refptr;
delete p;
}
}
Vec<char>* clone(const Vec<char>* vp)
{
return new Vec<char>(*vp);
}
class Str
{
friend std::istream& operator>>(std::istream&,Str&);
friend std::istream& getline(std::istream&,Str&);
public:
operator bool(){return size()!=0?true:false;}
Str& operator+=(const Str& s)
{
data.make_unique();
std::copy(s.data->begin(),s.data->end(),std::back_inserter(*data));
return *this;
}
//interface as before
typedef Vec<char>::size_type size_type;
//constructors to creator Ptrs
Str():data(new Vec<char>){}
Str(const char* cp):data(new Vec<char>)
{
std::copy(cp,cp+strlen(cp),std::back_inserter(*data));
}
Str(size_type n,char c):data(new Vec<char>(n,c)){}
template<class In>
Str(In i,In j):data(new Vec<char>)
{
std::copy(i,j,std::back_inserter(*data));
}
//call mack_unique as necessary
char& operator[](size_type i)
{
data.make_unique();
return (*data)[i];
}
const char& operator[](size_type i)const{return (*data)[i];}
size_type size()const{return data->size();}
const Str substr(size_type i,size_type length) const
{
return Str(&(*data)[i],&(*data)[i]+length);
}
const char* c_str() const;
const char* c_date() const;
const char* copy(char*,size_type) const;
typedef Vec<char>::iterator iterator;
typedef Vec<char>::const_iterator const_iterator;
iterator begin(){return data->begin();}
const_iterator begin() const {return data->begin();}
iterator end(){return data->end();}
const_iterator end() const {return data->end();}
private:
//store a Ptr to a vector
Ptr<Vec<char> > data;
};
std::ostream& operator<<(std::ostream& os, const Str& s)
{
for(Str::size_type i=0;i<s.size();++i)
os<<s[i];
return os;
}
Str operator+(const Str& s,const Str& t)
{
Str r=s;
r+=t;
return r;
}
std::istream& getline(std::istream& is,Str& s)
{
//obliterate existing value (s)
s.data->clear();
//read and discard leading whitespace
char c;
while(is.get(c)&&isspace(c))
;//nothing to do, except testing the condition
//if still something to read, do so until next whitespace charactor
if(is)
{
do
s.data->push_back(c); //compile error! data is private
while(is.get(c)&&c!='\n');
}
return is;
}
const char* Str::copy(char* p,size_type n) const
{
if(strlen(p)<n)
throw "benefit!";
else
{
std::copy(data->begin(),data->begin()+n,p);
return p;
}
}
const char* Str::c_str() const
{
char* p=new char[size()];
std::copy(data->begin(),data->end(),p);
p[size()]=0;
return p;
}
const char* Str::c_date() const
{
char* p=new char[size()-1];
std::copy(data->begin(),data->end(),p);
return p;
}
Vec<Str> split(const Str& s)
{
Vec<Str> ret;
typedef Str::size_type string_size;
string_size i=0;
//ivarinant: we have processed characters [original value of i, i)
while(i!=s.size())
{
//ignore leading blanks
//invariant: characters in range [original i, current i) are all spaces
while(i!=s.size()&&isspace(s[i]))
++i;
//find end of next word
string_size j=i;
//invariant: none of the characters in range [original j,current j)is a space
while(j!=s.size()&&!isspace(s[j]))
j++;
//if we found some nonwhitespace characters
if(i!=j)
{
//copy from s starting at i and taking j-i chars
ret.push_back(s.substr(i,j-i));
i=j;
}
}
return ret;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
class Picture;
class Pic_base
{
friend std::ostream& operator<<(std::ostream&,const Picture&);
friend class Frame_Pic;
friend class HCat_Pic;
friend class VCat_Pic;
friend class String_Pic;
//no public interface
typedef Vec<Str>::size_type ht_sz;
typedef Str::size_type wd_sz;
//this class is an abstract base class
virtual wd_sz width() const=0;
virtual ht_sz height() const=0;
virtual void display(std::ostream&,ht_sz,bool) const=0;
protected:
static void pad(std::ostream& os, wd_sz beg, wd_sz end)
{
while(beg!=end)
{
os<<" ";
++beg;
}
}
};
class Picture
{
friend std::ostream& operator<<(std::ostream&,const Picture&);
friend Picture frame(const Picture&);
friend Picture hcat(const Picture&,const Picture&);
friend Picture vcat(const Picture&,const Picture&);
public:
Picture(const Vec<Str>& =Vec<Str>());
private:
Picture(Pic_base* ptr):p(ptr){}
Ptr<Pic_base> p;
};
////////////////////////////////////////////////////////////////////////////////////
class Frame_Pic:public Pic_base
{
friend Picture frame(const Picture&);
Ptr<Pic_base> p;
Frame_Pic(const Ptr<Pic_base>& pic):p(pic){}
wd_sz width()const{return p->width()+8;}
ht_sz height()const{return p->height()+4;}
void display(std::ostream&,ht_sz,bool)const;
};
char ch;
void Frame_Pic::display(std::ostream& os,ht_sz row,bool do_pad)const
{
if(row>=height())
{
//out of range
if(do_pad)
pad(os,0,width());
}
else
{
if(row==0||row==height()-1)
{
//top or bottom row
os<<Str(width(),ch);
}
else if(row==1||row==height()-2)
{
//second from top or bottom row
os<<Str(1,ch)+Str(" &");
pad(os,1,(width()-5)/2);
os<<"$";
pad(os,(width()-5)/2+1,width()-5);
os<<Str("& ")+Str(1,ch);
}
else
{
//interior row
if(row==height()/2)
{
os<<Str(1,ch)+Str(" % ");
p->display(os,row-2,true);
os<<Str(" % ")+Str(1,ch);
}
else
{
os<<Str(1,ch)+Str(" ");
p->display(os,row-2,true);
os<<Str(" ")+Str(1,ch);
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////
class String_Pic:public Pic_base
{
friend class Picture;
Vec<Str> data;
String_Pic(const Vec<Str>& v):data(v){};
ht_sz height() const {return data.size();}
wd_sz width() const;
void display(std::ostream&,ht_sz,bool)const;
};
Pic_base::wd_sz String_Pic::width()const
{
Pic_base::wd_sz n=0;
for(Pic_base::ht_sz i=0;i!=data.size();++i)
n=std::_MAX(n,data[i].size());
return n;
}
void String_Pic::display(std::ostream& os, ht_sz row, bool do_pad)const
{
wd_sz start=0;
//write the row if we're still in range
if(row<height())
{
os<<data[row];
start=data[row].size();
}
//pad the output if necessary
if(do_pad)
pad(os,start,width());
}
/////////////////////////////////////////////////////////////////////////////////////
class VCat_Pic:public Pic_base
{
friend Picture vcat(const Picture&,const Picture&);
Ptr<Pic_base> top,bottom;
VCat_Pic(const Ptr<Pic_base>& t,const Ptr<Pic_base>& b):top(t),bottom(b){}
wd_sz width()const{return std::_MAX(top->width(),bottom->width());}
ht_sz height()const{return std::_MAX(top->height(),bottom->height());}
void display(std::ostream&,ht_sz,bool)const;
};
void VCat_Pic::display(std::ostream& os, ht_sz row, bool do_pad)const
{
wd_sz w=0;
if(row<top->height())
{
//we are in the top subpicture
top->display(os,row,do_pad);
w=top->width();
}
else if (row<height())
{
//we are in the bottom subpicture
bottom->display(os,row-top->height(),do_pad);
w=bottom->width();
}
if(do_pad)
pad(os,w,width());
}
//////////////////////////////////////////////////////////////////////////////////
class HCat_Pic:public Pic_base
{
friend Picture hcat(const Picture&,const Picture&);
Ptr<Pic_base> left,right;
HCat_Pic(const Ptr<Pic_base>& l,const Ptr<Pic_base>& r):left(l),right(r){}
wd_sz width()const{return left->width()+right->width();}
ht_sz height()const{return std::_MAX(left->height(),right->height());}
void display(std::ostream&,ht_sz,bool)const;
};
void HCat_Pic::display(std::ostream& os,ht_sz row,bool do_pad)const
{
left->display(os,row,do_pad||row<right->height());
right->display(os,row,do_pad);
}
//////////////////////////////////////////////////////////////////////////////
Picture frame(const Picture& pic)
{
return new Frame_Pic(pic.p);
}
Picture hcat(const Picture& l,const Picture& r)
{
return new HCat_Pic(l.p,r.p);
}
Picture vcat(const Picture& t,const Picture& b)
{
return new VCat_Pic(t.p,b.p);
}
//Picture::Picture(const Vec<Str>& v):p(new String_Pic(v)){}
std::ostream& operator<<(std::ostream& os,const Picture& picture)
{
const Pic_base::ht_sz ht=picture.p->height();
for(Pic_base::ht_sz i=0;i!=ht;++i)
{
picture.p->display(os,i,false);
os<<endl;
}
return os;
}
Picture::Picture(const Vec<Str>& v):p(new String_Pic(v)){}
int main()
{
Str str;
getline(cin,str);
cout<<str<<endl;
Vec<Str> v;
v=split(str);
cout<<"specify what characters to use for these border characters"<<endl;
cin>>ch;
Picture p = v;
cout<<p<<endl;
Picture q = frame(p);
cout<<q<<endl;
Picture r = hcat(p, q) ;
cout<<r<<endl;
Picture s = vcat(q, r);
cout<<"specify what characters to use for these border characters"<<endl;
cin>>ch;
cout << frame(hcat(s, vcat(r, q))) << endl;
return 0;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -