现在的位置: 首页 > 综合 > 正文

一个采用了MFC文档序列化的C++文件管理类

2012年11月07日 ⁄ 综合 ⁄ 共 14753字 ⁄ 字号 评论关闭

/*-----------------------------------------
* Copyright (c) 2002,计算中心
* All rights reserved.
*
* 文件名称:Formulas.h
* 文件标识:见配置管理计划书
* 摘    要:公式集合类和公式类的声明
*
* 当前版本:0.11
* 作    者:
* 完成日期:2002年6月29日
*
* 取代版本:0.1
* 原作者  :
* 完成日期:2002年6月21日
*------------------------------------------
*/
// Formulas.h: interface for the CFormulas class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_FORMULAS_H__355D4974_250C_41E9_9EE8_337D795BAC4F__INCLUDED_)
#define AFX_FORMULAS_H__355D4974_250C_41E9_9EE8_337D795BAC4F__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <afxtempl.h> //CArray模板类头文件

#include "Splimits.h" //系统限制预定义

class CFormula;  //前置声明,因为CFormulas用到了CFormula类
class CFormulas : public CObject  //公式集合类
{
 //以下的宏定义使CFormulas类支持序列化文件
 DECLARE_SERIAL( CFormulas )
  
public:
 long SaveTextFile(CString Filename);
 long GetNameNoteType(CStringArray &name, CStringArray &note,CStringArray &type,CString m_FormulaFileName);
 //按照给定的公式文件和类型type,返回公式名到name,注释到type如果不存在这样的公式,返回空字符串
 long GetNameNoteByType(CStringArray &name,CStringArray &note,CString m_FormulaFileName,CString type);
 //按照给定的公式名称和类型,返回公式内容,如果不存在这样的公式,返回空字符串""
 CString GetFormulaBodyByNameType(CString name, CString type);
 //追加一个公式fa到公式集末端,不检查同名而且类型相同的公式是否已存在(不同于Add)
 long AppendFormula(CFormula fa);  
 long FindFormula(CFormula fa);  //从公式集合查找与指定公式fa的公式名和公式类型都一致的一个公式
  long DelFormula(CString name, CString type);  //从公式集合删除指定公式名name和公式类型type的一个公式
 long LoadFile(CString Filename);  //从公式文件读全部公式到公式集合
 long SaveFile(CString Filename);  //从公式集合读全部公式写到公式文件
 long DelFormula(long recn);  //从公式集合删除指定记录号的一个公式
 //增加一个公式fa到公式集,如果同名而且类型相同的公式已存在,覆盖那个公式
 long AddFormula(CFormula fa);  
 
 
 CArray <CFormula,CFormula> m_fa;//存放公式的数组
 long m_reccount;//公式总数
 CFormulas();//构造函数,初始化公式纪录总数,公式数组的容量
 virtual ~CFormulas();
 
};
class CFormula : public CObject //公式类
{
 //以下的宏定义使CFormula类支持序列化文件
 DECLARE_SERIAL( CFormula )
private:
 short si_recn;//short型公式的记录号,仅读写文件时用
 long m_recn; //公式的记录号,允许范围[0,CFormulas.m_reccount-1]
 CString m_name; //公式名
 CString m_type; //公式类型,汉字
 CString m_typechr; //公式类型,用0-9,A-Z来表示最多36种公式,字符和汉字的对照关系见Splimits.h
 CString m_flag; //公式验证有效标志["0"|"1"=无效|有效]
 CString m_note; //公式注释
 CString m_body; //公式内容
 long Trim();//清除公式名和注释字符串前后多余的空格
 
 
public:
 //把公式类别由1个字符的字符串转成汉字
 long FaTypeChrToChinese(const CString Chr, CString &chinese);
 //把公式类别由汉字转成1个字符的字符串
 long FaTypeChineseToChr(const CString chinese, CString &Chr);
 //取出公式内容放到各个字段
 long GetFields(long& recn,CString& name,CString& type,CString& flag,CString& note,CString& body);
 CString GetRec();
 //按照各个字段设置公式内容
 void SetFields(long recn,CString name,CString type,CString flag,CString note,CString body);
 inline long SetRecn(long recn);//设置公式的记录号
 inline long GetRecn();//取公式的记录号
 
