#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <windows.h> 
 typedef struct record_tab{	/*就诊记录结构类型*/
   char name[10];			/*病人姓名*/
   char pat_num[8];			/*病人编号*/ 
   char depart_num[8];		/*科室编号*/ 
   char time[9];			/*就诊时间*/
   char sym[40];			/*症状*/
   struct record_tab *next;
} record;
 
 typedef struct patient_tab{/*病人结构类型*/
	char num[8];  			/*病人编号*/
    char name[10];			/*病人姓名*/
    char adr[40];			/*病人住址*/
    char tel[15];			/*病人电话*/
    char depart_num[8];		/*科室编号*/
    record *head_rec;		/*指向就诊记录链的头指针*/ 
    struct patient_tab *next;
 } patient;
 
 typedef struct depart_tab{	/*科室结构类型*/
	char num[8];  			/*科室编号*/
    char name[10];			/*科室名称*/
    char adr[20];			/*科室地址*/
    char tel[15];			/*科室电话*/
    patient *head_pat;		/*指向病人链的头指针*/
    struct depart_tab *next;
 } depart; 
 
 /*函数原型声明*/ 
void creat_cross_list(depart **head);/*创建十字交叉链表，即输入数据*/
void save_cross_list(depart *head);/*保存十字交叉链表*/
void load_cross_list(depart **head);/*读入已保存的链表数据*/
void prt_dat(depart * head);/*输出全部信息*/
void enq_pat_num(depart * head);/*按病人编号查询的函数*/
void statistic_info();/*统计信息*/
void ShowMenu(); /*显示主菜单*/
void ShowMenu_enquiry(); /*显示查询菜单*/ 
void ShowMenu_revise();	/*显示修改菜单*/ 
void enquiry_data(depart *head);/*查询数据函数*/ 
void revise_data(depart **head);/*修改数据函数*/ 
void enq_depart_num(depart *head);/*按科室编号查询的函数*/
void enq_time(depart *head);/*按就诊时间查询的函数*/

void depart_add(depart **head);
void depart_del(depart **head);
void depart_rev(depart **head);
void patient_add(depart **head);
void patient_del(depart **head);
void patient_rev(depart **head);
void record_add(depart **head);
void record_del(depart **head);
void record_rev(depart **head);

