T1469 ArrayList

文章描述了一个编程任务,要求创建一个名为ArrayList的模板类,以解决C++原生数组的局限,如下标越界检查、数组拼接和输出。该类需要支持构造函数、拷贝构造、大小查询、元素访问、数组拼接、赋值以及输出重载。同时,必须处理异常情况,如非法长度和下标越界,并提供相应的错误信息。示例展示了如何使用这个类以及预期的异常处理和输出格式。
摘要由CSDN通过智能技术生成

题目描述

Rainy Memory 嫌弃 C++ 的数组很久了:不仅不会检查下标越界,也没有数组拼接、数组输出等方便的功能。学习了 OOP 知识的你,可不可以写一个类帮他解决这个问题呢?

你需要完成一个模板类 ArrayList ,有且仅有一个模板参数 T ,为数组中元素的类型。

这个类需要支持以下功能:

  • 构造函数
    • 从已有的数组构造:参数 T* arr, int length , length 为 arr 的长度
    • 构造一个固定长度的数组:参数 int length,其中的元素应调用其默认构造函数
    • 拷贝构造函数(深拷贝,需要复制元素的值)
  • 析构函数
  • 成员函数 size() ,返回数组大小。
  • operator[] 的重载,支持通过 [] 赋值与得到数组元素(需要同时完成左值与右值的重载)。
  • operator+ 的重载,拼接两个数组,原来的两个数组不应该改变
  • operator= 的重载,将本数组赋值为另一个数组,需要支持连续赋值。(同拷贝构造函数一样是深拷贝)
  • operator==, != 的重载,数组相同的判定条件是长度与对应位元素均相等
  • operator<< 的重载,格式为使用一个空格隔开数组中的所有元素,不输出换行符
    • 在评测时,程序的任何输出都将通过调用 printList 函数来实现(见下方代码,略去了模板相关的内容)。因此,如果你没有完成operator<< 的重载,你也可以利用给定的print函数并注释掉#define USE_OS以使得评测能够正常进行,否则可能产生编译错误。print函数同样按照格式输出到cout,不输出换行符。

题面补充:如果你要测试 operator<< 的重载,需要在你提交的代码开头加上 #define USE_OS

void printList(ArrayList list) {
#ifdef USE_OS
    std::cout << list << "\n";
#else
    list.print();
    std::cout << "\n";
#endif
}

保证模板参数 T 有默认构造函数,支持 operator==, <<, = 。

同时需要在出现问题时抛出异常。我们提供以下异常类:

class error : public std::exception {
private:
    std::string msg;

public:
    explicit error(const char *_msg_) : msg(_msg_) {}

    const char *toString() {
        return msg.c_str();
    }
};

可能出现的异常有:

  • 下标越界:下标为 0-based ,若下标越界抛出 index out of bound
  • 初始化长度非法:若构造函数中 length < 0 ,抛出 invalid length

调用示例

#include "ArrayList.hpp"
...
    try {
        ArrayList<char> list_err(-1);
    } catch (error &e) {
        std::cout << e.toString() << std::endl;
    }

    ArrayList<int> list(5);

    try {
        list[-1];
    } catch (error &e) {
        std::cout << e.toString() << std::endl;
    }
    try {
        list[2000];
    } catch (error &e) {
        std::cout << e.toString() << std::endl;
    }

    for (int i = 0; i < list.size(); i++) list[i] = i;
    printList(list);
    ArrayList<int> temp = list;
    printList(temp);
    temp = list;
    printList(temp);
    if (temp == list) std::cout << "true" << std::endl;

    int arr[5] = {4, 215, 12, 84, 76};
    const ArrayList<int> list_const(arr, 5);
    std::cout << list_const[3] << std::endl;
    printList(list_const);

    printList(list_const + list);

    return 0;
...

样例输出

invalid length
index out of bound
index out of bound
0 1 2 3 4
0 1 2 3 4
0 1 2 3 4
true
84
4 215 12 84 76
4 215 12 84 76 0 1 2 3 4

输入格式

你不需要处理输入,可以参考上述调用示例。

输出格式

你不需要处理输出,可以参考上述调用示例。

数据范围

check point数据特征
1同调用样例
2仅检测异常处理
3鲁棒性
4主要考察+,size
5流输出运算符重载
6元素默认构造函数的调用
7 ~ 12内容同上述1 ~ 6,检查内存泄漏,共20分

时空磁盘限制(运行时)

时间限制: 3000 ms

内存空间限制: 244 MiB

磁盘空间限制: 无限制

题目解答:

如果多次throw会导致Memory Leak 蛮难找的提交了七八次才凑出来

以及鲁棒性方面 =重载考虑自身不然delete自己再new会导致赋值不对WA

#include<iostream>
#include<cstdio>
#define USE_OS

using namespace std;
class error : public std::exception {

private:
    std::string msg;

public:
    explicit error(const char *_msg_) : msg(_msg_) {}

    const char *toString() {
        return msg.c_str();
    }
};


template<typename T>
class ArrayList
{
    
public:
    T *data;
    int length;
    ArrayList(T *arr, int len)
    {
        if (len<0) throw error("invalid length");
        length=len;
        data=new T[length];
        int i;
        for (i=0;i<length;i++)
            data[i]=arr[i];

    }
    ArrayList(int len)
    {
        if (len<0) throw error("invalid length");
        length=len;
        data=new T[length];
    }
    ArrayList(const ArrayList &b)
    {
        if (b.length<0) throw error("invalid length");
        length=b.length;
        data=new T[length];
        int i;
        for (i=0;i<length;i++)
            data[i]=b.data[i];
    }
    ~ArrayList()
    {
        length=0;
        delete []data;
    }
    int size()
    {
        if (length<0) throw error("invalid length");
        return this->length;
    }
    const T &operator[](int index) const
    {
        if (index>=this->length || index<0) throw error("index out of bound");
        return this->data[index];
    }
    T &operator[](int index)
    {
        if (index>=this->length || index<0) throw error("index out of bound");
        return this->data[index];
    }
    bool operator==(const ArrayList &b)
    {
        if (!(b.length==this->length)) return false;
        int i;
        for (i=0;i<this->length;i++)
            if (!(this->data[i]==b.data[i])) return false;
        return true;
    }
    bool operator!=(const ArrayList &b)
    {
        if (!(b.length==this->length)) return true;
        int i;
        for (i=0;i<this->length;i++)
            if (!(this->data[i]==b.data[i])) return true;
        return false;
    }
    ArrayList &operator=(const ArrayList &a)
    {
        int i;
        if (*this==a) return *this;
        delete []data;
        length=a.length;
        data=new T[a.length];
        for (i=0;i<a.length;i++) this->data[i]=a.data[i]; 
        return *this;
    }
};
template<typename T>
ArrayList<T> operator+(const ArrayList<T> &a,const ArrayList<T> &b)
    {
        ArrayList<T> t(a.length+b.length);
        int i;
        for (i=0;i<a.length;i++) t.data[i]=a.data[i];
        for (i=a.length;i<a.length+b.length;i++) t.data[i]=b.data[i-a.length];
        return t;
    }


template<typename T>
ostream &operator <<(ostream &os, const ArrayList<T> &obj)
{
    int i;
    for (i=0;i<obj.length;i++) os<<obj.data[i]<<' ';
    return os;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值