题目大意(具体问题可参考C++沉思录第九章):

现实中,一张图片,可以给予添加一层又一层片框,也可以和其他的图片组合在一块,或横,或竖,……,

如下图所示:

普通的图片:

wjj
lqm
lqmwjj
szb  

加框的图片:

+******+
|wjj   |
|lqm   |
|lqmwjj|
|szb   |
+******+

前两个图片横向连接,再纵向连接,再加框的图片

+**************+
|wjj   +******+|
|lqm   |wjj   ||
|lqmwjj|lqm   ||
|szb   |lqmwjj||
|      |szb   ||
|      +******+|
|+******+      |
||wjj   |      |
||lqm   |      |
||lqmwjj|      |
||szb   |      |
|+******+      |
+**************+

默认情况下:横向连接顶端对齐,纵向连接左边对齐。

以下为自己看书后写的源代码:

picture.h

#ifndef _PICTURE_H
#define _PICTURE_H#include <cstdlib>
#include <vector>
#include <string>
#include "pnode.h"
#include "string_pic.h"//图片句柄类,又称作智能指针类class Picture
{//重载输出运算符friend std::ostream & operator<<(std::ostream &os, const Picture &p);friend class FramePic;friend class VcatPic;friend class HcatPic;
public:Picture() : _p(NULL){}Picture(const Picture & p) : _p(p._p){++p._p->use;}Picture & operator=(const Picture &p){if(_p != p._p){if(--_p->use == 0){delete _p;}_p = p._p;++p._p->use;}return *this;}//默认构造StringPic类型的图片Picture(const std::vector<std::string> &lines) : _p(new StringPic(lines)){}~Picture(){if(--_p->use == 0)delete _p;}//每次输出图片的一行,其实是调用的对应图像累的display函数void display(std::ostream &os, int row) const;//四个实用操作,原书采用的全局函数,这里用的类的静态成员函数static const Picture Frame(const Picture &p, char corner_ch, char side_ch, char top_ch);static void Reframe(const Picture &p, char corner_ch, char side_ch, char top_ch);static const Picture Vcat(const Picture &top, const Picture &bottom);static const Picture Hcat(const Picture &left, const Picture &right);private:int GetWidth() const{return _p->width;}int GetHeight() const{return _p->height;}//私有的构造函数,实现由实际图片类型的指针到Picture的隐式转换Picture(Pnode *p) : _p(p){++p->use;}//指向实际的图片类型Pnode *_p;
};#endif

picture.cpp

#include "picture.h"
#include "frame_pic.h"
#include "vcat_pic.h"
#include "hcat_pic.h"void Picture::display(std::ostream &os, int row) const
{_p->display(os,row);
}std::ostream & operator<<(std::ostream &os, const Picture &p)
{for(int i = 0; i < p.GetHeight() - 1; ++i){p.display(os,i);os << std::endl;}p.display(os,p.GetHeight() - 1);return os;
}const Picture Picture::Frame(const Picture &p, char corner_ch, char side_ch, char top_ch)
{return new FramePic(p, corner_ch, side_ch, top_ch);
}
const Picture Picture::Vcat(const Picture &top, const Picture &bottom)
{return new VcatPic(top, bottom);
}
const Picture Picture::Hcat(const Picture &left, const Picture &right)
{return new HcatPic(left, right);
}void Picture::Reframe(const Picture &p, char corner_ch, char side_ch, char top_ch)
{static_cast<FramePic*>(p._p)->Reframe(corner_ch, side_ch, top_ch);
}

pnode.h

#ifndef _PNODE_H
#define _PNODE_H
#include <iosfwd>//输出流的前置声明
#include <string>//图片类的基类,实现动态绑定
class Pnode
{friend class Picture;
protected:Pnode(int w, int h) : width(w), height(h), use(1){}//重要的虚函数,每次显示一行图片内容virtual void display(std::ostream &os, int row) const = 0;//用于填充空格符void pad(std::ostream &os, int num, char ch) const{for(int i = 0; i < num; ++i){os << ch;}}int width;int height;int use;//引用计数
};#endif

string_pic.h

#ifndef _STRING_PIC_H
#define _STRING_PIC_H#include <vector>
#include <string>
#include <algorithm>
#include <functional>
#include "pnode.h"class StringPic : public Pnode
{friend class Picture;struct StrShorter : std::binary_function<std::string, std::string, bool>{bool operator()(const std::string& str1, const std::string& str2) const{return str1.size() < str2.size();}};StringPic(const std::vector<std::string> &lines);virtual void display(std::ostream &os, int row) const;std::vector<std::string> _lines;
};#endif

string_pic.cpp

#include "string_pic.h"StringPic::StringPic(const std::vector<std::string> &lines) : Pnode(std::max_element(lines.begin(),lines.end(),StrShorter())->length(), lines.size()), _lines(lines)
{++use;
}void StringPic::display(std::ostream &os, int row) const
{os << _lines[row];pad(os,width - _lines[row].size(),' ');
}

frame_pic.h

#ifndef _FRAME_PIC_H
#define _FRAME_PIC_H#include "picture.h"
#include "pnode.h"class FramePic : public Pnode
{friend class Picture;FramePic(const Picture &p, char corner_ch, char side_ch, char top_ch);virtual void display(std::ostream &os, int row) const;void Reframe(char corner_ch, char side_ch, char top_ch);Picture _p;char _corner_ch;char _side_ch;char _top_ch;
};#endif

frame_pic.cpp

#include "frame_pic.h"FramePic::FramePic(const Picture &p, char corner_ch, char side_ch, char top_ch) :Pnode(p.GetWidth()+2, p.GetHeight()+2),_p(p), _corner_ch(corner_ch), _side_ch(side_ch), _top_ch(top_ch)
{}void FramePic::display(std::ostream &os, int row) const
{if(row == 0 || row == height - 1){os << _corner_ch;for(int i = 0; i < width-2; ++i){os << _top_ch;}os << _corner_ch;}if(row > 0 && row < height - 1){os << _side_ch;_p.display(os,row - 1);os << _side_ch;}
}void FramePic::Reframe(char corner_ch, char side_ch, char top_ch)
{_corner_ch = corner_ch;_side_ch = side_ch;_top_ch = top_ch;
}

vcat_pic.h

#ifndef _VCAT_PIC_H
#define _VCAT_PIC_H#include "picture.h"
#include "pnode.h"class VcatPic : public Pnode
{friend class Picture;VcatPic(const Picture &top_p, const Picture &bottom_p);virtual void display(std::ostream &os, int row) const;Picture _top_p;Picture _bottom_p;
};#endif

vcat_pic.cpp

#include "vcat_pic.h"VcatPic::VcatPic(const Picture &top_p, const Picture &bottom_p) :Pnode(std::max(top_p.GetWidth(), bottom_p.GetWidth()), top_p.GetHeight() + bottom_p.GetHeight()),_top_p(top_p), _bottom_p(bottom_p)
{}void VcatPic::display(std::ostream &os, int row) const
{if(row < _top_p.GetHeight()){_top_p.display(os,row);pad(os,width - _top_p.GetWidth(),' ');}else{_bottom_p.display(os,row - _top_p.GetHeight());pad(os,width - _bottom_p.GetWidth(),' ');}
}

hcat_pic.h

#ifndef _HCAT_PIC_H
#define _HCAT_PIC_H#include "picture.h"
#include "pnode.h"class HcatPic : public Pnode
{friend class Picture;HcatPic(const Picture &lpic,const Picture &rpic);virtual void display(std::ostream &os, int row) const;Picture _lpic;Picture _rpic;
};#endif

hcat_pic.cpp

#include "hcat_pic.h"HcatPic::HcatPic(const Picture &lpic,const Picture &rpic) :Pnode(lpic.GetWidth() + rpic.GetWidth(), std::max(lpic.GetHeight(), rpic.GetHeight())),_lpic(lpic), _rpic(rpic)
{}
void HcatPic::display(std::ostream &os, int row) const
{if(row < _lpic.GetHeight())_lpic.display(os,row);elsepad(os,_lpic.GetWidth(),' ');if(row < _rpic.GetHeight())_rpic.display(os,row);elsepad(os,_rpic.GetWidth(),' ');
}

main.cpp

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include "picture.h"using namespace std;int main(int argc, char *argv[])
{ofstream outfile("d:/hello.txt");//图像信息保存在vector中,原书用的字符数组//目前写c++程序建议用vector代替数组vector<string> pic;pic.push_back("wjj");pic.push_back("lqm");pic.push_back("lqmwjj");pic.push_back("szb");//创建一个图片Picture p(pic);outfile << p << endl;//创建一个加边框的图片Picture frame_pic = Picture::Frame(pic,'+','|','*');outfile << frame_pic << endl;//综合使用横向连接与纵向连接Picture all_p = Picture::Frame(Picture::Vcat(Picture::Hcat(pic,frame_pic), frame_pic),'+','|','*');outfile << all_p << endl;//改变图像的边框样式Picture::Reframe(frame_pic, '*', '|', '-');outfile << frame_pic << endl;//再连接一次outfile << Picture::Hcat(all_p,frame_pic) << endl;return 0;
}

测试输出结果:hello.txt

wjj
lqm
lqmwjj
szb
+******+
|wjj   |
|lqm   |
|lqmwjj|
|szb   |
+******+
+**************+
|wjj   +******+|
|lqm   |wjj   ||
|lqmwjj|lqm   ||
|szb   |lqmwjj||
|      |szb   ||
|      +******+|
|+******+      |
||wjj   |      |
||lqm   |      |
||lqmwjj|      |
||szb   |      |
|+******+      |
+**************+
*------*
|wjj   |
|lqm   |
|lqmwjj|
|szb   |
*------*
+**************+*------*
|wjj   *------*||wjj   |
|lqm   |wjj   |||lqm   |
|lqmwjj|lqm   |||lqmwjj|
|szb   |lqmwjj|||szb   |
|      |szb   ||*------*
|      *------*|
|*------*      |
||wjj   |      |
||lqm   |      |
||lqmwjj|      |
||szb   |      |
|*------*      |
+**************+