int main()
{
	depart *head=NULL;					/*科室信息头指针*/ 
	char ch;							/*选择指令的字符变量*/ 
lop:
	ShowMenu();							/*显示菜单*/ 
	printf("选择要进行的操作\n");
	scanf("%c",&ch);
	getchar();
	system("CLS");
	if(ch<'1'||ch>'7'){
		printf("指令错误，请重新输入指令\n");
		goto lop;
	}
	else
	switch(ch)
	{
		case '1':
			system("CLS");				/*清屏*/ 
			break;
		case '2':
			creat_cross_list(&head);	/*输入数据，创建链表*/ 
			system("pause"); 
			break;
		case '3':
			save_cross_list(head);		/*保存数据*/ 
			system("pause");
			break;
		case '4':
			system("CLS");
			load_cross_list(&head);		/*从磁盘载入数据*/ 
			system("pause"); 
			break;
		case '5':
			system("CLS");
			enquiry_data(head);			/*查询信息*/ 
//			system("pause"); 
			break;
		case '6':
			system("CLS");
			revise_data(&head);			/*修改信息*/ 
			load_cross_list(&head);
			system("pause"); 
			break;
		case '7':
			return 0;
	}
	goto lop;
} 
void ShowMenu()
{
	printf("\t****************************************\n");
	printf("\t1. 清屏并显示菜单;\n");
	printf("\t2. 输入数据;\n");
	printf("\t3. 保存数据到磁盘;\n");
	printf("\t4. 从磁盘读入数据;\n");
	printf("\t5. 查询输出信息;\n");
	printf("\t6. 修改数据;\n");
	printf("\t7. 退出系统\n");
	printf("\t****************************************\n");
}
void creat_cross_list(depart **head)/*创建十字交叉链表，即输入数据*/
{
	depart *hp=NULL , *p ;
	patient * php , *pp ;
	record * rhp;
	char InNum[8]="" , ch; 
loop:  
	p=(depart *)malloc(sizeof(depart));/*创建科室信息节点*/
	printf("输入科室编号 名称 地址 电话\n");
	scanf("%s %s %s %s",p->num,p->name,p->adr,p->tel);/*输入各项数据*/
	getchar();
	p->head_pat=NULL;/*置病人链头指针为NULL*/
	p->next=hp;
	hp=p;/*头指针指向新创建的结点*/
	printf("继续创建科室信息结点吗？按Y或y继续，其它字符结束。\n");
	ch=getchar();
	getchar();
	if(ch=='Y'||ch=='y')/*是，创建下一个科室信息结点*/
		goto loop;
	 *head=hp;/*否，结束创建，将调用函数中head指针指向科室信息链*/ 
	 
	 p=*head;/*p指向科室信息链头*/
	 while(p!=NULL){
	 	printf("要输入科室%s的病人信息吗？按Y或y输入，其它字符结束。\n",p->name);
		ch=getchar();
		getchar();
		while(ch=='Y'||ch=='y') {
			php=(patient*)malloc(sizeof(patient));/*创建病人结点*/
			printf("输入病人姓名 编号 住址 联系电话\n");
			scanf("%s %s %s %s",php->name,php->num,php->adr,php->tel); 
			getchar();
			strcpy(php->depart_num,p->num);/*科室编号赋值*/
			php->head_rec=NULL;/*置就诊记录链头指针为NULL*/
			php->next=p->head_pat;
			p->head_pat=php;/*头指针指向新结点*/
			printf("要继续创建科室%s的病人信息吗？按Y或y输入，其它字符结束。\n",p->name);
			ch=getchar();
			getchar(); 
		}
		pp=p->head_pat;/*pp指向病人链的头指针*/
		while(pp!=NULL){
			printf("要输入病人%s的就诊记录吗？按Y或y输入，其它字符结束。\n",pp->name);
			ch=getchar();
			getchar();
			while(ch=='Y'||ch=='y'){
				rhp=(record*)malloc(sizeof(record));/*创建就诊记录结点*/
				printf("输入就诊时间 症状\n");
				scanf("%s %s",rhp->time,rhp->sym);
				getchar();
				strcpy(rhp->name,pp->name);
				strcpy(rhp->pat_num,pp->num);
				strcpy(rhp->depart_num,p->num);/*病人姓名，编号，科室编号赋值*/
				rhp->next=pp->head_rec;
				pp->head_rec=rhp;/*头指针指向新的结点*/
				printf("要继续创建%s的就诊记录吗？按Y或y输入，其它字符结束。\n",pp->name);
				ch=getchar();
				getchar();
			}
			pp=pp->next;/*pp指向下一个病人*/
		}
		p=p->next;/*p指向下一个科室*/
	 } 
}

void save_cross_list(depart *head)					/*保存十字交叉链表*/ 
{
	FILE *out1, *out2, *out3;
	depart *p=head;
	patient *pp;
	record *ppp;
	if((out1 = fopen("depart.dat","wb"))==NULL)		/*打开科室文件*/
		exit(-1);
	if((out2 = fopen("patient.dat","wb"))==NULL)	/*打开病人文件*/ 
		exit(-1);
	if((out3 = fopen("record.dat","wb"))==NULL)		/*打开就诊记录文件*/ 
		exit(-1);
	while(p!=NULL){
		fwrite(p,sizeof(depart),1,out1);			/*写科室信息*/ 
		pp=p->head_pat;								/*病人遍历指针指向病人链头*/ 
		while(pp!=NULL){
			fwrite(pp,sizeof(patient),1,out2);		/*写病人信息*/ 
			ppp=pp->head_rec;						/*就诊记录指针指向就诊记录链头*/ 
			while(ppp!=NULL){
				fwrite(ppp,sizeof(record),1,out3);	/*写就诊记录信息*/ 
				ppp=ppp->next;						/*指向下一个就诊记录*/ 
			}
			pp=pp->next;							/*指向下一个病人*/ 
		}
		p=p->next;									/*指向下一个科室*/ 
	} 
	fclose(out1);									/*关闭三个文件*/ 
	fclose(out2);
	fclose(out3);
	printf("数据保存成功！\n");
}

