实验6 模板类、文件I/O和异常处理

1. 实验任务1

验证性实验

知识点:

  • 创建文件并输出内容:
    ofstream out("ans.txt");
    //ofstream允许程序将数据写入文件;
    //out("ans.txt")创建一个名为ans.txt的文件,并将这个文件与名为out的ofstream对象关联起来
    out << "Hello, world!" << std::endl;//在文件中写入Hello, world!
    out << a << std::endl;//在文件中写入变量a
    out.close();//调用close()方法关闭文件流

     

2. 实验任务2

验证性实验

知识点:

  • 从文件中读取:
    ifstream in(filename);
    getline(in, title_line);     // 跳过标题行
    int first_column;
    Contestant t;                //类
    while(in >> first_column >> t) //之前重载了>>
        v.push_back(t);

     

  • 保存数据到文件:
    // 把vector<Constestant>对象中的元素插入到输出流out
    void output(std::ostream &out, const std::vector<Contestant> &v) {
        for(auto &i: v)
            out << i << std::endl;
    }
    
    
    // 把vector<Contestant>对象中的元素写到filename文件中
    void save(const std::string &filename, std::vector<Contestant> &v) {
        using std::ofstream;
        ofstream out(filename);
        output(out, v);
        out.close();
    }

     

3. 实验任务3

验证性实验

知识点:

  • trycatch
    try {
        Triangle t(a, b, c);//尝试创建一个名为t的Triangle类的对象,并传入参数
        cout << "三角形面积: " << t.area() << endl << endl;//如果成功创建了三角形对象t
    }catch(const exception &e) {//catch块用于捕获所有类型的标准异常,当try块中的代码抛出异常时,这个catch块会被执行
        cout << "error: " << e.what() << endl << endl;
    }
    //在Triangle类的初始化函数中有:
    if(a <= 0 || b <= 0 || c <= 0)
    	throw invalid_argument("边长出现负值");//抛出异常
    	
    if(a+b <= c || b+c <= a || a+c <= b) 
    	throw invalid_argument("不满足任意两边之和大于第三边");
  • peek()函数:peek()函数用于查看输入流中的下一个字符,但并不实际提取它。如果没有更多字符可供读取,peek()将返回特殊值EOF
    if(in.peek() == EOF)
        break;

 

4. 实验任务4

Vector.hpp源代码:

#include<iostream>
#include <stdexcept>
#include <vector>

template <typename T>
class Vector {
private:
    T* elements;
    int capacity;

public:
    Vector(int size = 0) : capacity(size) {
        if (size < 0) {
            throw std::length_error("negative size");
        }
        elements = new T[size];
    }

    Vector(int size, T value) : capacity(size) {
        if (size < 0) {
            throw std::length_error("negative size");
        }
        elements = new T[size];
        for (int i = 0; i < size; ++i) {
            elements[i] = value;
        }
    }

    Vector(const Vector<T>& other) : capacity(other.capacity) {
        elements = new T[capacity];
        for (int i = 0; i < capacity; ++i) {
            elements[i] = other.elements[i];
        }
    }

    ~Vector() {
        delete[] elements;
    }

    //其它成员函数
    int get_size() const {
        return capacity;
    }

    T& at(int index) {//返回值类型是T&,即对模板类型T的引用,意味着函数返回的是对存储在Vector中的元素的引用
        if (index >= capacity) {
            throw std::out_of_range("index out of range");
        }
        return elements[index];
    }

    T& operator[](int index) {
        return at(index);
    }

    template <typename T>
    friend void output(const Vector<T>& V);
};

template <typename T>
void output(const Vector<T>& V) {//Vector<T> 类型对象的常量引用
    for (int i = 0; i < V.capacity; ++i) {
        std::cout << V.elements[i] << " ";
    }
    std::cout << std::endl;
}

task4.cpp源代码:

#include <iostream>
#include "Vector.hpp"

void test1() {
    using namespace std;

    int n;
    cout << "Enter n: ";
    cin >> n;
    
    Vector<double> x1(n);
    for(auto i = 0; i < n; ++i)
        x1.at(i) = i * 0.7;

    cout << "x1: "; output(x1);

    Vector<int> x2(n, 42);
    const Vector<int> x3(x2);

    cout << "x2: "; output(x2);
    cout << "x3: "; output(x3);

    x2.at(0) = 77;
    x2.at(1) = 777;
    cout << "x2: "; output(x2);
    cout << "x3: "; output(x3);
}

void test2() {
    using namespace std;

    int n, index;
    while(cout << "Enter n and index: ", cin >> n >> index) {
        try {
            Vector<int> v(n, n);
            v.at(index) = -999;
            cout << "v: "; output(v);
        }
        catch (const exception &e) {
            cout << e.what() << endl;
        }
    }
}

int main() {
    std::cout << "测试1: 模板类接口测试\n";
    test1();

    std::cout << "\n测试2: 模板类异常处理测试\n";
    test2();
}

运行截图:

 

5. 实验任务5

task5.cpp源代码:

#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <string>
#include <fstream>
#include <algorithm>

class Student {
public:
    std::string no;          //学号
    std::string name;        //姓名
    std::string major;       //专业
    int score;               //分数

    //重载流插入运算符<<
    friend std::ostream& operator<<(std::ostream& out, const Student& s);

    //重载流提取运算符>>
    friend std::istream& operator>>(std::istream& in, Student& s);
};

std::ostream& operator<<(std::ostream& out, const Student& s) {
    out << std::left;
    out << std::setw(15) << s.no
        << std::setw(15) << s.name
        << std::setw(15) << s.major
        << std::setw(5) << s.score;
    return out;
}

std::istream& operator>>(std::istream& in, Student& s) {
    in >> s.no >> s.name >> s.major >> s.score;
    return in;
}

//比较函数,用于排序
bool compareStudents(const Student& a, const Student& b) {
    if (a.major < b.major) return true;
    else if (a.major == b.major && a.score > b.score) return true;
    return false;
}

int main() {
    std::vector<Student> students;
    // 从data5.txt读取数据
    std::ifstream inFile("data5.txt");
    if (!inFile.is_open()) {
        std::cout << "fail to open file to write\n";
        return 0;
    }
    if (inFile) {
        std::string title_line;
        std::getline(inFile, title_line);     // 跳过标题行

        Student s;
        while (inFile >> s)
            students.push_back(s);

        inFile.close();
    }

    // 排序
    std::sort(students.begin(), students.end(), compareStudents);

    // 输出到屏幕并保存到ans5.txt
    std::ofstream outFile("ans5.txt");
    if (outFile) {
        for (auto& i : students) {
            std::cout << i << std::endl;
            outFile << i << std::endl;
        }
        outFile.close();
    }

    return 0;
}

运行截图:

 

实验总结:

本次实验综合运用到了trycatch函数、peek()函数、模板类、文件的输入与输出等,实验4中的模板类令我印象深刻:T& at(int index);该函数返回值类型是T&,即对模板类型T的引用,意味着函数返回的是对存储在Vector中的元素的引用,这是第一次遇到这样的类型。实验5综合运用了各种知识,包括运算符重载、文件输入输出等,特别是对c++库中的sort函数的应用,实现了对与多项项目的排序,很有意义。

posted @ 2024-12-17 21:07  Sunria  阅读(5)  评论(0编辑  收藏  举报