实验十二 对象的持久化和异常
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();
}