首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

C++沉思录下提到的一道练习题及其源码实现

2012-09-11 
C++沉思录上提到的一道练习题及其源码实现题目大意(具体问题可参考C沉思录第九章):现实中,一张图片,可以给

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

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

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

如下图所示:

普通的图片:

wjj   lqm   lqmwjjszb  

加框的图片:

+******+|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   lqmwjjszb   +******+|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   |      |        |*------*      |        +**************+        


 

热点排行
Bad Request.