c++沉思录 第9章

练习需求:编写一个操作位图的简化版,我们用字符代替二进制数据.使得简化版的位图能够加框(如同应用窗口),能够将两张位图进行水平布局,垂直布局

代码:
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,我们只能通过给定义好的类添加方法做到,后期我们会不得不作重复的事情,来做到扩展.
浪费大量空间,比如一个图的一行字符串很长,而其他行都比较短,而我们给他填充空格,反而浪费了大量的空间去存储空格

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值