练习需求:编写一个操作位图的简化版,我们用字符代替二进制数据.使得简化版的位图能够加框(如同应用窗口),能够将两张位图进行水平布局,垂直布局
代码:
picture.h
#ifndef PICTURE_H
#define PICTURE_H
#include <ostream>
class Picture {
friend std::ostream& operator<< (std::ostream& os,const Picture& p);
friend Picture operator &(const Picture&,const Picture&);
friend Picture operator |(const Picture&,const Picture&);
public:
Picture();
Picture(const char* const* d,const int& n);
Picture(const Picture& p);
Picture& operator=(const Picture&);
~Picture();
void addFrame();
int getWidth()const;
int getHeight()const;
private:
static int maxWidth(const char* const* p,const int& n);
static int max(const int& a,const int& b);
char& position(const int& r,const int& c);
char position(const int& r,const int& c)const;
void copyBlockFrom(const int& r,const int& c,const Picture& p);
void fill(const int& r,const int& c,const int& w,const int& h);
void init(const int& w,const int& h);
char* data;
int width;
int height;
};
#endif /*PICTURE_H*/
picture.cpp
#include "picture.h"
#include <string.h>
#include <iostream>
#include <cstddef>
using std::nullptr_t;
using std::endl;
inline int Picture::maxWidth(const char* const* d,const int& n) {
int max = 0;
for (int i = 0; i < n; ++i) {
if (strlen(d[i]) > max) {
max = strlen(d[i]);
}
}
return max;
}
inline void Picture::init(const int& w,const int& h) {
height = h;
width = w;
data = new char[width * height];
}
char& Picture::position(const int& r,const int& c) {
return data[r * width + c];
}
char Picture::position(const int& r,const int& c) const {
return data[r * width + c];
}
Picture::Picture(const char* const* d,const int& n) {
init(Picture::maxWidth(d,n),n);
int j = 0;
for (int i = 0; i < height; ++i) {
for (j = 0; j < strlen(d[i]); ++j) {
position(i,j) = d[i][j];
}
while (j < width) {
position(i,j) = ' ';
++j;
}
}
}
Picture::Picture():height(0),width(0),data(nullptr) {
}
int Picture::getWidth() const{
return width;
}
int Picture::getHeight() const{
return height;
}
void Picture::copyBlockFrom(const int& r,const int& c,const Picture& p) {
for (int i = 0; i < p.height; ++i) {
for (int j = 0; j < p.width; ++j) {
position(i + r,j + c) = p.position(i,j);
}
}
}
void Picture::fill(const int& r,const int& c,const int& w,const int& h) {
for (int i = r; i < h; ++i) {
for (int j = c; j < w; ++j) {
position(i,j) = ' ';
}
}
}
Picture::Picture(const Picture& p) {
if (&p != this) {
init(p.getWidth(),p.getHeight());
copyBlockFrom(0,0,p);
}
}
Picture& Picture::operator= (const Picture& p) {
if (&p != this) {
init(p.getWidth(),p.getHeight());
copyBlockFrom(0,0,p);
}
return *this;
}
inline int Picture::max(const int& a,const int& b) {
return a > b ? a : b;
}
Picture operator& (const Picture& lhs,const Picture& rhs) {
Picture temp;
temp.init(Picture::max(lhs.getWidth(),rhs.getWidth()),lhs.getHeight() + rhs.getHeight());
temp.copyBlockFrom(0,0,lhs);
temp.copyBlockFrom(lhs.getHeight(),0,rhs);
return temp;
}
Picture operator| (const Picture& lhs,const Picture& rhs) {
Picture temp;
temp.init(lhs.getWidth() + rhs.getWidth(),Picture::max(lhs.getHeight(),rhs.getHeight()));
temp.copyBlockFrom(0,0,lhs);
if (lhs.getHeight() < rhs.getHeight()) {
temp.fill(lhs.getHeight(),0,lhs.getWidth(),rhs.getHeight());
}else {
temp.fill(rhs.getHeight(),lhs.getWidth(),lhs.getWidth() + rhs.getWidth(),lhs.getHeight());
}
temp.copyBlockFrom(0,lhs.getWidth(),rhs);
return temp;
}
Picture::~Picture() {
if(data != nullptr) {
delete []data;
}
}
std::ostream& operator<< (std::ostream& os,const Picture& p) {
for (int i = 0; i < p.height; ++i) {
for (int j = 0; j < p.width; ++j) {
os << p.position(i,j);
}
os << endl;
}
return os;
}
void Picture::addFrame() {
Picture p(*this);
delete []data;
init(p.getWidth() + 2,p.getHeight() + 2);
copyBlockFrom(1,1,p);
position(0,0) = '+';
position(0,width - 1) = '+';
position(height - 1,0) = '+';
position(height - 1,width - 1) = '+';
for (int c = 1; c < width - 1; ++c) {
position(0,c) = '-';
position(height - 1,c) = '-';
}
for (int r = 1; r < height - 1; ++r) {
position(r,0) = '|';
position(r,width - 1) = '|';
}
}
测试:main.cpp
#include "picture.h"
#include <iostream>
using std::cout;
using std::endl;
int main() {
char *init1[] = {"Life is","Worth","Living"};
Picture p(init1,3);
p.addFrame();
char *init2[] = {"what do you mean?","you wanner go","baby"};
Picture p2(init2,3);
Picture p3 = p | p2;
Picture p4 = p2 | p;
Picture p5 = p3 | p;
cout << p3 << endl;
p3.addFrame();
cout << p3 << endl;
cout << p4 << endl;
cout << p5 << endl;
return 0;
}
缺点:扩展性不高,比如加框的字符需要改变,而不是特定的一种,水平布局,垂直布局需要margin,我们只能通过给定义好的类添加方法做到,后期我们会不得不作重复的事情,来做到扩展.
浪费大量空间,比如一个图的一行字符串很长,而其他行都比较短,而我们给他填充空格,反而浪费了大量的空间去存储空格