首页 > 其他分享 >实验6 模板类,文件I/O及异常处理

实验6 模板类,文件I/O及异常处理

时间:2024-12-24 10:42:57浏览次数:3  
标签:std 文件 const Vector get Complex 实验 include 模板

一 实验目的

  1. 练习编写模板函数、模板类,从多态角度理解模板函数和模板类(类型作为参数)
  2. 体验标准I/O流类、文件I/O流类、字符串I/O流类的用法,能正确使用
  3. 针对问题场景,使用流类库对I/O数据进行格式化和读、写操作
  4. 体验异常处理的基础用法,能解释异常处理的机制和流程
  5. 训练综合应用类的封装、继承、多态特性及现代C++标准库编写正确、高效、安全代码

二 实验步骤

task1

complex.hpp

#pragma once

#include <iostream>
#include <stdexcept>

// 声明
////////////////////////////////////////////////////
// 复数模板类声明
template<typename T>
class Complex {
public:
    Complex(T r = 0, T i = 0);
    Complex(const Complex<T> &c);

    T get_real() const;
    T get_imag() const;

    // 重载+=为成员函数
    Complex<T>& operator+=(const Complex<T> &c);

    // 重载<<、>>为友元函数
    template<typename T1>
    friend std::ostream& operator<<(std::ostream &out, const Complex<T1> &c);

    template<typename T1>
    friend std::istream& operator>>(std::istream &in, Complex<T1> &c);

private:
    T real, imag;
};

// 普通函数声明
// 重载+用于Complex类型
template<typename T>
Complex<T> operator+(const Complex<T> &c1, const Complex<T> &c2);

// 重载==用于Complex类型
template<typename T>
bool operator==(const Complex<T> &c1, const Complex<T> &c2);


// 实现
////////////////////////////////////////////////////
// 成员函数模板实现
template<typename T>
Complex<T>::Complex(T r, T i): real{r}, imag{i} {
}

template<typename T>
Complex<T>::Complex(const Complex<T> &c): real{c.real}, imag{c.imag} {
}

template<typename T>
T Complex<T>::get_real() const {
    return real;
}

template<typename T>
T Complex<T>::get_imag() const {
    return imag;
}

// 重载+=为成员函数
template<typename T>
Complex<T>& Complex<T>::operator+=(const Complex<T> &c) {
    real += c.real;
    imag += c.imag;

    return *this;
}

///////////////////////////////////////
// 友元函数模板实现
template<typename T1>
std::ostream& operator<<(std::ostream &out, const Complex<T1> &c) {
    if(c.imag >= 0)
        out << c.real << " + " << c.imag << "i";
    else
        out << c.real << " - " << -c.imag << "i";
    
    return out;
}

template<typename T1>
std::istream& operator>>(std::istream &in, Complex<T1> &c) {
    in >> c.real >> c.imag;

    return in;
}

///////////////////////////////////////
// 普通函数模板实现
// 重载+用于Complex类型
template<typename T>
Complex<T> operator+(const Complex<T> &c1, const Complex<T> &c2) {
    return Complex<T>(c1.get_real()+c2.get_real(), 
                      c1.get_imag()+c2.get_imag());
}

// 重载==用于Complex类型
template<typename T>
bool operator==(const Complex<T> &c1, const Complex<T> &c2) {
    return c1.get_real() == c2.get_real() && 
           c1.get_imag() && c2.get_imag();
}

task1.cpp

#include "Complex.hpp"
#include <iostream>
#include <fstream>
#include <stdexcept>

void test1();
void test2();

int main() {
    using namespace std;

    cout << "测试1: 复数模板类测试" << endl;
    test1();

    cout << "\n测试2: 文件I/O测试" << endl;
    test2();
}

void test1() {
    using namespace std;

    Complex<double> c1{3.5, 2}, c2;
    cout << "Enter c2: ";
    cin >> c2;
    cout << "c1 = " << c1 << endl;
    cout << "c2 = " << c2 << endl;
    cout << "c1 == c2: " << boolalpha << (c1 == c2) << endl;

    cout << "c1 + c2 = " << c1 + c2 << endl;
    c1 += c2;
    cout << "c1.real = " << c1.get_real() << endl;
    cout << "c1.imag = " << c1.get_imag() << endl;

    cout << "c1 == c2: " << boolalpha << (c1 == c2) << endl;
}