void load_cross_list(depart **head)					/*从磁盘载入数据*/ 
{
	FILE * in1, *in2, *in3;							/*三个文件指针*/ 
	depart *hp=NULL,*p;
	patient *pp;
	record *rhp;
	if((in1=fopen("depart.dat","rb"))==NULL){		/*打开文件*/ 
		printf("未找到完整数据文件\n"); 			/*打开文件失败的错误说明*/
		exit(-1); 
	} 
	if((in2=fopen("patient.dat","rb"))==NULL){
		printf("未找到完整数据文件\n"); 
		exit(-1); 
	}
	if((in3=fopen("record.dat","rb"))==NULL){
		printf("未找到完整数据文件\n"); 
		exit(-1); 
	}
	while(!feof(in1)){								/*读取科室信息数据文件，创建信息链表*/
		p=(depart *)malloc(sizeof(depart));
		fread(p,sizeof(depart),1,in1);
		if(!feof(in1)){
			p->head_pat=NULL;
			p->next=hp;
			hp=p;
		}
	}
	*head=hp;
	
	while(!feof(in2)){								/*读取病人信息数据文件，创建信息链表*/ 
		pp=(patient *)malloc(sizeof(patient));
		fread(pp,sizeof(patient),1,in2);
		pp->head_rec=NULL;
		if(!feof(in2)){
			p=*head;
			while(p!=NULL){
				if(!strcmp(p->num,pp->depart_num)){/*科室编号匹配则将该病人放到该科室*/ 
					pp->next=p->head_pat;
					p->head_pat=pp;
					break;
				}
				else
					p=p->next;
			}
		}
	}
	
	
	while(!feof(in3)){								/*读取就诊记录信息数据文件，创建信息链表*/ 
		rhp=(record *)malloc(sizeof(record));
		fread(rhp,sizeof(record),1,in3);
		if(!feof(in3)){
			p=*head;
			while(p!=NULL){
				pp=p->head_pat;
				while(pp!=NULL){
					if((!strcmp(p->num,rhp->depart_num))&&(!strcmp(rhp->pat_num,pp->num))){
													/*科室编号和病人编号都匹配则将该就诊记录放到该病人记录中*/ 
						rhp->next=pp->head_rec;
						pp->head_rec=rhp;
						goto Break;
					}
					else
						pp=pp->next;
				}
				p=p->next;
			}
		Break:
			;	
		}
	}
	printf("数据载入成功！\n"); 
}

void prt_dat(depart *head)		/*输出全部信息*/ 
{
	depart *p=head;				/*科室指针*/ 
	patient *pp;				/*病人指针*/ 
	record *ppp;				/*就诊记录指针*/ 
	while(p!=NULL){				/*未到最后一个科室*/ 
		printf("科室编号\t科室名称\t科室地址\t科室电话\t\n");
		printf("%8s\t%8s\t%8s\t%s\t\n",p->num,p->name,p->adr,p->tel);
		pp=p->head_pat;
		while(pp!=NULL){		/*未到科室的最后一个病人*/ 
			printf("\t病人编号\t病人姓名\t    病人电话\t病人住址\t\n");
			printf("\t%8s\t%8s\t%12s\t%8s\t\n",pp->num,pp->name,pp->tel,pp->adr);
			ppp=pp->head_rec;
			printf("\t\t就诊时间\t症状\t\n");
			while(ppp!=NULL){	/*未到病人的最后一条就诊记录*/ 
				printf("\t\t%8s\t%s\t\n",ppp->time,ppp->sym);
				ppp=ppp->next;
			}
			pp=pp->next;
		}
		p=p->next;
	} 
} 