C++沉思录上提到的一道练习题及其源码实现相关推荐

  1. 关于《设计模式》与《设计模式沉思录》中提到的“常露齿嘻笑的猫”(Cheshire Cat)的说明

    最近在看GoF的<设计模式>,在此之前看了John Vlissides的<设计模式沉思录>,在"沉思录"P42页脚注中,作者提到 "在C++中这样 ...

  2. 关于《设计模式》与《设计模式沉思录》中提到的“常露齿嘻笑的猫”(Cheshire Cat)的说明...

    最近在看GoF的<设计模式>,在此之前看了John Vlissides的<设计模式沉思录>,在"沉思录"P42页脚注中,作者提到 "在C++中这样 ...

  3. 马可奥勒留《沉思录》读后感作文6000字

    马可奥勒留<沉思录>读后感作文6000字: 马可奥勒留的<沉思录>早有耳闻,一直没有去读是因为还没有碰到靠自己的之前的思考模式解决不了的难题.但近一年多来的迷茫让我认识到在执行 ...

  4. ASP.NET Core 沉思录 - Logging 的两种介入方法

    ASP.NET Core 中依赖注入是一个很重要的环节.因为几乎所有的对象都是由它创建的(相关文章请参见<ASP.NET Core 沉思录 - ServiceProvider 的二度出生> ...

  5. 渗透沉思录 - 转自亮神

    声明:本文内容来自亮神-gitbook-渗透沉思录[还有一文,"渗透测试的本质"] https://micropoor.blogspot.com/ 附:目前亮神的git已经停更2年 ...

  6. 一切笔直都是骗人的 —— 2020 年产品沉思录卷首语摘录

    小时候很喜欢看<读者>,尤其是其中的「言论」部分,在那个能把所有书籍读完的时代,很难走出家门五公里的年代,这些字字玑珠的文字仿佛打开了另外一个世界的大门. 抽空把 2020 年产品沉思录的 ...

  7. 产品沉思录 #Vol.20200425:所谓常识

    产品沉思录是我从 2017 年开始运营的付费 Newsletter (邮件组),经过四年来的运营,还积累了一个庞大的关于产品的知识库. 每周我(少楠) 和 fonter ,都会精选四篇关于互联网产品的 ...

  8. 产品沉思录精选:交易平台的金字塔进阶

    本文根据上一期沉思录回顾的调研结果,为大家翻译整理了交易平台的金字塔进阶专题. 作为本年回顾类型的最后一期,想随着这个话题给大家分享fonter在新一期沉思录中介绍的概念depth year &quo ...

  9. JAVA编程调优全集-性能设计沉思录(12)

    各文章各专题涉及到还原实践中的场景,原理,方法,模型,代码,原则,设计等:精心打造系列分享,阅读者仔细了解,必定有所收获,也可以收藏,日后工作中参考. 线程与JVM调优专题:设计模式调优-性能设计沉思 ...

最新文章

  1. 多迪将企业的Python工程师定位成哪几类?
  2. python安装步骤电脑版-超详细的小白python3.X安装教程|Python安装
  3. idea 开发spark 程序代码
  4. JVM内存结构 VS Java内存模型 VS Java对象模型
  5. stm32 工业按键检测_基于STM32芯片的能谱仪设计
  6. 如何赋予自主系统具备持续学习的能力?
  7. “隐私经济”有未来吗?
  8. 悬赏数据控!2018网易有数可视化大赛火热开启!
  9. 在Vue中使用Echarts可视化库的完整步骤记录
  10. 全能地图工具共享及操作规范
  11. html文本框显示当前时间,javascript  在文本框中显示系统当前日期(年-月-日 时:分:秒)...
  12. 使用Kieker(AspectJ)监控控制台程序
  13. 移动硬盘在mac上无法显示
  14. Vue对高德地图2.0的封装使用
  15. Lumerical Mode FDE 碰到的错误整理【整理中】
  16. 卡数字怀念的东西:魔方
  17. 32位系统无法运行64位系统安装文件
  18. 干支纪年法简便算法_天干地支的简单算法
  19. 厄拉托塞师(Eratosthenes)筛法
  20. Java面试题——数据库的优化

热门文章

  1. 测试wlan的软件是什么,配置软件定义的WLAN测试系统
  2. html正方形边框,HTML实战篇:html制作边框为1px的九宫格
  3. 服务器如何采集信息吗,如何进行数据采集?这份数据采集方案告诉你
  4. git merge 之后文件被删除
  5. 史上最强 Tomcat8 性能优化实战!
  6. windows10安装sql server
  7. 解读华为数据治理方法论及最佳实践(24H限时下载)
  8. 破解迅雷下载被屏蔽的电影(正版)
  9. AD20/Altium designer——过孔盖油
  10. 2020年第六届“美亚杯”中国电子数据取证大赛 资格赛 解题(一)