void test2() {
    using namespace std;

    Complex<int> c1{1, 2}, c2{9, -7};
    ofstream out("ans.txt");
    if(!out.is_open()) {
        cout << "fail to open file ans.txt to write\n";
        return;
    }

    out << "c1 = " << c1 << endl;
    out << "c2 = " << c2 << endl;
    out << "c1 + c2 = " << c1 + c2 << endl;
    out << "(c1 == c2) = " << boolalpha << (c1 == c2) << endl;

    out.close();
    cout << "测试ok!" << endl;
}

task2

contestant.hpp

#pragma once

#include <iostream>
#include <iomanip>
#include <string>

using std::string;
using std::ostream;
using std::istream;
using std::setw;
using std::setprecision;
using std::setiosflags;
using std::ios_base;

// Contestant类声明
class Contestant {
public:
    Contestant() = default;
    ~Contestant() = default;

    int get_num() const { return num; }
    float get_time_usage() const { return time_usage; }

    friend ostream& operator<<(ostream &out, const Contestant &c);
    friend istream& operator>>(istream &in, Contestant &c);

private:
    string no;          // 学号
    string name;        // 姓名
    string major;       // 专业
    int num;            // 解题数
    float time_usage;   // 总用时
};

// 友元函数实现
// 重载流插入运算符<<
ostream& operator<<(ostream &out, const Contestant &c) {
    out << setiosflags(ios_base::left);
    out << setw(15) << c.no
        << setw(15) << c.name
        << setw(15) << c.major
        << setw(5) << c.num
        << setprecision(2) << c.time_usage;
    
    return out;
}

// 重载流提取运算符>>
istream& operator>>(istream &in, Contestant &c) {
    in >> c.no >> c.name >> c.major >> c.num >> c.time_usage;

    return in;
}

utils.hpp

#include "Contestant.hpp"
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

// 排序函数
// 按解题数比较,解题数相同的情况下,按总用时比较,总用时越少,排名越靠前
bool compare_by_solutionInfo(const Contestant &c1, const Contestant &c2) {
    if(c1.get_num() > c2.get_num())
        return true;
    
    if(c1.get_num() == c2.get_num())
        return c1.get_time_usage() < c2.get_time_usage();
    
    return false;
}

// 把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);
    if(!out.is_open()) {
        std::cout << "fail to open file to write\n";
        return;
    }

    output(out, v);
    out.close();
}

// 从文件filename读取参赛选手信息到vector<Contestant>对象
void load(const std::string &filename, std::vector<Contestant> &v) {
    using std::ifstream;

    ifstream in(filename);
    if(!in.is_open()) {
        std::cout << "fail to open file to read\n";
        return;
    }

    std::string title_line;
    getline(in, title_line);     // 跳过标题行

    int first_column;
    Contestant t;
    while(in >> first_column >> t) 
        v.push_back(t);

    in.close();
}

task2.cpp

#include "Contestant.hpp"
#include "utils.hpp"
#include <iostream>
#include <vector>
#include <algorithm>


void test() {
    using namespace std;

    vector<Contestant> v;

    load("data2.txt", v);   // 从文件加载选手信息到对象v
    sort(v.begin(), v.end(), compare_by_solutionInfo);  // 按解题情况排序
    output(cout, v);    // 输出对象v中信息到屏幕
    save("ans.txt", v); // 把对象v中选手信息保存到文件
}

int main() {
    test();
}

task3

traingle.hpp

#include <iostream>
#include <stdexcept>
#include <cmath>

using namespace std;

class Triangle {
public:
    Triangle(double s1, double s2, double s3);
    ~Triangle() = default;

    double area() const;

private:
    double a, b, c;
};

Triangle::Triangle(double s1, double s2, double s3): a{s1}, b{s2}, c{s3} {
    if(a <= 0 || b <= 0 || c <= 0)
        throw invalid_argument("边长出现负值");
        
    if(a+b <= c || b+c <= a || a+c <= b) 
        throw invalid_argument("不满足任意两边之和大于第三边");
}

double Triangle::area() const {
    double s = (a + b + c)/2;
    return sqrt(s*(s-a)*(s-b)*(s-c));
}

task3.cpp

#include "Triangle.hpp"
#include <iostream>
#include <fstream>

void test() {
    using namespace std;

    cout << "从文件读入三角形三边边长,计算面积" << endl;

    ifstream in("data3.txt");
    if(!in.is_open()) {
        cout << "fail to open file to read\n";
        return;
    }

    double a,b,c;
    do {
        cout << "三角形边长: ";
        in >> a >> b >> c;
        cout << a << " " << b << " " << c << endl;

        try {
            Triangle t(a, b, c);
            cout << "三角形面积: " << t.area() << endl << endl;
        }catch(const exception &e) {
            cout << "error: " << e.what() << endl << endl;
        }

        if(in.peek() == EOF)
            break;
    } while(1);

    in.close();
}

int main() {
    test();
}


task4
vector.hpp

#pragma once
#include<iostream>
#include<stdexcept>
using namespace std;

template<typename T>
class Vector
{
private:
    int size;
    T* ptr;
public:
    Vector(int n);
    Vector(int n, T value);
    Vector(const Vector<T>& v);
    ~Vector();

    int get_size()
    {
        return size;
    }

    T& at(int index)const;
    T& at(int index);

    T& operator[](int index)const;
    T& operator[](int index);

    template<typename T1>                             
    friend void output(const Vector<T1>& v);
};

template<typename T>
Vector<T>::Vector(int n) :size(n)
{
    if (n < 0)
   {
        throw length_error("Vector constructor:negative size");
    }
    else
    {
        ptr = new T[size];
    }
}


template<typename T>
Vector<T>::Vector(int n,T value):size(n)
{

    if (n < 0)
    {
        throw length_error("Vector constructor:negative size");
    }
    else
    {
        ptr = new T[size];
        for (int i = 0; i < size; i++)
        {
            ptr[i] = value;

        }
    }


}

template<typename T>
Vector<T>::Vector(const Vector<T>& v):size(v.size),ptr(new T[size])
{
    for (int i = 0; i < size; i++)
    {
        ptr[i] = v.ptr[i];
    }

}

template<typename T>
Vector<T>::~Vector()
{

    delete[]ptr;
}

template<typename T>
T& Vector<T>::at(int index)const
{
    if (index < 0 || index >= size)
    {
        throw out_of_range("Vector:index out of range");
    }
    else
    {
        return ptr[index];
    }

}

template<typename T>
T& Vector<T>::at(int index)
{
    return static_cast<const Vector*>(this)->at(index);

}

template<typename T>
T& Vector<T>::operator[](int index)const
{
    if (index < 0 || index >= size)
    {
        throw out_of_range("Vector:index out of range");
    }
    else
    {
        return ptr[index];
    }

}
template<typename T>
T& Vector<T>::operator[](int index)
{
    return static_cast<const Vector*>(this)->operator[](index);

}

template<typename T>
 void output(const Vector<T>& v)
{
     for (int i = 0; i < v.size; i++)
     {
         cout << v.ptr[i] << ", ";
     }
     cout <<"\b\b " << endl;

}

task4.cpp

#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() {
    cout << "测试1: 模板类接口测试\n";
    test1();

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


task5
people.hpp

#pragma once
#include<iostream>
#include<string>
#include<iomanip>

using namespace std;

class people
{
private:
    int xuehao;
    string name;
    string major;
    int score;
public:
    people() = default;
    ~people() = default;

    string get_major()const
    {
        return major;
    }
    int get_score()const
    {
        return score;
    }

    friend ostream& operator<<(ostream& out, people& p);
    friend istream& operator>>(istream& in, people& p);


};

ostream& operator<<(ostream& out, people& p)
{
    out << setiosflags(ios_base::left);
    out << setw(10) << p.xuehao
        << setw(10) << p.name
        << setw(10) << p.major
        << setw(10) << p.score << endl;
    return out;

}

istream& operator>>(istream& in, people& p)
{
    in >> p.xuehao >> p.name >> p.major >> p.score;
    return in;



}

tools.hpp

#pragma once
#include"people.hpp"
#include<iostream>
#include<string>
#include<fstream>
#include<vector>

bool paixu(const people& p1, const people& p2)
{
    if (p1.get_major() < p2.get_major())
    {
        return true;
    }
    if (p1.get_major() == p2.get_major())
    {
        return p1.get_score() > p2.get_score();

    }
    return false;

}

void output(ostream& out, vector<people>& v)
{
    for (auto& i : v)
    {
        out << i;
    }

}

void save(const string& filename, vector<people>& v)
{
    ofstream out(filename);
    if (!out.is_open())
    {
        cout << "文件写入失败" << endl;
        exit(0);
    }

    output(out, v);
    out.close();

}

