📄 home.h
字号:
#include<iostream.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#define namelength 6
#define length 7
#include <conio.h>
#include <process.h>
typedef struct homeperson{//个人结点
char *name;//姓名
char *bymd;//出生年月日
char *dymd;//逝世年月日
char marry;//婚否
char living;//健在否
char mother;//母亲,因为其父可能有一妻一妾,0表示文件中没有显示其母亲,1表示其母为其父之妻,2表示其母为其父之妾
char distinction;//性别
char generation;//第几代
int ID;
homeperson *child,*lover1,*lover2,*father,*lmates,*nmates;//链接,表示最大孩子,爱人,妾,父亲,最小兄姐,最大弟弟或妹妹
}*people;
typedef struct node{//队列结点
homeperson *point;//存放人员指针
node *next;//指向队列在下一个结点
}linknode;
struct stack{//栈
people *top;//栈顶
people *bottom;//栈底
};
stack homeS;//全局变量
bool sinit( ){//初始化栈
homeS.top=new people[50];//栈以数组形式存储
if(!homeS.top)
return false;
homeS.bottom=homeS.top;
return true;
}
bool homepop(homeperson *&p){//homepop
if(homeS.top==homeS.bottom)
return false;
else
p=*homeS.bottom;
homeS.bottom--;
return true;
}
bool homepush(homeperson *p){//homepush
if((homeS.bottom-homeS.top)>=39)
return false;
else
homeS.bottom++;
*homeS.bottom=p;
return true;
}
bool stackempty( ){//判断栈是否为空
if(homeS.top==homeS.bottom)
return true;
else
return false;
}
bool gettop(homeperson *&p){//取栈顶元素
if(stackempty()){
p=NULL;
return false;
}
p=*homeS.bottom;
return true;
}
bool destorys( ){//销毁栈
delete []homeS.top;
return true;
}
struct queue{//队列
node *front;//头
node *rear;//尾
};
queue homeQ;//全局变量
bool qinit( ){//队列初始化
homeQ.front=new node;//为头分配一个指针
if(!homeQ.front) return false;
homeQ.front->next=NULL;//next置空
homeQ.rear=homeQ.front;//头尾共处
return true;
}
bool inqueue(homeperson *p){//进队
node *q;
q=new node;
if(!q) return false;
q->point=p;
q->next=NULL;
homeQ.rear->next=q;
homeQ.rear=q;
return true;
}
bool dequeue(homeperson *&p){//出队
if(homeQ.front==homeQ.rear){
p=NULL;
return false;
}
node *r=homeQ.front->next;
p=r->point;
homeQ.front->next=r->next;
if(homeQ.front->next==NULL)//特殊情况,栈已为空
homeQ.rear=homeQ.front;
delete r;
return true;
}
bool qempty(){//判断队列是否为空
if(homeQ.front==homeQ.rear)
return true;
else
return false;
}
bool clears( ){//清空栈
homeS.bottom=homeS.top;
return true;
}
bool clear(){//清空队列
node *r,*q;
if(homeQ.front==homeQ.rear)
return true;
else{
r=homeQ.front->next;
while(r){
q=r;
r=r->next;
delete q;
}
homeQ.rear=homeQ.front;
}
return true;
}
bool qdestory(){//释放队列中所有结点
node *r,*q;
if(homeQ.front==homeQ.rear){
delete homeQ.front;
}
else{
r=homeQ.front;
while(r!=NULL){
q=r;
r=r->next;
delete q;
}
}
return true;
}
class home{//家族类
private:
int totalnumber;//总人数
int generations;//总代数
int womennumber;//女性人数
public:
homeperson *ancestors;//祖
home(){
init( );
}
bool init( );//调用文件,在读取数据的同时,将树建好;
bool insert(char name[],char mothername[],char sex,char bymd[]);
bool insertmarry(char name[],char husbandname[],char bymd[]);
void printheadline(){
cout<<"姓名 第几代 父亲 母亲 出生 性别 最小兄姐 婚 偶 妾 长子 健在 死亡";
}
bool seek(homeperson *&q,char *name); //按姓名查找人,并以q返回其指针
bool gseek(char generation,people gs[],int &i); //按代查找
bool dseek(char distinction,people ds[],int &i); //按性别查找
bool lseek(char living,people ls[],int &i); //按是否死亡查找
bool modify(people p,int j,char info[]); //修改某人资料
int treehigh(homeperson *q); //计算出树高
bool out(int &generation); //为输入出总代数提供一个接口
bool relation(people q,people p,CString &rela); //找出两个人之间的关系
bool initperson(homeperson *p); //将一个人所包函的所有指针设置为空
bool destoryperson(homeperson *&P);
bool printperson(homeperson *r); //在屏幕上打印一个人的信息
bool printhome(); //在屏幕上打印整个家族
bool makefile(); //将内存中的信息进行存盘
bool writeperson(homeperson *p,FILE *fp); //将一个人在内存中的信息输出到一个文件
int rank(homeperson *q); //计算出此人的排行
int compare(homeperson *p,homeperson *q); //比较两个人的大小
friend bool inqueue(homeperson *p);
friend bool homepush(homeperson *p);
bool exist(){
if(ancestors)
return true;
else
return false;
}
~home();//析构
};
bool home::seek(homeperson *&q,char *name){//按姓名查找人,并以q返回其指针
homeperson *p;
q=NULL;
clear( );
sinit( );
qinit( );
homepush(ancestors);
while(!stackempty()){//以中序遍列执行;
while(gettop(p)&&p) homepush(p->child);
homepop(p);//将空出栈
if(!stackempty()){
homepop(p);
if(strcmp(name,p->name)==0){
q=p;
clears( );//为下次执行seek,所以要进行清空处理
return true;
}
if(p->lover1)//lover1,lover2为附带节点,不入栈,但需进行比较;
if(strcmp(name,p->lover1->name)==0){
q=p->lover1;
clears( );//为下次执行seek,所以要进行清空处理
return true;
}
if(p->lover2)
if(strcmp(name,p->lover2->name)==0){
q=p->lover2;
clears( );//为下次执行seek,所以要进行清空处理
return true;
}
homepush(p->nmates);//右孩子进栈
}
}
return false;
}
bool home::init(){ //调用文件,在读取数据的同时,将树建好;
FILE *fp; //fp为家谱文件,fp1为记录文件名的文件
char *home;
char flag='y',ch,e=15; //flag,use都是用以供用户选择
char temp[20];
char *name;
int i=1;
home=NULL;
homeperson *q,*p;
ancestors=NULL;
totalnumber=home::womennumber=0; //初始化为0
if((fp=fopen("home.txt","r+"))==NULL){ } //打开记录文件名的文件
else
{
//文件存在则让用户选择用原文件,还是启用新的家谱文件
//读取并输出文件名。
}
ch=fgetc(fp);
while(ch!=EOF){//开始读取人员资料
if(ch=='!'){
//开始读一个人的资料
q=new homeperson;
home::initperson(q);
home::totalnumber++;
if(!q)
return false;
q->name=new char[length];
//读姓名
fread(q->name,namelength,1,fp);
q->name[6]='\0';
// cout<<q->name<<endl;
//读代数
q->generation=fgetc(fp);//读代数
//以下为读父亲的姓名
name=new char[length];
fread(name,namelength,1,fp);
if(name[0]=='0'){
q->father=NULL;
}
else{
name[6]='\0';
seek(p,name);
if(!p->child){
p->child=q;
}
q->father=p;
}
delete []name;
//读出生年月日
q->bymd=new char[9];
fread(q->bymd,8,1,fp);
q->bymd[8]='\0';
//读性别
q->distinction=fgetc(fp);
if(q->distinction=='f')
home::womennumber++;
if(q->generation=='0'&& q->distinction=='m'){
ancestors=q;
}
//读兄或姐
name=new char[length];
fread(name,namelength,1,fp);
if(name[0]=='0'){
delete []name;
}
else{
name[6]='\0';
seek(p,name);
p->nmates=q;
q->lmates=p;
}
q->mother=fgetc(fp);
//读是否已婚
q->marry=fgetc(fp);
if(q->marry=='n'||q->distinction=='m'){//否,则无偶,或为女性时,不读
fread(temp,6,1,fp);
}
else{//是,则读偶
name=new char[length];//读丈夫
fread(name,namelength,1,fp);
if(name[0]=='0'){
q->lover1=NULL;
}
else{
name[6]='\0';
seek(p,name);
if(p->lover1)
p->lover2=q;
else
p->lover1=q;
// cout<<"夫"<<p->name;
q->lover1=p;
}
q->lover2=NULL;
delete []name;
}//else
q->living=fgetc(fp);//读是否健在
/// cout<<"健"<<q->living<<" ";
if(q->living=='y')
q->dymd=NULL;
else{//不在,读逝世日期
q->dymd=new char[9];
q->dymd[8]='\0';
fread(q->dymd,8,1,fp);
}//else
generations=q->generation-48;
}//if
ch=fgetc(fp);
}//while
//To Do
// cout<<endl<<"数据调用完成,";
// cout<<"本家族中共有"<<home::generations<<"代"<<home::totalnumber<<"人,其中女性"<<home::womennumber<<"人,下面进入功能区。"<<endl; ;
fclose(fp);
return true;
}
bool home::insert(char name[],char mothername[],char sex,char bymd[])
{//增加新人
char flag='y';
homeperson *q,*p,*r;
q=new homeperson;
home::initperson(q);
q->name=name;
q->bymd=bymd;
//ToDo
if(q){//出生
q->distinction=sex;
if(q->distinction=='f')
home::womennumber++;
while(flag=='y'){
if(seek(r,mothername)&&r->distinction=='f'){
p=r->lover1;
if(p->lover1==r)
q->mother='1';
else
q->mother='2';
q->father=p;
q->generation=p->generation+1;
if(home::generations=p->generation-48)
home::generations++;
if(p->child){
p=p->child;
while(p->nmates)
p=p->nmates;
p->nmates=q;
q->lmates=p;
}
else{
p->child=q;
q->lmates=NULL;
}
flag='n';
q->marry='n';
q->living='y';
q->lover1=q->lover2=q->nmates=NULL;
q->dymd=NULL;
home::totalnumber++;
}//if
else
{
return false;
}//else
}//while
}//if
return true;
}
bool home::insertmarry(char name[],char husbandname[],char bymd[]){//增加新人
homeperson *q,*p;
q=new homeperson;
home::initperson(q);
q->name=name;
q->bymd=bymd;
if(q)
{//迎娶
//迎娶在以往家族中皆为女性外嫁
if(seek(p,husbandname)){//建立关系
if(p->lover1)
p->lover2=q;
else
p->lover1=q;
q->lover1=p;
p->marry='y';
q->lover2=q->father=q->nmates=q->lmates=q->child=NULL;
q->marry='y';
q->living='y';
q->distinction='f';//自动给出性别
home::totalnumber++;
home::womennumber++;
q->generation=p->generation;
}//if
else
{
return false;
}//else
}
return true;
}
bool home::destoryperson(homeperson *&p){//销毁人员,用于析构。
delete []p->name;
delete []p->bymd;
if(p->living=='y')
delete p->dymd;
delete p;
return true;
}
home::~home(){//析构
homeperson *p;
homepush(ancestors);
while(!stackempty()){
while(gettop(p)&&p) homepush(p->child);
homepop(p);
if(!stackempty()){
homepop(p);
if(p->lover1){
destoryperson(p->lover1);
}
if(p->lover2)
destoryperson(p->lover2);
homepush(p->nmates);
destoryperson(p);
}
}
}
bool home::initperson(homeperson *q){//将一个人所包函的所有指针设置为空,及部分信息初始化
if(!q)
return false;
else{
q->name=q->bymd=q->dymd=NULL;
q->child=q->father=q->nmates=q->lmates=q->lover1=q->lover2=NULL;
q->living='y';
q->marry='n';
q->mother='0';
return true;
}
}
bool home::printperson(homeperson *r){//在屏幕上打印一个人的信息
if(r==NULL){
return false;
}
else{
cout<<endl<<r->name<<" "<<r->generation<<" ";
if(r->father)
cout<<" "<<r->father->name;
else
cout<<" ";
if(r->mother=='0')
cout<<" ";
else{
if(r->mother=='1')
cout<<" "<<r->father->lover1->name;
else
cout<<" "<<r->father->lover2->name;
}
cout<<" "<<r->bymd;
cout<<" "<<r->distinction;
if(r->lmates)
cout<<" "<<r->lmates->name;
else
cout<<" ";
cout<<" "<<r->marry<<" ";
if(r->lover1){//cout<<"lover1";
cout<<r->lover1->name<<" ";
}
else{
cout<<" ";
}
if(r->lover2){//cout<<"lover2";
cout<<r->lover2->name;
}
else{
cout<<" ";
}
if(r->child){
cout<<" "<<r->child->name;
}
else{
cout<<" ";
}
cout<<r->living;
if(r->living=='n')
cout<<" "<<r->dymd<<" ";
}
return true;
}
bool home::gseek(char generation,people gs[],int &i){//按代查找
i=0;
if(generation>57||generation<48)//本程序中暂时不支持超进9代的家族,不过作者认为要支持也很简单,不过程序编完大面积地改有点吃力,所有没有作修改
return false;
homeperson *r;
clear();
if(!ancestors)
return false;
inqueue(ancestors);
while(!qempty()){//以队列形式查找
dequeue(r);
if(r->generation==generation){
gs[i]=r;
i++;
if(r->lover1)
{
gs[i]=r->lover1;
i++;
}
if(r->lover2)
{
gs[i]=r->lover2;
i++;
}
}
if(r->child){
inqueue(r->child);
r=r->child;
while(r->nmates){
inqueue(r->nmates);
r=r->nmates;
}
}
}
clear( );
return true;
}
bool home::dseek(char distinction,people ds[],int &i){//按性别查找
homeperson *r;
clear();
i=0;//记录人数
if(!ancestors)
return false;
inqueue(ancestors);
while(!qempty()){//查找方法与代相同
dequeue(r);
if(r->distinction!=distinction){
if(r->lover1)
{
ds[i]=r->lover1;
i++;
}
if(r->lover2)
{
ds[i]=r->lover2;
i++;
}
}
else
{
if(r!=ancestors)
{
ds[i]=r;
i++;
}
}
if(r->child){
inqueue(r->child);
r=r->child;
while(r->nmates){
inqueue(r->nmates);
r=r->nmates;
}
}
}
clear( );
return true;
}
void getmini(people p,CString str)
{
CString str2;
str2.Format("姓名 %s ",p->name);
str+=str2;
if(p->distinction=='f')
str+="女";
else
str+="男";
str+="\r\n";
}
bool home::lseek(char living,people ls[],int &i){//按是否死亡查找
homeperson *r;
clear();
i=0;//记录人数
if(!ancestors)
return false;
inqueue(ancestors);
while(!qempty()){//查找方法也与代的查找方法相同
dequeue(r);
if(r!=ancestors&&r->living==living)
{
ls[i]=r;
i++;
}
if(r->lover1&&r->lover1->living==living)
{
ls[i]=r->lover1;
i++;
}
if(r->lover2&&r->lover2->living==living)
{
ls[i]=r->lover2;
i++;
}
if(r->child){
inqueue(r->child);
r=r->child;
while(r->nmates){
inqueue(r->nmates);
r=r->nmates;
}
}
}
clear( );
return true;
}
bool home::modify(people p,int j,char info[]){//修改某人资料
homeperson *r;
char c;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -