第十章:一个课堂练习的分析(下)2
10-1.4 显示图象
我们很可能使用一个反映了Picture结构的算法来打印该Picture.典型方式是分行打印字符串。假设我们打算这么干,这种情况下如果实现显示Frame_Pic的函数呢?很难办。(为什么?)。因为需要在该图象的每一行中打印边框部分。所以显示操作功能不够完美。
如果希望能够控制每一行的首尾形态,则必须能够打印指定图象的某一行(不带换行符)。只要能作到这点,加筐的操作就简单了,首先打印顶筐,然后图象的每一行,打印左边框,然后是图象行,再后是右边筐,最后打印底框。
仔细分析这个过程,我们需要确定一副图象的高度和宽度。
完了吗?假设我们要显示一个String_Pic,我们希望每一行显示完毕后立即换行,没有必要在尾部填充多余的空格。但是当 包含String_Pic的Frame_Pic时,必须在该String_Pic的每一行尾部填补适量的空格。
于是,显示操作需要两个参数:打印的行数和最小宽度。每一行都会填补必要的空格来满足最小宽度的要求。应该还有一个参数:输出的目标文件。
P_Node的派生类将会用到我们新增的heignt, width, 和display函数。然而我们把这些设置为private, 这样普通用户不能使用它们。这个想法可以保证Picture类的节口不能使用其函数,付出代价,所有的P_Node派生出来的新类成为Picture的友员。
class Picture{
//和前面一样
friend class String_Pic;
friend class Frame_Pic;
friend class Hcat_Pic;
friend class Vcat_Pic;
private:
Picture(P_Node*);
int height() const; //新增的
int width() const; //新增的
int display(ostream&, int, int) const; // 新增的
P_Node* p;
};
int Picture::height() const
{
return p->height();
}
int Picture::width() const
{
return p->width();
}
void Picture::display(ostream& o, int x, int y) const
{
p->display(o, x, y);
}
现在考虑operator<<
ostream& operator<
{
int ht = picture.height(0;
for(int i=0; i
picture.display(os, i, o);
os<
}
return os;
}
class P_Node {
friend class Picture;
protected:
P_Node();
virtual ~P_Node();
virtual int height() const = 0; //新增的
virtual int width() const = 0; //新增的
virtual void display
(ostream&, int, int )const=0; //新增的
private:
int use;
};
其派生类都加上,不要带0。
int P_node::max(int x, int y)
{
return x>y?x:y;
}
int String_Pic::height() const
{
return size;
}
int String_Pic::width() const
{
int n= 0;
for(int i= 0; i
n = max(n.strlen(data[i]));
}
return n;
}
static void pad(ostream& os, int x, int y)
{
for(int i =x; i
os << " ";
}
void
String_Pic::display(ostream& os, int row, int weith) const
{
int start = 0;
if(row >= 0 && row
os << data[row];
start = strlen(data[row]);
}
pad(os, start, width);
}
//获取加筐图象的高度和宽度
int Frame_Pic::height() const
{
return p.height() + 2;
}
int Frame_Pic::width() const
{
return p.width() +2;
}
//打印一个加筐图象是很烦琐的,但并不困难,三种情况
//需要打印行在图象之外,或是顶筐或底筐,或在图象之内。
void Frame_Pic::display(ostream& os, int row, int we) const
{
if(row < 0 || row >= height()) {
// 越界
pad(os, 0, wd);
}else {
if(row = 0 ||row ==hieght()-1) {
//顶筐和低筐
os << "+";
int i = p.width();
while(--i >= 0)
os << "-";
os <
}else {
//内部行
os << "|";
p.display(os, row-1, p.width());
os << "|"
}
pad(os, width(0, wd);
}
}
//打印连接后的图象
int VCat_Pic::height() const
{
return top.height() +bottom.height();
}
int VCat_Pic::width() const
{
return max(top.width(), bottom.width());
}
int HCat_Pic::height() const
{
return max(left.height(0, reght.height());
}
int HCat_Pic::width() const
{
return left.width() + reght.width();
}
void Vcat_Pic::display(ostream& os, int row, int wd) const
{
if(row >= 0 &&row < top.height())
top.display(os, row, wd);
else if(row
bottom.display(os.row-top.height(), wd);
else
pad (os, 0, wd);
}
//注意当我们显示下层图象时,一定要注意某行的行号是上面图象的高度加上
//改行在下图图象中的行号
//横向连接:首先打印左边图象的某行,然后右边图象的对应行
//最后填补空格
void Hcat_Pic::display(ostream& os, int row, int wd) const
{
left.display(os, row, left.width());
right.display(os, reow, right.width());
pad(os, width(), wd);
}
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/409557/viewspace-892092/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/409557/viewspace-892092/