void load(const string& filename, vector<people>& v)
{
    ifstream in(filename);

    if (!in.is_open())
    {
        cout << "文件读出失败" << endl;
        exit(0);
    }

    string firstline;
    getline(in, firstline);
    people p;
    while (in >> p)
    {
        v.push_back(p);
    }

    in.close();
}

task5.cpp

#include"people.hpp"
#include"tools.hpp"
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>

int main()
{

    vector<people> v;
    load("data5.txt", v);
    sort(v.begin(), v.end(), paixu);

    output(cout, v);
    save("ans.txt", v);


    return 0;
}
```![](/i/l/?n=24&i=blog/3533458/202412/3533458-20241224103652016-1547751231.png)

标签:std,文件,const,Vector,get,Complex,实验,include,模板
From: https://www.cnblogs.com/fantasies31/p/18626847

相关文章

  • 面向教学科研智能网联汽车仿真测试实验室
    概述    随着智能网联汽车的蓬勃发展,高校培养相关人才的需求日益迫切。然而,传统教学设备难以满足实际工程应用需求,限制了学生实践能力和科研创新。为此,经纬恒润推出高校智能网联汽车仿真测试解决方案,为高校提供与产业接轨的全栈式解决方案,助力科研项目、人才培养和教学模......
  • 软件项目《光灵斗域》实验报告
    软件项目《光灵斗域》实验报告分工:陈艺根:卡牌效果,卡牌逻辑,随机地图设计,UI框架,音频管理王朗凡:游戏策划,游戏背包UI肖宇轩:游戏中数据处理袁瑶:美术,场景过渡的代码夏亦轩:TA,着色器编程,地图设计,敌人设计相关文档游戏网页光灵斗域PC/主机-TapTap策划案https://bxqu4udvl43.fe......
  • Flutter OHOS open_filex(以字符串结果打开文件)
    open_filex以字符串结果打开文件的插件用法要使用此插件,请在pubspec.yaml文件中添加open_filex作为依赖项。dependencies:open_filex:^lastVersion例子import'package:open_filex/open_filex.dart';OpenFilex.open("/sdcard/example.txt");鸿蒙OS代码文件是否......
  • 文件系统
    文件系统文件系统是小程序提供的一套以小程序和用户维度隔离的存储以及一套相应的管理接口。通过wx.getFileSystemManager()可以获取到全局唯一的文件系统管理器,所有文件系统的管理操作通过FileSystemManager来调用。varfs=wx.getFileSystemManager()文件主要分为两大......
  • C#队列、多线程根据URL下载文件
    ///<summary>///下载辅助类///</summary>publicclassDownFileHelper{///<summary>///构造函数///</summary>staticDownFileHelper(){Start();}privatestaticobjectlockObject=newobject();......
  • 这款跨网文件安全交换系统 凭什么受到各行业的欢迎?
    跨隔离网的文件传输交换,这是各个行业都会面临的场景,能解决传输问题的工具也不少,可为什么说有一款跨网文件安全交换系统,在各行业中应用都很广泛,受到各行业的欢迎呢?首先我们来看看跨网文件传输有哪些需求。 一、跨网文件传输的普遍需求跨网文件传输的普遍需求与挑战可以概括为以......
  • 实验6
    实验任务1:Complex,hpp:1#pragmaonce23#include<iostream>4#include<stdexcept>56template<typenameT>7classComplex{8public:9Complex(Tr=0,Ti=0);10Complex(constComplex<T>&c);1112......
  • Linux文件目录 --- 复制命令CP、递归复制目录、软连接、硬链接
    一、复制cp该命令用于复制文件或目录,下面是命令使用格式和常用的参数cp[参数]源文件或目录目标文件或目录                      #中间各有一个空格隔开参数作用-f覆盖同名文件或目录时不进行提醒-i          ......
  • python代码在生产环境部署有必要打包.so文件吗?(python打包so、python so)共享对象文件
    文章目录1.性能优化优点:-加速执行-减少解释开销缺点:-有限的性能提升-优化复杂度2.代码保护优点:-防止源码泄露缺点:-并非完全安全-增加部署复杂度3.部署和依赖管理优点:-打包依赖-跨平台支持缺点:-平台依赖性-维护成本4.替代方案-Cython-PyInstall......
  • 数据结构实验
    (一)线性表1#include<bits/stdc++.h>usingnamespacestd;intmain(){intn;multiset<int>ms;cin>>n;for(inti=1;i<=n;i++){intx;cin>>x;ms.insert(x);}intx;cin......