实验六 模板类,文件io和异常处理

发布时间 2023-12-17 21:51:53作者: 小程夏天

实验任务4

#pragma once
#include <iostream>
#include <stdexcept>

using std::cout;
using std::endl;


template <typename T>
class Vector {
public:
    // 构造函数,默认大小为0
    Vector(int n = 0) : size(n), data(new T[n]) {   
        if (n < 0) {
        throw std::length_error("Vector<T> constructor: negative size");
        }
    }

    // 构造函数,指定大小和初始值
    Vector(int n, T value) : size(n), data(new T[n]) {
        if (n < 0) {
        throw std::length_error("Vector<T> constructor: negative size");
        }
        for (int i = 0; i < n; ++i) {
        data[i] = value;
        }
    }

    // 拷贝构造函数(深复制)
    Vector(const Vector& other) : size(other.size), data(new T[other.size]) {
        for (int i = 0; i < size; ++i) {
        data[i] = other.data[i];
        }
    }

    // 析构函数
    ~Vector() {
        delete[] data;
    }

    // 返回数组中元素的个数
    int getSize() const {
        return size;
    }

    // 通过索引访问元素
    T& at(int index) {
        validateIndex(index);
        return data[index];
    }

    const T& at(int index) const {
         if (index < 0 || index >= size) {
        throw std::out_of_range("Index out of range");
        }
        validateIndex(index);
        return data[index];
    }

    // 重载下标操作符
    T& operator[](int index) {
        return at(index);
    }

    const T& operator[](int index) const {
         if (index < 0 || index >= size) {
        throw std::out_of_range("Index out of range");
        }
        return at(index);
    }

    template <typename U>
    friend void output(const Vector<U>& vec);

private:
    int size;  // 数组的当前大小
    T* data;   // 指向动态分配数组的指针

    void validateIndex(int index) const {
        if (index < 0 || index >= size) {
        throw std::out_of_range("Index out of range");
        }
    }
};

template <typename U>
void output(const Vector<U>& vec) {
    for (int i = 0; i < vec.size; ++i) {
    cout << vec.data[i] << ", ";
    }
    if (vec.size > 0) {
    cout << "\b\b ";
    }
    cout << endl;
}
task4.hpp
#include <iostream>
#include "task4.hpp"
void test() {
using namespace std;
int n;
cin >> n;
Vector<double> x1(n);
for(auto i = 0; i < n; ++i)
x1.at(i) = i * 0.7;
output(x1);
Vector<int> x2(n, 42);
Vector<int> x3(x2);
output(x2);
output(x3);
x2.at(0) = 77;
output(x2);
x3[0] = 999;
output(x3);
}
int main() {
test();
}
task4.cpp

//收获,了解了三个函数的区别
非常量成员函数 (int& get(int index)):当你需要修改 Vector 中的元素时使用。如果你要更新 Vector 中的某个值,这个合适.

常量引用返回的非常量成员函数 (const int& getConst(int index)):当你需要读取但不修改 Vector 中的元素时提供了一个安全的方式来访问元素,防止不小心修改它们。

常量成员函数 (const int& getConst(int index) const):当你在一个常量(例如在一个接收 const Vector& 参数的函数内)时使用。这确保了即使在这种上下文中,你也能读取 Vector 中的元素,同时保证不会修改 Vector 的状态。

 

实验任务5

#include <iostream>
#include <fstream>
#include <iomanip>

void output(std::ostream &out) {
    for (int i = 0; i <=26; ++i) {
       
        if (i == 0) { out<<"   ";
            for (char ch = 'a'; ch <= 'z'; ++ch) {
                out << ch << ' ';
            }
            out << '\n';
            continue;
        }
        
      
        out << std::setw(2) << i << ' ';
        

        for (int j = 0; j < 26; ++j) {
         
            out << char('A' + (j + i ) % 26) << ' ';
        }
        out << '\n';  
    }
}

int main() {
    output(std::cout);

    std::ofstream file_out("cipher_key.txt");
    if (file_out.is_open()) {
        output(file_out);
    } else {
        std::cerr << "Error opening the file for writing." << std::endl;
    }
    file_out.close();

    return 0;
}
View Code

相比与传统的用两个封装函数void save_to_file(){}和void load_from_file(){}这种编写方式极大的缩减了代码的长度,并且在一开始先用cout传递参数,在显示器输出后面所要保存的文本数据,实现了快速解决问题和要求的能力。但是弊端就是逻辑思路不清晰,没有体现封装的特性。