void statistic_info()
{
	
}
 
void ShowMenu_enquiry()		/*查询信息的子菜单*/ 
{
	printf("请选择查询方式:\n");
	printf("\t****************************************\n"); 
	printf("\t1. 输出全部信息;\n");
	printf("\t2. 按科室编号查询;\n");
	printf("\t3. 按病人编号查询;\n");
	printf("\t4. 按就诊日期查询;\n");
	printf("\t5. 返回上一级;\n");
	printf("\t****************************************\n");
} 

void enquiry_data(depart *head) 		/*查询数据子函数*/
{
	depart *hp=head;
	char ch_enq;						/*选择指令的字符变量*/
show_enq:
	ShowMenu_enquiry();					/*显示菜单*/ 
input:
	scanf("%c",&ch_enq);
	getchar();
	system("CLS");
	if(ch_enq<'1'||ch_enq>'5'){
		printf("指令错误，请重新输入\n");
		goto show_enq;
	}
	else
	switch(ch_enq)
	{
		case '1':
			prt_dat(hp);				/*输出全部信息*/
			break;
		case '2':
			enq_depart_num(hp);			/*按科室编号查询*/ 
			break;
		case '3':
			enq_pat_num(hp);			/*按病人编号查询*/ 
			break;
		case '4':
			enq_time(hp);				/*按就诊日期查询*/ 
			break;
		case '5':
			return;						/*返回*/ 
	}
	goto show_enq;
} 

void enq_pat_num(depart *head)		/*按病人编号查找病人*/
{
	depart *p=head;					/*科室指针*/     
	patient *pp;        			/*病人指针*/     
	record *ppp;					/*就诊记录指针*/ 
	char aim_num[8];				/*要查找的病人编号*/ 
	printf("请输入病人编号\n");
	scanf("%s",aim_num);
	getchar();
	while(p!=NULL){					/*未到最后一个科室*/ 
		pp=p->head_pat;
		while(pp!=NULL){			/*未到该科室最后一个病人*/ 
			if(!strcmp(aim_num,pp->num)){	/*如果编号匹配*/ 
				printf("%s %s %s\n",p->name,pp->num,pp->name);/*输出病人信息和就诊记录*/ 
				ppp=pp->head_rec;
				while(ppp!=NULL){
					printf("%s %s\n",ppp->time,ppp->sym);
					ppp=ppp->next;	/*指向下一条就诊记录*/ 
				}
			}
			pp=pp->next;		 	/*指向下一个病人*/ 
		}
		p=p->next;					/*指向下一科室*/ 
	}
}

void enq_depart_num(depart *head)				/*按科室编号查询*/ 
{
	char aim_num[8];							/*目标编号*/
	printf("请输入要查询的科室编号:\n");		 
	scanf("%s",aim_num);
	getchar();
	depart *p=head;
	patient *pp;
	while(p!=NULL){								/*未到最后一个科室*/ 
		if(!strcmp(p->num,aim_num)){			/*编号匹配*/ 
			printf("科室编号：%s\n",p->num);	/*输出信息*/ 
			printf("科室名称：%s\n",p->name);
			printf("科室地址：%s\n",p->adr);
			printf("科室电话：%s\n",p->tel);
			int n=0;							/*统计病人人数*/ 
			pp=p->head_pat;
			while(pp!=NULL) {
				n++;
				pp=pp->next;
			}
			printf("病人人数：%d\n",n);
		}
		p=p->next;
	}
}

