⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 operationfamilytree.cpp

📁 家谱管理系统
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -