实验十二 对象的持久化和异常

本文档展示了C++中对象持久化的方法,通过文件操作将对象存储到文本和二进制文件中。实验内容包括读写文本文件、二进制文件,以及异常处理机制,特别是自定义FileNotFoundException类。程序读取Shapes.txt文件生成框架产品目录,排序后输出,并将产品按类别存入二进制文件,再从文件中读取并显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

实验十二 对象的持久化和异常

1 实验目的

(1)学习对象的持久化方法 —— 文件操作

(2)学习如何读取和写入文本文件

(3)学习如何读取和写入二进制固定长文件

(4)正确理解C++的异常处理机制,学习异常处理的声明和执行过程

2 实验内容

在《实验十 抽象类》的基础上进行扩展。

(1)在类的层次中添加正方形框架(Square),声明为长方形的子类。为每类框架定义一个classId,即圆,1;长方形,2;直角三角形,3;正方形,4。定义每个框架的单价,单位是 元**/**厘米。

(2)用一个文本文件(Shapes.txt)存放每类框架的名字及单价(元**/厘米),然后根据文本文件生成框架产品的目录清单,将清单中的产品读取到动态数组**中,然后排序并输出到显示器上。所有框架的几何参数都默认为3厘米,即圆的半径为3;直角三角形的边长为3,3;等。

\1. Circle, 4.0

\2. Rectangle, 2.0

\3. RightAngle, 3.5

\4. Square, 1.5

(3)将文本文件中的产品,按其分类,分别存入相应的二进制固定长文件,即Circle.dat,Rectangle.dat,Rightrangle.dat和Square.dat中,并再次从文件中读取出来,按照类别输出到显示器上。固定长文件记录的格式如下:

圆:1 Circle Radius Price

长方形:2 Rectangle Width Height Price

(4)自定义异常类FileNotFoundException。表示当读取文本文件Shapes.txt时,如果在指定的目录中没有找到该文件,就抛出该异常对象。并在程序中适当的位置处理异常,给出错误提示,并等待用户创建正确的Shapes.txt文件。

FileNotFoundException类要继承logic_error类。

3 代码

源.cpp
#include "Array.h"
#include < iostream>
#include < iomanip>
#include < algorithm>
#include <fstream>
#include<sstream>
#include<string>
#include<stdexcept>
using namespace std;