void enq_time(depart *head)							/*按就诊日期查询*/ 
{
	depart *p=head; 
	patient *pp;
	record *ppp;
	char aim_time[9];
	printf("输入要查询的日期，格式如20150722\n");	
	scanf("%s",aim_time);
	getchar();
	printf("病人编号 病人姓名 就诊科室 就诊日期 症状\n");
	while(p!=NULL){
		pp=p->head_pat;
		while(pp!=NULL){
			ppp=pp->head_rec;
			while(ppp!=NULL){
				if(!strcmp(ppp->time,aim_time)){	/*日期匹配*/
					printf("%8s %8s %8s %8s %s\n",pp->num,pp->name,p->name,ppp->time,ppp->sym);
				}
				ppp=ppp->next;
			}
			pp=pp->next;
		}
		p=p->next;
	} 
}
 
 void ShowMenu_revise()		/*修改数据的子菜单*/ 
 {
	printf("\t****************************************\n");
	printf("\t1. 增加科室;\n");
	printf("\t2. 删除科室;\n");
	printf("\t3. 修改现有科室;\n");
	printf("\t4. 增加某科室病人;\n");
	printf("\t5. 删除某科室病人;\n");
	printf("\t6. 修改现有某科室某病人;\n");
	printf("\t7. 增加某病人就诊记录;\n");
	printf("\t8. 删除某病人就诊记录;\n");
	printf("\t9. 修改某病人的现有的就诊记录;\n");
	printf("\t0. 返回上一级;\n");
	printf("\t****************************************\n");
	printf("请选择修改方式:\n");
 } 

void revise_data(depart **head)
{
	depart *hp=*head;
	int ch_rev;
show_rev:
	ShowMenu_revise();
	scanf("%d",&ch_rev);
	getchar();
	system("CLS");
	if(ch_rev<0||ch_rev>9){
		printf("指令错误，请重新输入\n");
		goto show_rev;
	}
	else
	switch(ch_rev)
	{
		case 1:
			depart_add(&hp);
			break;
		case 2:
			depart_del(&hp);
			break;
		case 3:
			depart_rev(&hp);
			break;
		case 4:
			patient_add(&hp);
			break;
		case 5:
			patient_del(&hp);
			break;
		case 6:
			patient_rev(&hp);
			break;
		case 7:
			record_add(&hp);
			break;
		case 8:
			record_del(&hp);
			break;
		case 9:
			record_rev(&hp);
			break;
		case 0:
			return;
	}
	save_cross_list(hp);
	*head=hp;
	system("pause");
	goto show_rev;
}

void depart_add(depart **head)/*添加科室*/
{
	char ch;
	depart *hp=*head,*p;
	patient *pp,*php;
	record *ppp,*rhp;
	p=(depart *)malloc(sizeof(depart));
	printf("输入科室编号 名称 地址 电话\n");
	scanf("%s %s %s %s",p->num,p->name,p->adr,p->tel);/*输入各项数据*/
	getchar();
	p->head_pat=NULL;/*置病人链头指针为NULL*/
	p->next=hp;
	hp=p;/*头指针指向新创建的结点*/
	*head=hp;
	printf("要输入科室%s的病人信息吗？按Y或y输入，其它字符结束。\n",p->name);
		ch=getchar();
		getchar();
		while(ch=='Y'||ch=='y') {
			php=(patient*)malloc(sizeof(patient));/*创建病人结点*/
			printf("输入病人姓名 编号 住址 联系电话\n");
			scanf("%s %s %s %s",php->name,php->num,php->adr,php->tel);
			getchar();
			strcpy(php->depart_num,p->num);/*科室编号赋值*/
			php->head_rec=NULL;/*置就诊记录链头指针为NULL*/
			php->next=p->head_pat;
			p->head_pat=php;/*头指针指向新结点*/
			printf("要继续创建科室%s的病人信息吗？按Y或y输入，其它字符结束。\n",p->name);
			ch=getchar();
			getchar(); 
		}
		pp=p->head_pat;/*pp指向病人链的头指针*/
		while(pp!=NULL){
			printf("要输入病人%s的就诊记录吗？按Y或y输入，其它字符结束。\n",pp->name);
			ch=getchar();
			getchar();
			while(ch=='Y'||ch=='y'){
				rhp=(record*)malloc(sizeof(record));/*创建就诊记录结点*/
				printf("输入就诊时间 症状\n");
				scanf("%s %s",rhp->time,rhp->sym);
				getchar();
				strcpy(rhp->name,pp->name);
				strcpy(rhp->pat_num,pp->num);
				strcpy(rhp->depart_num,p->num);/*病人姓名，编号，科室编号赋值*/
				rhp->next=pp->head_rec;
				pp->head_rec=rhp;/*头指针指向新的结点*/
				printf("要继续创建%s的就诊记录吗？按Y或y输入，其它字符结束。\n",pp->name);
				ch=getchar();
				getchar();
			}
			pp=pp->next;/*pp指向下一个病人*/
		}
		
}

