// Picture.h
#include <iostream>
using namespace std;
// 类声明
class P_Node;
class Picture;
//==============================================================================
/// global function
//==============================================================================
Picture frame(const Picture&);
//==============================================================================
/// class Picture
//==============================================================================
class Picture
{
friend ostream& operator<<(ostream&, const Picture&);
friend Picture reframe(const Picture&, char, char, char);
public:
Picture();
Picture(P_Node*);
Picture(const Picture&);
Picture(const char* const*, int);
~Picture();
int height()const;
int width()const;
void display(ostream&, int, int)const;
Picture& operator=(const Picture&);
private:
P_Node* p; // 使用父类类型,方便不同的类型进行使用
};
//==============================================================================
/// class P_Node
//==============================================================================
class P_Node
{
friend Picture;
protected:
P_Node();
virtual ~P_Node();
int max(int x, int y) const;
virtual void display(ostream&, int, int)const = 0; // 子类必须实现的方法,函数中操作的都是const成员变量
virtual int height()const = 0; // 为子类添加必须实现的方法,函数中操作的都是const成员变量
virtual int width()const = 0; // 为子类添加必须实现的方法,函数中操作的都是const成员变量
public:
virtual Picture doreframe(char, char, char) = 0; // 为子类添加必须实现的方法,函数中操作的都是const成员变量
int refcount;
};
//==============================================================================
/// class String_Pic
//==============================================================================
class String_Pic: public P_Node
{
friend Picture;
public:
String_Pic(const char* const*, int);
~String_Pic();
void display(ostream&, int, int)const;
int height()const;
int width()const;
Picture doreframe(char, char, char);
private:
char** data;
int size;
int h;
int w;
};
//==============================================================================
/// class Frame_Pic
//==============================================================================
class Frame_Pic: public P_Node
{
friend Picture;
friend Picture frame(const Picture&);
friend Picture reframe(const Picture&, char, char, char);
public:
Frame_Pic();
Frame_Pic(const Picture&, char = '+', char = '|', char = '-');
void display(ostream&, int, int)const;
int height()const;
int width()const;
Picture doreframe(char, char, char);
private:
Picture p;
char corner;
char sideborder;
char topborder;
};
//==============================================================================
/// class Vcat_Pic
//==============================================================================
class Vcat_Pic: public P_Node
{
friend Picture;
friend Picture operator&(const Picture&, const Picture&);
friend Picture reframe(const Picture&, char, char, char);
public:
Vcat_Pic(const Picture&, const Picture&);
void display(ostream&, int, int)const;
int height()const;
int width()const;
Picture doreframe(char, char, char);
private:
Picture top, bottom;
};
//==============================================================================
/// class Hcat_Pic
//==============================================================================
class Hcat_Pic: public P_Node
{
friend Picture;
friend Picture operator|(const Picture&, const Picture&);
friend Picture reframe(const Picture&, char, char, char);
public:
Hcat_Pic(const Picture&, const Picture&);
void display(ostream&, int, int)const;
int height()const;
int width()const;
Picture doreframe(char, char, char);
private:
Picture left, right;
};
// Picture.cpp
#include "Picture.h"
//==============================================================================
/// global function
//==============================================================================
static void pad(ostream& out, int x, int y)
{
for(int i = x; i < y; ++i)
{
out<<" ";
}
}
ostream& operator<<(ostream& os, const Picture& p)
{
for(int i = 0; i < p.height(); ++i)
{
p.display(os, i, p.width());
os<<endl;
}
return os;
}
Picture frame(const Picture& pic)
{
return new Frame_Pic(pic);
}
Picture reframe(const Picture& pic, char c, char s, char t)
{
return pic.p->doreframe(c, s, t);
}
Picture operator&(const Picture& top, const Picture& bottom)
{
return new Vcat_Pic(top, bottom);
}
Picture operator|(const Picture& right, const Picture& left)
{
return new Hcat_Pic(right, left);
}
//==============================================================================
/// class Picture
//==============================================================================
Picture::Picture(P_Node* pnode)
:p(pnode)
{
}
Picture::Picture(const char* const* str, int size)
:p(new String_Pic(str, size))
{
}
Picture::Picture(const Picture& ori)
{
p = ori.p;
p->refcount++;
}
Picture& Picture::operator=(const Picture& ori)
{
ori.p->refcount++;
if(--p->refcount == 0)
{
delete p;
p = NULL;
}
p = ori.p;
return *this;
}
Picture::~Picture()
{
if(--p->refcount == 0)
{
delete p;
p = NULL;
}
}
int Picture::height() const
{
return p->height();
}
int Picture::width()const
{
return p->width();
}
void Picture::display(ostream& out, int x, int y)const
{
p->display(out, x, y);
}
//==============================================================================
/// class P_Node
//==============================================================================
P_Node::P_Node()
:refcount(1)
{
}
P_Node::~P_Node()
{
}
int P_Node::max(int x, int y)const
{
return x > y ? x : y;
}
//==============================================================================
/// class String_Pic
//==============================================================================
String_Pic::String_Pic(const char* const* p, int n)
:size(n)
{
int i = 0;
w = 0;
for(i = 0; i < size; ++i)
{
w = max(w, static_cast<int>(strlen(p[i])));
}
h = size;
data = new char*[size];
for(i = 0; i < size; ++i)
{
data[i] = new char[strlen(p[i]) + 1];
strcpy_s(data[i], strlen(p[i]) + 1, p[i]);
}
}
String_Pic::~String_Pic()
{
for(int i = 0; i < size; ++i)
{
delete[] data[i];
data[i] = NULL;
}
delete data;
data = NULL;
}
void String_Pic::display(ostream& out, int row, int width)const
{
int start = 0;
if((row >= 0) && (row < height()))
{
out<<data[row];
start = strlen(data[row]);
}
pad(out, start, width);
}
int String_Pic::height()const
{
return h;
}
int String_Pic::width()const
{
return w;
}
Picture String_Pic::doreframe(char c , char s, char t)
{
++refcount;
return this;
}
//==============================================================================
/// class Frame_Pic
//==============================================================================
Frame_Pic::Frame_Pic(const Picture& picture, char c, char s, char t)
:p(picture), corner(c), sideborder(s), topborder(t)
{
}
void Frame_Pic::display(ostream& out, int row, int wd)const
{
if((row < 0) || (row >= height()))
{
pad(out, 0, wd);
}
else
{
if((row == 0) || (row == (height() - 1)))
{
out<<corner; //out << "+";
int i = p.width();
while(--i >= 0)
{
out<<topborder; //out << "-";
}
out<<corner; //out << "+";
}
else
{
out<<sideborder; //out << "|";
p.display(out, row - 1, p.width());
out<<sideborder; //out << "|";
}
pad(out, width(), wd);
}
}
Picture Frame_Pic::doreframe(char c, char s, char t)
{
return new Frame_Pic(reframe(this->p, c, s, t), c, s, t);
}
int Frame_Pic::height()const
{
return (p.height() + 2);
}
int Frame_Pic::width()const
{
return (p.width() + 2);
}
//==============================================================================
/// class Vcat_Pic
//==============================================================================
Vcat_Pic::Vcat_Pic(const Picture& t, const Picture& b)
:top(t), bottom(b)
{
}
void Vcat_Pic::display(ostream& out, int row, int wd)const
{
if((row >= 0) && (row < top.height()))
{
top.display(out, row, wd);
}
else if((row < top.height()) + bottom.height())
{
bottom.display(out, row - top.height(), wd);
}
else
{
pad(out, 0, wd);
}
}
int Vcat_Pic::height()const
{
return (top.height() + bottom.height());
}
int Vcat_Pic::width()const
{
return max(top.width(), bottom.width());
}
Picture Vcat_Pic::doreframe(char c, char s, char t)
{
return new Vcat_Pic(reframe(top, c, s, t), reframe(bottom, c, s, t));
}
//==============================================================================
/// class Hcat_Pic
//==============================================================================
Hcat_Pic::Hcat_Pic(const Picture& l, const Picture& r)
:left(l), right(r)
{
}
void Hcat_Pic::display(ostream& out, int row, int wd)const
{
left.display(out, row, left.width());
right.display(out, row, right.width());
pad(out, width(), wd);
}
Picture Hcat_Pic::doreframe(char c, char s, char t)
{
return new Hcat_Pic(reframe(left, c, s, t), reframe(right, c, s, t));
}
int Hcat_Pic::height()const
{
return max(left.height(), right.height());
}
int Hcat_Pic::width()const
{
return (left.width() + right.width());
}
// main.cpp
#include "Picture.h"
int main(int argc, char* const argv[])
{
char* characters[] = {"Hello,", "World!"};
Picture p(characters, sizeof(characters) / sizeof(characters[0]));
cout<<p<<endl;
Picture q = frame(p);
cout<<q<<endl;
Picture r = p | q;
cout<<r<< endl;
Picture s = q & r;
cout<<s<<endl<<frame(s)<<endl;
cout<<reframe(frame(s), '*', '@', '#')<<endl;
cout<<"Press any key to continue ......"<<endl;
getchar();
return 0;
}
输出:
Hello,
World!
+------+
|Hello,|
|World!|
+------+
Hello,+------+
World!|Hello,|
|World!|
+------+
+------+
|Hello,|
|World!|
+------+
Hello,+------+
World!|Hello,|
|World!|
+------+
+--------------+
|+------+ |
||Hello,| |
||World!| |
|+------+ |
|Hello,+------+|
|World!|Hello,||
| |World!||
| +------+|
+--------------+
*##############*
@*######* @
@@Hello,@ @
@@World!@ @
@*######* @
@Hello,*######*@
@World!@Hello,@@
@ @World!@@
@ *######*@
*##############*
Press any key to continue ......