class FileNotFoundException : public logic_error {
public:
    FileNotFoundException(const string& msg):logic_error(msg){}
};
class Shape
{
private:
    double price;
    int classId;
public:
    Shape(double pr,int i) :price(pr),classId(i) {}
    double virtual getCircumference() = 0;
    void virtual showInf() = 0;
    double getPrice() { return price;}
    double getTotlePrice() {
        return getCircumference() * price;
    }
    int getId() {
        return classId;
    }
};
class Circle : public Shape
{
private:
    double radius;
    const double Pi = 3.1415926535;
public:
    Circle(double r=3,double pr=0,int id=1) : radius(r),Shape(pr,id){}
    double virtual getCircumference() { return radius * 2 *Pi; }
    void virtual showInf() {
        cout << "圆,半径" << setiosflags(2) <<
        radius << ",周长" << setiosflags(2) << getCircumference() << endl;
    }
};
class RightTriangle : public Shape
{
private:
    double side_one;
    double side_two;
public:
    RightTriangle(double o=3, double t=3, double pr=0,int id=3) : side_one(o), side_two(t) ,Shape(pr,id){}
    double virtual getCircumference() { return side_one + side_two + sqrt(side_one * side_one + side_two * side_two); }
    void virtual showInf() { cout << "三角形,直角边" << setiosflags(2) << side_one << ",直角边" << setiosflags(2) << side_two << ",周长" << setiosflags(2) << getCircumference() << endl; }
};
class Rectangle : public Shape
{
private:
    double side_one;
    double side_two;
public:
    Rectangle(double o=3, double t=3, double pr=0,int id=2) : side_one(o), side_two(t),Shape(pr,id) {}
    double virtual getCircumference() { return (side_one + side_two) * 2; }
    void virtual showInf() { cout << "长方形,长" << setiosflags(2) << side_one << ",宽" 
        << setiosflags(2) << side_two << ",周长" << setiosflags(2) << getCircumference() << endl; }
};
class Square :public Rectangle
{
private:
    double side;
public:
    Square(double o=3, double pr=0,int id=4) :side(o),Rectangle(o,o,pr,id){}
    double virtual getCircumference() { return side * 2; }
    void virtual showInf() {
        cout << "正方形,边长" << setiosflags(2) << side << ",周长" << setiosflags(2) << getCircumference() << endl;
    }
};
bool operator<(Shape& one, Shape& two) { return one.getCircumference() < two.getCircumference(); }
void mywrite(Array<Shape*>& parry, int num) {
    cout << endl << "下面将动态数组以二进制的形式写入四个文件中:" << endl;
   
    ofstream rightangleFile("Rightangle.dat", ios_base::out | ios_base::binary);
    ofstream squareFile("Square.dat", ios_base::out | ios_base::binary);
    ofstream circleFile("Circle.dat", ios_base::out | ios_base::binary);
    ofstream RectangleFile("Rectangle.dat", ios_base::out | ios_base::binary);
    

    for (int i = 0; i < num; i++) {
        switch (parry[i]->getId()) {
        case 1: {
            Circle* p = dynamic_cast<Circle*>(parry[i]);
            circleFile.write(reinterpret_cast<char*>(p), sizeof(*p));
            cout << "写入了一个圆形\n";
            break;
        }
        case 2: {
            Rectangle* p = dynamic_cast<Rectangle*>(parry[i]);
            RectangleFile.write(reinterpret_cast<char*>(p), sizeof(*p));
            cout << "写入了一个长方形\n";
            break;
        }
        case 3: {
            RightTriangle* p = dynamic_cast<RightTriangle*>(parry[i]);
            rightangleFile.write(reinterpret_cast<char*>(p), sizeof(*p));
            cout << "写入了一个直角三角形\n";
            break;
        }
        case 4: {
            Square* p = dynamic_cast<Square*>(parry[i]);
            squareFile.write(reinterpret_cast<char*>(p), sizeof(*p));
            cout << "写入了一个正方形\n";
            break;
        }
        }
    }
    circleFile.close();
    cout << "完成文件写入!" << endl;
}
void myread() {
    cout << endl << "下面从四个二进制文件中读取数据" << endl;

    ifstream circleFile("Circle.dat", ios_base::in | ios_base::binary);
    ifstream RectangleFile("Rectangle.dat", ios_base::in | ios_base::binary);
    ifstream rightangleFile("Rightangle.dat", ios_base::in | ios_base::binary);
    ifstream squareFile("Square.dat", ios_base::in | ios_base::binary);

    Circle circle;
    while (circleFile.read(reinterpret_cast<char*>(&circle), sizeof(circle))) {
        circle.showInf();
    }

    Rectangle rectangle;
    while (RectangleFile.read(reinterpret_cast<char*>(&rectangle), sizeof(rectangle))) {
        rectangle.showInf();
    }
    
    RightTriangle right;
    while (rightangleFile.read(reinterpret_cast<char*>(&right), sizeof(right))) {
        right.showInf();
    }
    
    Square square;
    while (squareFile.read(reinterpret_cast<char*>(&square), sizeof(square))) {
        square.showInf();
    }
    squareFile.close();
    circleFile.close();
    RectangleFile.close();
    rightangleFile.close();
    cout << "完成文件读取!" << endl;
}

int main()
{
    Array<Shape*> parray;
    int num = 0;
    Rectangle rectangle(3,3,2);
    Square square(3, 1.5);
    RightTriangle righttriangle(3, 3, 3.5);
    Circle circle(3, 4);
    try
    {
        ifstream is("Shapes.txt", ios_base::in);
        if (is.rdstate() & ios::failbit) {
            string info("不能打开文件,请检查文件是否存在!");
            throw FileNotFoundException(info);
        }
        string temp;
    while (getline(is,temp)) {
        istringstream iss(temp);
        int id;
        string shape_name;
        double unity;
        iss >> id;
        getline(iss, shape_name,',');
        iss >> unity;
        switch (id){
        case 1: 
            if (parray.getSize() <= num - 1) {
                parray.resize(parray.getSize() * 2); 
            }
            parray[num++] = new Circle(3, unity);
            cout << "圆形制造成功!\n";
            break;
        case 2:
            if (parray.getSize() <= num - 1) {
                parray.resize(parray.getSize() * 2);
            }
            parray[num++] = new Rectangle(3, 3,unity);
            cout << "正方形制造成功!\n";
            break;
        case 3:
            if (parray.getSize() <= num - 1) {
                parray.resize(parray.getSize() * 2);
            }
            parray[num++] = new RightTriangle(3,3, unity);
            cout << "直角三角形制造成功!\n";
            break;
        case 4:
            if (parray.getSize() <= num - 1) {
                parray.resize(parray.getSize() * 2);
            }
            parray[num++] = new Square(3, unity);
            cout << "正方形制造成功!\n";
            break;
        default:
            cout << "classId有误,请检查文件内容与格式!\n" << endl;
            break;
        }
    }
    }
    catch (FileNotFoundException &e)
    {
        cout << e.what()<<endl;
    }
    mywrite(parray,num);
    myread();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值