 CFormula() { m_recn = 0; }
 CFormula( const CFormula& a ) ;//这个拷贝构造函数必须保留
 
 void Serialize( CArchive& ar);//读写公式
 //重载赋值运算符=,实现CFormula对象的复制
 inline const CFormula& operator=( const CFormula& a );

 //重载相等运算符==,实现CFormula对象的比较
 BOOL operator==(CFormula a);

#ifdef _DEBUG
 void Dump( CDumpContext& dc ) const
 {
  CObject::Dump( dc );
  dc << m_recn;
 }
#endif
};

#endif // !defined(AFX_FORMULAS_H__355D4974_250C_41E9_9EE8_337D795BAC4F__INCLUDED_)

/*-----------------------------------------
* Copyright (c) 2002,计算中心
* All rights reserved.
*
* 文件名称:Formulas.cpp
* 文件标识:见配置管理计划书
* 摘    要:公式集合类和公式类的成员函数的实现
*
* 当前版本:0.1
* 作    者:
* 完成日期:2002年6月21日
*
* 取代版本:
* 原作者  :
* 完成日期:
*------------------------------------------
*/
// Formulas.cpp: implementation of the CFormulas class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
//LT 20020628 FIX

#include "Sarp.h"
//LT 20020628 FIX END
#include "Formulas.h"
#define BUFSIZE 40000L

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//以下的宏定义使CFormulas类和CFormula类支持序列化文件
IMPLEMENT_SERIAL( CFormulas, CObject, VERSIONABLE_SCHEMA | 2 )
IMPLEMENT_SERIAL( CFormula, CObject, VERSIONABLE_SCHEMA | 2 )

//取公式的记录号
/*inline */long CFormula::GetRecn()
{
 return m_recn;
}
//设置公式的记录号
/*inline */long CFormula::SetRecn(long recn)
{
 m_recn=recn;
 return m_recn;

}
//没有什么用的重载构造函数
/*
CFormula::CFormula(long recn, CString name, CString type, CString flag, CString note, CString body)
{
 m_recn =recn;
 m_name =name;
 m_type =type;
 m_flag =flag;
 m_note =note;
 m_body =body;
 
}
*/
//按照各个字段设置公式内容

void CFormula::SetFields(long recn,CString name,CString type,CString flag,CString note,CString body)
{

 m_recn =recn;
 m_name =name;
 m_type =type;
 m_flag =flag;
 m_note =note;
 m_body =body;

 Trim(); 
}
CFormula::CFormula( const CFormula& a ) //这个拷贝构造函数必须保留
 {
  m_recn =a.m_recn;
  m_name =a.m_name;
  m_type =a.m_type;
  m_flag =a.m_flag;
  m_note =a.m_note;
  m_body =a.m_body;
  
  Trim();
 } // Copy constructor
 //重载赋值运算符=,实现CFormula对象的复制
/* inline */const CFormula& CFormula::operator=( const CFormula& a )
 {
  m_recn =a.m_recn;
  m_name =a.m_name;
  m_type =a.m_type;
  m_flag =a.m_flag;
  m_note =a.m_note;
  m_body =a.m_body;
  
  Trim();
  return *this;
 }
//重载相等运算符==,实现CFormula对象的比较
 BOOL CFormula::operator ==(CFormula a)
 {
  //return m_recn == a.m_recn;//这样不保险,万一设置recn不当
  //判断2个公式相等的条件应该是名字和类型都一致
//  return ((m_name == a.m_name)&&( m_type == a.m_type)); //LT DEL 20020701
  if(0==m_name.CompareNoCase  (a.m_name ))//改为比较字符串函数,避免==的不明确 //LT 20020815 Add NOCASE
  {
  if(0==m_type.Compare (a.m_type ))
  {
   return TRUE;
  }
   
  }
  return FALSE;
 }

