《C++沉思录》-第九章-- 一个课堂练习的分析(上)

picture.h

#ifndef PICTURE_H
#define PICTURE_H

#include<iostream>
using namespace std;

class Picture
{
public:
    Picture();
    Picture(const char* const*, int);
    Picture(const Picture&);
    Picture& operator=(const Picture&);
    ~Picture();

private:
    int m_height;
    int m_width;
    char* m_data;

    //获取固定位置上的字符,可以作为左值进行读写
    char& position(int row, int col)
    {
        return m_data[row * m_width + col];
    }

    //获取固定位置上的字符的副本
    char position(int row, int col) const
    {
        return m_data[row * m_width + col];
    }

    //初始化
    void init(int height, int width);

    //静态函数,比较两个数的大小,用于获取字符串数组中最长的长度
    static int max(int m, int n);

    //用于拷贝picture到固定起始位置开始的区域
    void copyBlock(int m, int n, const Picture&);

    //清理无用区域
    void clear(int x, int y, int height, int width);

    friend ostream& operator<<(ostream&, const Picture&);

    friend Picture frame(const Picture&);

    friend Picture operator&(const Picture&, const Picture&);

    friend Picture operator|(const Picture&, const Picture&);
};


#endif // PICTURE_H

picture.cpp

#include "picture.h"
#include <string.h>

Picture::Picture()
    :m_height(0), m_width(0), m_data(0)
{
}


Picture::Picture(const char* const* array, int n)
{
    int w = 0;
    for (int i = 0; i < n; i++)
    {
        w = Picture::max(w, strlen(array[i]));
    }

    init(n, w);

    for (int i = 0; i<n; i++)
    {
        const char* src = array[i];
        int len = strlen(src);
        int j = 0;

        while (j < len)
        {
            position(i, j) = src[j];
            ++j;
        }
        //给每一行中余下的位置要添上空格
        while (j< m_width)
        {
            position(i, j) = ' ';
            ++j;
        }
    }
}

Picture::Picture(const Picture& p)
     :m_height(p.m_height), m_width(p.m_width),
      m_data(new char[p.m_height * p.m_width])
{
    copyBlock(0 ,0 ,p);
}

Picture& Picture::operator=(const Picture& p)
{
    if (this != &p)
    {
        delete[] m_data;
        init(p.m_height, p.m_width);
        copyBlock(0, 0, p);
    }
    return *this;
}


Picture::~Picture()
{
}


void Picture::init(int height, int width)
{
    m_height = height;
    m_width = width;
    m_data = new char[height * width];

}

int Picture::max(int m, int n)
{
    return m>n ? m:n;
}

void Picture::copyBlock(int m, int n, const Picture& p)
{
    for (int i = 0; i < p.m_height; i++)
    {
        for (int j = 0; j < p.m_width; j++)
        {
            position(i + m, j + n) = p.position(i, j);
        }
    }
}

void Picture::clear(int x, int y, int height, int width)
{
    for (int i = x; i < height; ++i)
    {
        for (int j = y; j < width; ++j)
        {
            position(i, j) = ' ';
        }
    }
}

ostream& operator<<(ostream& o, const Picture& p)
{
    for (int i = 0; i < p.m_height; i++)
    {
        for (int j = 0; j < p.m_width; j++)
        {
            o << p.position(i, j);
        }
        o << endl;
    }
    return o;
}

Picture frame(const Picture& p)
{
    Picture r;
    r.init(p.m_height + 2, p.m_width + 2);

    //左右两边边框“|”
    for (int i = 1; i< r.m_height - 1; ++i)
    {
        r.position(i, 0) = '|';
        r.position(i, r.m_width - 1) = '|';
    }
    //上下边框“-”
    for (int j = 1; j < r.m_width - 1; ++j)
    {
        r.position(0, j) = '-';
        r.position(r.m_height - 1, j) = '-';
    }
    //四个角“+”
    r.position(0, 0) = '+';
    r.position(0, r.m_width - 1) = '+';
    r.position(r.m_height -1, 0) = '+';
    r.position(r.m_height -1, r.m_width - 1) = '+';

    r.copyBlock(1, 1, p);
    return r;


}

Picture operator&(const Picture& up, const Picture& down)
{
    Picture r;
    r.init(up.m_height + down.m_height,
           Picture::max(up.m_width, down.m_width));
    //将组合后的无用单元设置成空格
    r.clear(0, up.m_width, up.m_height, r.m_width);
    r.clear(up.m_height, down.m_width, r.m_height, r.m_width);

    r.copyBlock(0, 0, up);
    r.copyBlock(up.m_height, 0, down);
    return r;

}

Picture operator|(const Picture& left, const Picture& right)
{
    Picture r;
    r.init(Picture::max(left.m_height, right.m_height),
           left.m_width + right.m_width);
    r.clear(left.m_height, 0, r.m_height, left.m_width);
    r.clear(right.m_height, left.m_width, r.m_height, r.m_width);
    r.copyBlock(0, 0, left);
    r.copyBlock(0, left.m_width, right);

    return r;
}


main.cpp

#include <iostream>
#include "picture.h"
using namespace std;

char* init[] = {"Pairs", "in the", "Spring"};


int main()
{
    Picture p(init, 3);
    cout << p << endl;

    Picture q = p;
    cout << q << endl;

    Picture fq = frame(q);
    cout << fq << endl;

    Picture fqq = (fq & q);
    cout << fqq << endl;

    Picture  p_fqq = p | (frame(q) & q);
    cout << p_fqq << endl;

    Picture fpfqq = frame(p_fqq);
    cout << fpfqq << endl;

    return 0;
}



运行结果:

Pairs 
in the
Spring

Pairs 
in the
Spring

+------+
|Pairs |
|in the|
|Spring|
+------+

+------+
|Pairs |
|in the|
|Spring|
+------+
Pairs   
in the  
Spring  

Pairs +------+
in the|Pairs |
Spring|in the|
      |Spring|
      +------+
      Pairs   
      in the  
      Spring  

+--------------+
|Pairs +------+|
|in the|Pairs ||
|Spring|in the||
|      |Spring||
|      +------+|
|      Pairs   |
|      in the  |
|      Spring  |
+--------------+

缺陷:

首先,复制图像就要复制字符,而且再把一幅小图像并到大图像的过程中,也要复制其内部字符。

其次,可能需要花费不少内存来存储空格,如果图像其中某一行明显比其他各行长得多,那么这一开销就不容忽视了。

最后,该方案将所有图像内部结构信息都丢掉了。


下一章,将重新设计。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值