void depart_del(depart **head)/*删除科室*/ 
{
	depart *hp=*head,*p,*p_back=NULL;/*p为指向目标结点的指针，p_back为指向目标结点之前结点的指针*/ 
	patient *pp,*pp_back;
	record *ppp,*ppp_back;
	char aim_num[8];/*目标科室的编号*/ 
in_num: 
	printf("输入要删除的科室编号：\n或输入exit退出该操作\n");
	scanf("%s",aim_num);
	getchar();
	p=hp;
	while(p!=NULL){
		if(!strcmp(aim_num,"exit")){/*输入exit可退出该次操作*/ 
			return;
		}
		if(!strcmp(aim_num,p->num)){/*科室编号匹配，找到目标结点*/ 
			break;
		}
		p_back=p;
		p=p->next;
	}
	if(p==NULL){/*遍历链表未找到匹配的编号*/ 
		printf("不存在该科室！\n");
		goto  in_num;
	}
	if(p_back==NULL){/*目标结点为第一个结点*/ 
		hp=hp->next;
		*head=hp;
	}
	else{/*目标结点不是第一个结点*/ 
		p_back->next=p->next;
	}
	pp=p->head_pat;	
	while(pp!=NULL){/*循环释放病人信息链*/ 
		ppp=pp->head_rec;
		while(ppp!=NULL){/*释放就诊记录信息链*/ 
			ppp_back=ppp;
			ppp=ppp->next;
			free(ppp_back);
		}
		pp_back=pp;
		pp=pp->next;
		free(pp_back);
	}
	free(p);
}

void depart_rev(depart **head)
{
	int aim;/*要修改的内容的选项*/ 
	depart *hp=head,*p;/*p为指向目标结点的指针*/ 
	char aim_num[8];/*目标科室的编号*/ 
	load_cross_list(&p);
in_num: 
	printf("输入要修改的科室编号：\n或输入exit退出该操作\n");
	scanf("%s",aim_num);
	getchar();
//	p=hp;
	while(p!=NULL){
		if(!strcmp(aim_num,"exit")){/*输入exit可退出该次操作*/ 
			return;
		}
		if(!strcmp(aim_num,p->num)){/*科室编号匹配，找到目标结点*/ 
			break;
		}
		p=p->next;
	}
	if(p==NULL){/*遍历链表未找到匹配的编号*/ 
		printf("不存在该科室！\n");
		goto  in_num;
	}
	printf("当前科室信息为：\n");
	printf("科室编号 科室名称 科室电话    科室地址\n");
	printf("%8s %8s %11s %s\n",p->num,p->name,p->tel,p->adr);
	printf("请输入正确的科室信息：\n");
	printf("科室编号 科室名称 科室电话 科室地址\n");
	scanf("%s %s %s %s",p->num,p->name,p->tel,p->adr);
}

void patient_add(depart **head)
{
	
}

void patient_del(depart **head)
{
	
}

void patient_rev(depart **head)
{
	
}
void record_add(depart **head)
{
	
}

void record_del(depart **head)
{
	
}

void record_rev(depart **head)
{
	
}