//取出公式内容放到各个字段
long CFormula::GetFields(long &recn, CString &name, CString &type, CString &flag, CString &note, CString &body)
{
 recn =m_recn;
 name =m_name;
 type =m_type;
 flag =m_flag;
 note =m_note;
 body =m_body;
 
 return 1;
}

 //取出公式内容放到字符串对象,主要供调试时观察用
CString CFormula::GetRec()
{
 CString str;
 str.Format ("recn:%dname:%stype:%sflag:%snote:%sbody:%s",
  m_recn,m_name,m_type,m_flag,m_note,m_body.Left (20)); //防止字符串太长
 return str;
}
//读写公式
void CFormula::Serialize( CArchive& ar)
{
/*原来好的开始
 if(  ar.IsStoring())//把CFormula对象的数据成员,而不是整个对象保存到文件
 {
  ar << m_recn;
  ar << m_name;
  ar << m_type;
  ar << m_flag;
  ar << m_note;
  ar << m_body;
 }
 else //把CFormula对象的数据成员从文件读出来

 {
  ar >> m_recn;
  ar >> m_name;
  ar >> m_type;
  ar >> m_flag;
  ar >> m_note;
  ar >> m_body;
 }
原来好的结束*/
 si_recn = 0;
 if(  ar.IsStoring())//把CFormula对象的数据成员,而不是整个对象保存到文件
 {
  si_recn=(short)m_recn;//把long转成short
  ar << si_recn;
  ar << m_name;

  FaTypeChineseToChr(m_type,m_typechr);//把汉字类型转化成字符
  //只用m_type一个变量不行的,在运行过程中m_type的值改变了,汉字转化成字符,成了非法的

  ar << m_typechr;
  ar << m_flag;
  ar << m_note;
  ar << m_body;
 }
 else //把CFormula对象的数据成员从文件读出来

 {
  ar >> si_recn;
  m_recn=(long)si_recn;

  ar >> m_name;
  ar >> m_typechr;

  FaTypeChrToChinese(m_typechr,m_type);//把字符转化成汉字类型

  ar >> m_flag;
  ar >> m_note;
  ar >> m_body;
 }
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CFormulas::CFormulas()//构造函数,初始化公式纪录总数,公式数组的容量
{
 m_reccount=0;
 m_fa.SetSize(30);
}

CFormulas::~CFormulas()//应该释放一些内容
{
 m_fa.RemoveAll ();
}
/*-----------------------------------------
* 函数介绍:增加一个公式到公式集合,如果同名
* 而且类型相同的公式已存在,覆盖那个公式。保证
* 增加的公式与已存在不同名、类型是程序员的责任
* 输入参数:一个CFormula的对象fa
* 输出参数:
* 返回值  :1,表示增加成功,2表示覆盖成功
*------------------------------------------
*/
long CFormulas::AddFormula(CFormula fa)
{
 if(m_reccount<0) //这个条件应该永远不会达到,但为了保险还是加上
 {
  return 0;
 }
 long recn;
 recn=FindFormula(fa); //效率很低
 if (-1 != recn) //相同的公式已存在
 {
  fa.SetRecn(recn); //因为是覆盖,公式的记录号是recn
  m_fa[recn]=fa;
  return 2;
 }
 else
 {
  m_reccount+=1;
  m_fa.Add (fa);     //只有这一行不够,因为CFormula没有重载Add函数,
  fa.SetRecn(m_reccount-1); //因为是追加,新纪录的记录号是m_reccount-1
  m_fa[m_reccount-1]=fa; //不能自动给成员变量赋值,而=运算符是重载的
  //
  return 1;
 }
}
/*-----------------------------------------
* 函数介绍:从公式集合删除指定记录号的一个公式
* 输入参数:一个long的对象recn
* 输出参数:
* 返回值  :1,表示增加成功,0表示删除失败
*------------------------------------------
*/
//
long CFormulas::DelFormula(long recn)
{
 long i;
 if((recn<0)||(recn>m_reccount)) //非法的纪录号
 {
  return 0;
 }
 if(m_reccount<1) //公式集合为空
 {
  return 0;
 }
  else //公式集合不为空(至少1个公式)
 {
  for(i=recn+1;i<m_reccount;i++) //重新设置recn以后的公式的记录号等于原来纪录号-1
  {
   m_fa[i].SetRecn (m_fa[i].GetRecn() - 1);//参数的值实际上等于i-1
  }
  m_fa.RemoveAt(recn);//删除记录!!使CFormulas.m_fa的下标恒等于m_fa.m_recn
  m_reccount--;
  return 1;
 }
}
/*-----------------------------------------
* 函数介绍:从公式集合读全部公式写到公式文件
* 输入参数:一个CString的对象公式文件名
* 输出参数:
* 返回值  :1,表示写成功,0表示写失败
*------------------------------------------
*/
long CFormulas::SaveFile(CString Filename)
{
  CFile myFile(Filename, CFile::modeCreate | CFile::modeReadWrite);
// CFormula  foa, *pfoa;
 // Create a storing archive.
 CArchive arStore(&myFile, CArchive::store);
 CString m_fileflag="Sarp2002";
 arStore << m_fileflag;

 //arStore << m_reccount; //LT DEL 20020629
 //LT ADD 20020629
 short si_reccount=(short)m_reccount;
 arStore << si_reccount;
 //LT ADD 20020629 END
 long i=0;
 for(i=0;i<m_reccount;i++)
 {
  //arStore << &m_fa[i];//LT DEL 20020629
  //直接调用CArchive对象的Serialize函数
  arStore.WriteObject( &m_fa[i] );//LT ADD 20020629

 }
 arStore.Close();
 myFile.Close ();
 return 1;
}
/*-----------------------------------------
* 函数介绍:从公式文件读全部公式到公式集合
* 输入参数:一个CString的对象公式文件名
* 输出参数:
* 返回值  :1,表示读成功,0表示读失败
*------------------------------------------
*/
long CFormulas::LoadFile(CString Filename)
{
   CFileFind finder;
  // start working for files
   BOOL b_find = finder.FindFile(Filename);
  if(0==b_find)
   {
   return 0;
   }

 CFile myFile(Filename, CFile::modeRead);
 CFormula  foa, *pfoa;
 
 CArchive arLoad(&myFile, CArchive::load);
 CString m_fileflag="Sarp2002";
 short si_reccount=0;
 arLoad >> m_fileflag;
 //arLoad >> m_reccount; //LT DEL 20020629
 //LT FIX 20020629
 arLoad >> si_reccount;
 m_reccount=(long)si_reccount;
 //LT FIX 20020629 END

 if(m_reccount<=0)//1个公式都没有
 {
  return 0;
 }
 long i=0;
  m_fa.SetSize(m_reccount);   //LT MODI 20020810

 for(i=0;i<m_reccount;i++)
 {
  //arLoad >> pfoa; //LT FIX 20020629
  //函数使用范例pAge = (CAge*) arLoad.ReadObject( RUNTIME_CLASS(CAge) );
  /* good
  pfoa=(CFormula*)arLoad.ReadObject( RUNTIME_CLASS(CFormula));//直接调用CArchive对象的Serialize函数
  m_fa.Add (foa);
  m_fa[i]=*pfoa;
  */
  //LT MODI 20020810
  arLoad >> pfoa;
  m_fa[i]=*pfoa;
  delete pfoa; //消除内存泄漏

 }
 arLoad.Close();
 myFile.Close ();

 return 1;
}

/*-----------------------------------------
* 函数介绍:从公式集合删除指定公式名和公式类型的一个公式
* 输入参数:一个CString的对象公式名,一个CString的对象公式类型
* 输出参数:
* 返回值  :1,表示删除成功,0表示删除失败
*------------------------------------------
*/

long CFormulas::DelFormula(CString name, CString type)
{
//查找符合条件的纪录
//返回记录号
//调用另一个DelFormula(long recn)函数
 long recn;
  CFormula fa;
  fa.SetFields (-1,name,type,"","","");
 recn=FindFormula(fa);
 return DelFormula(recn);

}
/*-----------------------------------------
* 函数介绍:从公式集合查找指定公式名和公式类型的一个公式
* 输入参数:一个CFormula的对象fa
* 输出参数:
* 返回值  :>=0表示查找成功,-1表示查找失败
*------------------------------------------
*/
long CFormulas::FindFormula(CFormula fa)
{
 long i;
 for(i=0;i<m_reccount;i++)
 {
 // TRACE("i=%d,s=%s,a=%s",i,m_fa[i].GetRec() ,fa.GetRec() );
  if(m_fa[i]==fa)
  {
   return i;
  }
 }
 return -1;
}
/*-----------------------------------------
* 函数介绍:追加一个公式到公式集合末端,不检查同名
* 而且类型相同的公式是否已存在(不同于Add)。保证
* 增加的公式与已存在不同名、类型是程序员的责任
* 输入参数:一个CFormula的对象fa
* 输出参数:
* 返回值  :1,表示追加成功,2表示覆盖成功
*------------------------------------------
*/
long CFormulas::AppendFormula(CFormula fa)
{
 if(m_reccount<0) //这个条件应该永远不会达到,但为了保险还是加上
 {
  return 0;
 }
 else
 {
  m_reccount+=1;
  m_fa.Add (fa);     //只有这一行不够,因为CFormula没有重载Add函数,
  fa.SetRecn(m_reccount-1); //因为是追加,新纪录的记录号是m_reccount-1
  m_fa[m_reccount-1]=fa; //不能自动给成员变量赋值,而=运算符是重载的
  //
  return 1;
 }

}
//清除公式名和注释字符串前后多余的空格
long CFormula::Trim()
{
 m_name.TrimLeft ();
 m_name.TrimRight ();
 m_note.TrimLeft ();
 m_note.TrimRight ();
 return 1;
}
//按照给定的公式名称和类型,返回公式内容,如果不存在这样的公式,返回空字符串""
//#include "mainfrm.h"
CString CFormulas::GetFormulaBodyByNameType(CString name, CString type)
{
   // CMainFrame *MFrame=(CMainFrame *)AfxGetMainWnd();//获得指向框架的指针
    CFormulas cf;
 //MFrame->
  GetFormulaFileName();
 LoadFile (FormulaFileName);

 CFormula fa;
 CString str_name,str_type,str_flag,str_note,str_body;
 long l_recn;
 fa.SetFields(-1, name, type,"","","");
  CString str_chtype="";
  fa.FaTypeChineseToChr(type,str_chtype);
 l_recn = FindFormula(fa);
 if(-1!=l_recn)
 {
  m_fa[l_recn].GetFields(l_recn,str_name,str_type,str_flag,str_note,str_body);
  //除了指针以外的公式最后补/n
  if((str_chtype>='0'&&str_chtype<='9')//指针都>9
   &&str_body.GetAt(str_body.GetLength()-1)!='/n') //20020814, add '/n' at end of string
  {
   str_body=str_body+"/n";
  }
  return str_body;
 }
 else
 {
  if(str_chtype>='0'&&str_chtype<='9')
  {
   return "/n"; //20020814
  }
  return "";
 }
 
}
//把公式类别由汉字转成1个字符的字符串
//参数:CString chinese公式类别汉字
//CString &Chr,转换后的字符串,只有一个字符
//如果没有匹配,Chr==空字符串""
//返回值,转化成功后的字符的ASC值,失败返回-1

long CFormula::FaTypeChineseToChr(const CString chinese, CString &Chr)
{
  CString str_fulltype=STRING_FORMULA_TYPES_CHAR;
  if(chinese.GetLength ()<2)//汉字必然>=2个字符
  {
#ifdef  _DEBUG
//   AfxMessageBox("非法的汉字公式类型["+chinese+"]");
#endif
   Chr="";
   return -1;
  }
  long i=str_fulltype.Find(chinese);
  if(-1==i)
  {
#ifdef  _DEBUG
//   AfxMessageBox("找不到的汉字公式类型["+chinese+"]");
#endif
   Chr="";
   return -1;
  }
  else
  {
//LT030405   Chr=str_fulltype[i-1];//如果找到,i必然>=1
   Chr=str_fulltype.Mid(i-1,1);//如果找到,i必然>=1
//LT030405    return (long)str_fulltype[i-1];
   return (long)(str_fulltype.GetAt (i-1));
  }
}
//把公式类别由1个字符的字符串转成汉字
//参数:CString Chr,转换前的字符串,只有一个字符
//CString &chinese 转换后的公式类别汉字
//如果没有匹配,chinese==空字符串""
//返回值,转化成功后返回1,失败返回-1

long CFormula::FaTypeChrToChinese(const CString Chr, CString &chinese)
{
  CString str_fulltype=STRING_FORMULA_TYPES_CHAR;
  if(1!=Chr.GetLength ())//必然==1个字符
  {
#ifdef  _DEBUG
//   AfxMessageBox("非法的字符公式类型");
#endif
   chinese="";
   return -1;
  }
  long i=str_fulltype.Find(Chr);
  if(-1==i)
  {
#ifdef  _DEBUG
//   AfxMessageBox("找不到的字符公式类型");
#endif
   chinese="";
   return -1L;
  }
  else
  {
   long j=str_fulltype.Find ("|",i);//如果找到,j必然>i+1
   chinese=str_fulltype.Mid (i+1,j-i-1);
   return 1L;
  }
}
 //按照给定的公式文件和类型type,返回公式名到name,注释到type如果不存在这样的公式,返回空字符串

long CFormulas::GetNameNoteByType(CStringArray &name, CStringArray &note,CString m_FormulaFileName,CString type)
{
 long loadok=LoadFile (m_FormulaFileName);
// long FindSeltypefa=0;
 name.RemoveAll ();
 note.RemoveAll ();
 long l_recn=0;
 CString str_name;//公式名
 CString str_type;//公式类型
 CString str_flag;//公式有效标志[0|1=无效|有效]
 CString str_note;//公式注释
 CString str_body;//公式内容
 if(loadok>0) //文件中有至少1个公式
 {
  long i;
  for(i=0;i<m_reccount;i++)
  {
   m_fa[i].GetFields ( l_recn,
    str_name,str_type,str_flag,str_note,str_body );
   
   //应该只显示选择类型的公式
   if(str_type==type)
   {
    name.Add (str_name);
    note.Add (str_note);
   }
  }
return 1;
}
 return 0;

}

long CFormulas::GetNameNoteType(CStringArray &name, CStringArray &note,CStringArray &type,CString m_FormulaFileName)
{
 long loadok=LoadFile (m_FormulaFileName);
// long FindSeltypefa=0;
 name.RemoveAll ();
 note.RemoveAll ();
 type.RemoveAll ();
 long l_recn=0;
 CString str_name;//公式名
 CString str_type;//公式类型
 CString str_flag;//公式有效标志[0|1=无效|有效]
 CString str_note;//公式注释
 CString str_body;//公式内容
 if(loadok>0) //文件中有至少1个公式
 {
  long i;
  for(i=0;i<m_reccount;i++)
  {
   m_fa[i].GetFields ( l_recn,
    str_name,str_type,str_flag,str_note,str_body );
   
   //应该只显示选择类型的公式
 //  if(str_type==type)
   {
    name.Add (str_name);
    note.Add (str_note);
    type.Add (str_type);
   }
  }
return 1;
}
 return 0;

}

long CFormulas::SaveTextFile(CString Filename)
{
  CFile myFile(Filename, CFile::modeCreate | CFile::modeReadWrite);
 short si_reccount=(short)m_reccount;
 long i=0;
 long j=0;
 char buf[BUFSIZE];
 CString str,strname,strtype,strflag,strnote,strbody;
 for(i=0;i<m_reccount;i++)
 {
  str.Format ("%u/r/n",i);
  m_fa[i].GetFields(j,strname,strtype,strflag,strnote,strbody);
  str=str+"公式名:"+strname+"/r/n"
   "公式类型:"+strtype+"/r/n"
   "公式注释:"+strnote+"/r/n"
   "公式内容:/r/n"+strbody+"/r/n/007";
   strcpy(buf,(LPCSTR)str);
  myFile.Write (buf,strlen(buf));
 }
 myFile.Close ();
 return 1;
}

抱歉!评论已关闭.