?? operationfamilytree.cpp
字號:
// OperationFamilytree.cpp: implementation of the COperationFamilytree class.
//
//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
///// 家譜操作類實現文件
/////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "Familytree.h"
#include "OperationFamilytree.h"
#include "FileOpenAndSaveDlg.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
COperationFamilytree::COperationFamilytree()
{
//開始為空家譜
T=0;
}
COperationFamilytree::~COperationFamilytree()
{
//釋放資源
DestroyFamilytree();
}
void COperationFamilytree::NewFamilytree()
{
//本函數新建一空家譜
DestroyFamilytree(); //刪除原有家譜
T=0;
}
int COperationFamilytree::CreateFamilytree(CString filename)
{
//本函數建立一新家譜
DestroyFamilytree(); //建立一新家譜之前,清空原有家譜
FILE* fp;
if((fp=fopen(filename,"r"))==0) //打開文件filename
return READ_FILE_ERROR;
T=new PersonNode; //定義根結點
if(!T)
return NOT_ENOUGH_MEMORY;
T->child=0;
T->sibling=0;
T->parent=0;
Person parentT, temp; //定義兩個臨時結點
char parentname[MAX_CHARNUM]; //定義一個臨時字符串數組
//讀取根結點值,(姓名,出生日期(年,月,日),婚否,地址,健在否,(如過世,還有死亡日期))
int result;
result=ReadNode(fp,T,parentname);
if(result==FILE_DATA_NOT_PRACTICAL){
delete T; //若不合法,刪除申請的堆空間
T=0;
return result;
}
if(strcmp(T->info.name,parentname)==0){ //根結點名字與其父親名字相同,說明為空樹
delete T;
T=0;
return PEDIGREE_EMPTY;
}
temp=new PersonNode; //申請一結點
if(!temp){ //申請失敗
DestroyFamilytree(); //釋放申請空間
return NOT_ENOUGH_MEMORY;
}
result=ReadNode(fp,temp,parentname);
while(strcmp(temp->info.name,parentname)&&strcmp(temp->info.name,"end")){ //讀取信息結束的條件是兩個人的名字同為end
if(result==FILE_DATA_NOT_PRACTICAL){ //若數據不合法,釋放已申請空間,然后返回
delete temp;
DestroyFamilytree();
return result;
}
parentT=0;
Find(T,parentT,parentname); //找到parentname所在結點parentT
if(parentT){ //如果parentT存在,說明parentname在家譜中
//并且parentname為temp的父親
int cmp;
cmp=CompareDate(temp->info.birthday,parentT->info.birthday);
if(cmp<0){ //若孩子出生日期比父親大,則不對
delete temp;
DestroyFamilytree();
return FILE_DATA_NOT_PRACTICAL;
}
temp->child=temp->sibling=0;
temp->parent=parentT; //temp的父指針指向parentT;
if(parentT->child){ //parentname已經有孩子
InsertSibling(parentT->child,temp);
}//if
else //parentname無孩子,則temp應為
parentT->child=temp; //parentname的第一個孩子
}//if
else{ //parentT不存在,說明家譜中不存在parentname此人
DestroyFamilytree(); //返回出錯信息
return FILE_DATA_ERROR;
}
temp=new PersonNode; //申請一結點
if(!temp){ //申請失敗
DestroyFamilytree(); //釋放申請空間
return NOT_ENOUGH_MEMORY;
}
result=ReadNode(fp,temp,parentname); //繼續讀取數據
}//while
if(temp)
delete temp;
fclose(fp);
return OK;
}
void COperationFamilytree::Find(Person& T,Person& Tname,char* name)
{
//本函數以T為根結點開始,搜索結點信息中名字等于name的結點
if(T){ //如果T存在
if(strcmp(T->info.name,name)==0) //T結點姓名和name相同,把T結點指針傳給Tname
Tname=T;
else{
Find(T->sibling,Tname,name); //對T的兄弟遞歸搜索
Find(T->child,Tname,name); //對T的孩子遞歸搜索
}
}
}
void COperationFamilytree::Find(Person &T, Person*& Tname,int month, int day)
{
//本函數以T為根結點開始,搜索結點信息中生日等于month,day的結點,
//并把所有符合條件的結點指針值存入以Tname為起始地址的地址數組中
if(T){ //如果T存在
if(T->info.birthday.month==month&&T->info.birthday.day==day){
//T結點生日與所給相同,把T結點指針傳給Tname,同時Tname指針前進
Person temp;
temp=new PersonNode;
temp=T;
if(temp->info.birthday.month==month&&temp->info.birthday.day==day)
{
*Tname=temp;
Tname++;
}
temp=NULL;
}
Find(T->child,Tname,month,day); //對T的孩子遞歸搜索
Find(T->sibling,Tname,month,day); //對T的兄弟遞歸搜索
}
}
void COperationFamilytree::PostOrderTraverse(Person &T, void (__cdecl *Visit)(Person &))
{
//本函數對以T為根結點的所有結點后序遍歷訪問Visit函數
if(T){
PostOrderTraverse(T->child,Visit);
PostOrderTraverse(T->sibling,Visit);
(*Visit)(T);
}
}
void DestroyNode(Person &pNode)
{
//本函數刪除一結點
if(pNode){
delete pNode;
pNode=0;
}
}
void COperationFamilytree::DestroyFamilytree()
{
//本函數刪除家譜,釋放資源
PostOrderTraverse(T,DestroyNode);
}
int COperationFamilytree::SaveFamilytree(CString filename)
{
//本函數保存家譜到文件filename中
FILE* fp;
if((fp=fopen(filename,"w"))==0) //打開文件filename
return WRITE_FILE_ERROR;
PreOrderTraverse(fp,T,SaveNode); //從根結點開始存儲家譜數據
//置家譜數據結束標記(一結點的名字與其父結點的名字同為end)
fprintf(fp,"%s %d %d %d %d %s %d %s","end",1999,12,
2,1,"end",1,"end");
fclose(fp);
return OK;
}
void COperationFamilytree::PreOrderTraverse(FILE* fp,Person &T, void (__cdecl *Visit)(FILE* fp,Person &))
{
//本函數把所有以T結點為根結點的結點值存到文件fp中
if(T){
(*Visit)(fp,T);
PreOrderTraverse(fp,T->child,Visit);
PreOrderTraverse(fp,T->sibling,Visit);
}
}
void SaveNode(FILE *fp, Person &pNode)
{
//本函數向文件fp中存取一結點pNode
char ch='\n';
if(pNode){
fprintf(fp,"%s %d %d %d %d %s %d ",pNode->info.name,pNode->info.birthday.year,
pNode->info.birthday.month,pNode->info.birthday.day,pNode->info.marry,
pNode->info.addr,pNode->info.live);
if(pNode->info.live==0)
fprintf(fp," %d %d %d ",pNode->info.deathday.year,pNode->info.deathday.month,
pNode->info.deathday.day);
if(pNode->parent)
fprintf(fp," %s ",pNode->parent->info.name);
else
fprintf(fp," %s","-1");
fprintf(fp," %c",ch);
}
}
int COperationFamilytree::ReadNode(FILE *fp, Person &T,char* parentname)
{
//本函數從文件fp中讀取信息到結點T中,并讀取結點的父親名字到字符數組parentname中
//分別讀取結點值,為:姓名,出生日期(年,月,日),婚否,地址,健在否,(如過世,還有死亡日期)
fscanf(fp,"%s%d%d%d%d%s%d",T->info.name,&T->info.birthday.year,&T->info.birthday.month,
&T->info.birthday.day,&T->info.marry,T->info.addr,&T->info.live);
if(T->info.live==0)
fscanf(fp,"%d%d%d",&T->info.deathday.year,&T->info.deathday.month,
&T->info.deathday.day);
fscanf(fp,"%s",parentname);
if(!IsDateValid(T->info.birthday)) //出生日期合法性檢查
return FILE_DATA_NOT_PRACTICAL;
if(T->info.live==0) //若過世,死亡日期合法性檢查
{ if (CompareDate(T->info.birthday,T->info.deathday)!=-1)
return FILE_DATA_NOT_PRACTICAL;
if(!IsDateValid(T->info.deathday))
return FILE_DATA_NOT_PRACTICAL;}
return OK;
}
bool COperationFamilytree::IsDateValid(Date date)
{
//本函數為日期的有效性檢查
switch(date.month){
case 1:
case 3:
case 5:
case 7:
case 8:
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -