1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
#include <vector>
#include <string>
#include <iostream>
#include <string>
#include <xutility>
using std::string;
using std::vector;
using std::size_t;
using std::ostream;
using std::max;
using std::endl;
class Picture;
Picture frame( Picture& pic );
class Element{
friend class Picture;
friend class Frame;
friend class HMerge;
friend Picture frame( Picture& pic );
friend ostream& operator<<( ostream& out, Picture& pic );
public:
virtual ~Element(){
std::cout << "~Element()" << std::endl;
};
protected:
virtual void draw(ostream&, size_t)=0;
virtual size_t width()=0;
virtual size_t rows()=0;
private:
};
class Text:public Element{
friend class Picture;
public:
~Text(){
std::cout << "~Text()" << std::endl;
};
protected:
Text( const vector<string>& text ):text(text){}
void draw( ostream & out, size_t row ){ out << text[row] << string( width() - text[row].length(), ' ' ); }
size_t width(){ size_t width=0; for( size_t row = 0; row != text.size(); ++row ) width = max( width , text[row].length() ); return width; }
size_t rows(){ return text.size();}
private:
vector<string> text;
};
class Frame:public Element{
friend Picture frame( Picture& pic );
public:
~Frame(){
std::cout << "~Frame()" << std::endl;
if(ptr) delete ptr;
ptr = 0;
}
protected:
Frame( Element* ptr ):ptr(ptr){}
void draw( ostream& out, size_t row )
{
if( row == 0 || row == rows() - 1 ){ out << string( 2 + ptr->width() + 2, '*' ); }
else if( row == 1 || row == rows() - 2 ){ out << "*" + string( 1 + ptr->width() + 1, ' ' ) + "*";}
else if( row >= 1 && row <= rows() - 2 ){ out << string("* "); ptr->draw( out, row - 2 ); out << string(" *");}
}
size_t width(){ return 2 + ptr->width() + 2; }
size_t rows(){ return 2 + ptr->rows() + 2; }
private:
Element* ptr;
};
class HMerge : public Element{
friend void hMerge( Picture&, Picture& );
public:
~HMerge(){
std::cout << "~HMerge()" << std::endl;
if(lhs) delete lhs;
//if(rhs) delete rhs;
lhs = 0;
//rhs = 0;
}
protected:
HMerge( Element* lhs, Element* rhs ):lhs(lhs),rhs(rhs){}
void draw( ostream& out, size_t row )
{
if( row < lhs->rows() )
{
lhs->draw( out , row);
}
else
{
out << string( lhs->width() , ' ' );
}
if( row < rhs->rows() )
{
rhs->draw( out , row);
}
else
{
out << string( rhs->width() , ' ' );
}
}
size_t width(){ return lhs->width() + rhs->width(); }
size_t rows(){ return 2 + max( lhs->rows(), rhs->rows() ) + 2; }
private:
Element *lhs, *rhs;
};
/******************************PUBLIC INTERFACE***********************************/
class Picture{
friend void hMerge( Picture&, Picture&);
friend Picture frame( Picture& pic );
friend ostream& operator<<( ostream& out, Picture& pic );
public:
Picture( vector<string>& text ):ptr( new Text( text ) ){}
Picture( Picture& pic ):ptr( pic.ptr ){}
Picture( Element* ptr):ptr(ptr){}
~Picture(){
std::cout << "~Picture()" << std::endl;
if(ptr) delete ptr;
ptr=0;
}
operator Element* (){ return ptr; }
private:
Element * ptr;
};
Picture frame( Picture& pic ){
return new Frame( pic.ptr );
}
void hMerge( Picture& lhs, Picture& rhs ){
lhs.ptr = new HMerge( lhs.ptr, rhs.ptr );
}
ostream& operator<<( ostream& out, Picture& pic )
{
for( size_t row = 0 ;
row != pic.ptr->rows() ;
++row )
{
pic.ptr->draw( out , row );
out << endl;
}
return out;
}
int main(){
std::vector<std::string> v;
v.push_back( "Hallo" );
v.push_back( "Josef!" );
Picture p = v;
Picture q = frame( p ); //ERROR: after the assigment q holds only rubbish!!
std::cout << q << std::endl;
}
|