036:很难蒙混过关的CArray3d三维数组模板类

本文解析了一道编程题,涉及C++模板类的高级用法,如何将一维数组折叠成三维数组,并重点讲解了对象到指针的强制类型转换和内存管理技巧。实例代码展示了如何使用CArray3D模板类完成数组折叠,并演示了如何正确地对内部对象进行memset操作。
摘要由CSDN通过智能技术生成

题目:

http://cxsjsxmooc.openjudge.cn/2021t3springall2/036/

分析:

说实话这道题知识点都不难,难就难在新,在模版类里面建类(写完之后才发现老师在视频里讲过这种情况,所以,遇到问题应该先翻翻讲义。)

思路:本质上是将一个一维数组折叠成一个三维数组,难点主要是在三个 “[ ]” 怎么处理,第一个[ ] 在 CArray3D 类中返回 CArray2D类,然后第二个[ ] 再在 CArray2D类 中返回一个数组指针,第三个[ ]则直接根据上一步的指针取值,这就实现了老师题目中的 提示1: a[i][j][k] 这个表达式的第一个[]返回一个内部类的对象,该内部类也重载了[],且返回值为指针。

还有提示2: 必要时需重载对象到指针的强制类型转换运算符。 这个主要是因为根据上面的定义,第一个[ ] 在 CArray3D 类中返回的是 CArray2D类,但在下面的memset()函数中对a[1]进行了赋值,显然不能对类变量进行memset,则需使用重载对象到指针的强制类型转换运算符。

 

参考代码:

#include <iostream>
#include <iomanip>
#include <cstring>
using namespace std;
template <class T>
class CArray3D {
// 在此处补充你的代码
private:
    T *p;
    int x, y, z;
public:
    CArray3D(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {
        p = new T[x * y * z];
    }

    ~CArray3D() {
        delete[]p;
    }

    class CArray2D {
    private:
        T * x2p; //第x层
        int z2;
    public:
        CArray2D(T * _x2p,int _z):x2p(_x2p),z2(_z){}
        T * operator[](int y2){
            return x2p + y2 * z2;
        }
        operator T*(){
            return x2p;//重载对象到指针的强制类型转换运算符
        }
    };

    CArray2D operator[](int i){
        T * x2p = p + i * y * z;
        return  CArray2D(x2p,z);
    }
};

CArray3D<int> a(3,4,5);  //初始化参数表为3个整数。
CArray3D<double> b(3,2,2);
void PrintA()
{
    for(int i = 0;i < 3; ++i) {
        cout << "layer " << i << ":" << endl;
        for(int j = 0; j < 4; ++j) {
            for(int k = 0; k < 5; ++k)
                cout << a[i][j][k] << "," ;
            cout << endl;
        }
    }
}
void PrintB()
{
    for(int i = 0;i < 3; ++i) {
        cout << "layer " << i << ":" << endl;
        for(int j = 0; j < 2; ++j) {
            for(int k = 0; k < 2; ++k)
                cout << b[i][j][k] << "," ;
            cout << endl;
        }
    }
}

int main()
{

    int No = 0;
    for( int i = 0; i < 3; ++ i ) {
        a[i];//得重载[],返回的是指针
        for( int j = 0; j < 4; ++j ) {
            a[j][i];
            for( int k = 0; k < 5; ++k )
                a[i][j][k] = No ++; //难点,如何实现
            a[j][i][i];
        }
    }
    PrintA();
    memset(a[1],-1 ,20*sizeof(int));//对1层进行写-1,20个
    //根据上述定义,a[1]是一个对象,是不能直接用于初始化的,需要通过类型转换函数,将对象转换成指针。
    memset(a[1],-1 ,20*sizeof(int));//同上
    PrintA();
    memset(a[1][1],0 ,5*sizeof(int));//对1层的1行写0,5个
    PrintA();

    for( int i = 0; i < 3; ++ i )
        for( int j = 0; j < 2; ++j )
            for( int k = 0; k < 2; ++k )
                b[i][j][k] = 10.0/(i+j+k+1);
    PrintB();
    int n = a[0][1][2];
    double f = b[0][1][1];
    cout << "****" << endl;
    cout << n << "," << f << endl;

    return 0;
}

注:以上代码虽然通过了OpenJudge的样例测试,但受限于本人水平,如有疏漏,恳请斧正。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值