《数据结构的课程设计》报告题目:家谱管理系统设计与实现班级:1612401学号:*********姓名:***指导老师:**完成日期:2014.1.3目录一.需求分析.二.程序主要功能.三.程序运行平台.四.程序类说明.五.运行分析六.存在的不足与对策.七.体验感悟八.程序源代码.需求分析实现具有下列功能的家谱管理系统。
程序主要功能(1)输入文件以存放最初家谱中各成员的信息,成员的信息中均应包含以下内容:姓名、出生日期、婚否、地址、健在否、死亡日期(若其已死亡),也可附加其它信息、但不是必需的。
(2)实现数据的存盘和读盘。
(3)以图形方式显示家谱。
(4)显示第n 代所有人的信息。
(5)按照姓名查询,输出成员信息(包括其本人、父亲、孩子的信息)。
(6)按照出生日期查询成员名单。
(7)输入两人姓名,确定其关系。
(8)某成员添加孩子。
(9)删除某成员(若其还有后代,则一并删除)。
(10)修改某成员信息。
(11)按出生日期对家谱中所有人排序。
(12)打开一家谱时,提示当天生日的健在成员。
(13)要求建立至少30个成员的数据,以较为直观的方式显示结果,并提供文稿形式以便检查。
(14)界面要求:有合理的提示,每个功能可以设立菜单,根据提示,可以完成相关的功能要求。
(15)存储结构:根据系统功能要求自行设计,但是要求相关数据要存储在数据文件中。
测试数据:要求使用1、全部合法数据;2、局部非法数据。
进行程序测试,以保证程序的稳定。
程序运行平台该程序是用VC++6.0制做的,使用Microsoft Visual C++ 6.0运行该程序,具体操作是:打开Microsoft Visual C++ 6.0,菜单栏里点文件→打开工作区→找到“图书管理系统.dsw”这个文件→打开,或者在资源管理器中双击该文件,此时,VC++6.0会自动打开,并载入该系统相关资源,点击Run命令菜单或者或用快捷键Ctrl+F5运行该程序。
程序类说明函数分析:void setupinfo(per person[30]) //创建信息void displayhome(per person[30],int &n2) 显示家谱void displaylive(per person[30],int &n2) 现今健在的成员void displayinfo(per person[30],int &n2) //显示代数void namesearch(per person[30],int &n2) 姓名查询void birtfdaysearch(per person[30],int &n2)生日查询void addchild(per person[30],int &n2)添加孩子void editmember(per person[30],int &n2)修改信息void clear(per person[30],int &n2)删除成员void FixRelation(per person[30],int &n2)//输入两人姓名,确定其关系void display(per person[30],int &n1)交互界面运行分析;显示家谱姓名查找生日排序生日查找比较关系存在的不足与对策由于自身能力有限,所以没有设计提示当天生日的健在成员。
在设计过程中由于设计者的编程功底欠缺,因此学习过程较为艰辛,需要解决的问题也比较多。
在以后的学习中,应该循序渐进,不可急于求成,先打好基础,这样才能更好地发展。
体验感悟在编写程序的过程中,深切的体会到自身能力还有待提高,通过大规模的查询网上资料与相关书籍我学习到了很多以前不知道的编程方法与各种奇妙的函数语句时,提高了自己对程序设计本身的兴趣,更加乐意去学习这方面的新的东西,并在不断地自我挑战中收获着,或知识技能,或信心勇气。
希望自己在今后的学习中可以更好的完善自我。
程序源代码#include<iostream.h>#include<string.h>#include<fstream.h>#include<stdlib.h>#include<stdio.h>struct per{int father;char name[20];char brith[20];char marry;char address[20];char live;char dietime[20];char parent[20];int generation;int child[10];int numberchild;per(){for(int i=0;i<20;i++)name[i]='\0';for(i=0;i<20;i++)brith[i]='\0';for(i=0;i<20;i++)address[i]='\0';for(i=0;i<20;i++)dietime[i]='\0';for(i=0;i<10;i++)child[i]=0;for(i=0;i<20;i++)parent[i]='\0';live='\0';marry='\0';father=-10;generation=0;numberchild=0;}};void setupinfo(per person[30]) //创建信息{int i,j,k;char choose;choose='y';fstream fp("person.txt",ios::in|ios::out|ios::binary|ios::app);i=0;while(toupper(choose)=='Y'){cout<<" 姓名: ";cin.getline(person[i].name,20);cout<<" 生日(日期样式为1999.01.02) : ";cin.getline(person[i].brith,20);cout<<" 婚否y/n :";cin>>person[i].marry;while(toupper(person[i].marry)!='Y'&&toupper(person[i].marry)!='N') {cout<<" 你输入错误,请你重新输入!!"<<endl;cout<<" 婚否y/n :";cin>>person[i].marry;}cin.ignore();cout<<" 地址: ";cin.getline(person[i].address,20);cout<<" 是否健在y/n :";cin>>person[i].live; //是否死亡while(toupper(person[i].live)!='Y'&&toupper(person[i].live)!='N') {cout<<" 你输入错误,请你重新输入!!"<<endl;cout<<" 婚否y/n :";cin>>person[i].live;}cin.ignore();if(toupper(person[i].live)=='N'){cout<<" 死亡日期(日期样式为1999.01.02) :";cin.getline(person[i].dietime,20);// 输入死亡日期}cout<<" 属于第几代: ";cin>>person[i].generation;cin.ignore();if(person[i].generation!=1) //不是第一代{cout<<" 他的父亲: ";cin.getline(person[i].parent,20);}cout<<endl;cout<<"请问是否继续添加y/n"<<endl;cin>>choose;cin.ignore();i++;}for(j=0;j<i;j++){if(person[j].generation==1)person[j].father=-1;}for(j=0;j<i;j++){for(k=0;k<i;k++){if(strcmp(person[j].parent,person[k].name)==0) //比较2个字符串是否相同,实质是找某个人的父亲person[j].father=k;}}for(j=0;j<i;j++){for(k=0;k<i;k++){if(strcmp(person[j].parent,person[k].name)==0){person[k].child[person[k].numberchild]=j;person[k].numberchild++; //找某个人的孩子}}}for(j=0;j<i;j++)fp.write((char*)(person+j),sizeof(*person));fp.close(); //关闭文件夹cout<<endl;}void displayhome(per person[30],int &n2) //调用函数的参数传递的是一个参数地址{int i,j,max;char again;cout<<endl<<endl;if(n2==1)max=1;elsefor(i=0;i<n2-1;i++){max=person[i].generation;for(j=i+1;j<n2;j++){if(person[i].generation<person[j].generation)max=person[j].generation; //找出最大的代数}}for(i=1;i<=max;i++){cout<<" 第"<<i<<"代的成员有: ";for(j=0;j<n2;j++){if(person[j].generation==i)cout<<person[j].name<<" "; //输出每一代的人}cout<<endl;}cout<<endl<<endl;cout<<" 你是否想继续查看?请输入y/n!"<<endl;cin>>again;if(toupper(again)=='Y') //就是判断输入得是否为y或Y{cout<<endl;return;}if(toupper(again)=='N')exit(0); //终止程序的执行}void displaylive(per person[30],int &n2){int i;cout<<endl<<endl;cout<<"现今健在的成员:";for(i=1;i<=n2;i++){if(person[i].live!='N'&&person[i].live!='n')cout<<person[i].name<<" "; //输出每一代的人}cout<<endl<<endl;return;}void displayinfo(per person[30],int &n2) //显示代数{int i,gen,j=0;char again;cout<<endl<<endl;cout<<" 请你输入你要查询的代数: ";cin>>gen;cout<<endl; //换行for(i=0;i<n2;i++){if(person[i].generation!=gen)j++;}if(j==n2) //判断是否找到cout<<" 你要查的代数还没有"<<endl<<endl;for(i=0;i<n2;i++){if(person[i].generation==gen){cout<<" 姓名: "<<person[i].name<<endl<<" 出生日期: "<<person[i].brith<<" 第几代: "<<person[i].generation<<endl<<" 婚否: "<<person[i].marry<<" 地址:"<<person[i].address<<endl<<" 是否健在: "<<person[i].live<<endl;if(person[i].live=='N'||person[i].live=='n')cout<<" 死亡日期: "<<person[i].dietime<<endl;cout<<endl<<endl;}}cout<<" 你是否想继续查看?请输入y/n"<<endl;cin>>again;if(toupper(again)=='Y'){cout<<endl;return;}if(toupper(again)=='N')exit(0);}void namesearch(per person[30],int &n2){int i,j=0,k;char again,name[20];cout<<endl<<endl;cout<<" 请你输入你想要查询的人的姓名: ";cin.getline(name,20);for(i=0;i<n2;i++){if(strcmp(person[i].name,name)!=0)j++;}cout<<endl<<endl;if(j==n2)cout<<" 你要查询的人没有"<<endl<<endl;for(i=0;i<n2;i++){if(strcmp(person[i].name,name)==0){cout<<" 姓名: "<<person[i].name<<endl<<" 出生日期: "<<person[i].brith<<" 第几代: "<<person[i].generation<<endl<<" 婚否: "<<person[i].marry<<" 地址:"<<person[i].address<<endl<<" 是否健在: "<<person[i].live<<endl;if(person[i].live=='N'||person[i].live=='n')cout<<" 死亡日期: "<<person[i].dietime<<endl;cout<<endl<<endl;if(person[i].generation==1)cout<<" 他是这个家的根,没有父亲"<<endl<<endl;else{cout<<" 他父亲的信息: "<<endl;cout<<" 姓名: "<<person[person[i].father].name<<endl<<" 出生日期: "<<person[person[i].father].brith<<" 第几代: "<<person[person[i].father].generation<<endl<<" 婚否: "<<person[person[i].father].marry<<" 地址:"<<person[person[i].father].address<<endl<<" 是否健在: "<<person[person[i].father].live<<endl;if(person[person[i].father].live=='N'||person[person[i].father].live=='n')cout<<" 死亡日期: "<<person[person[i].father].dietime<<endl;cout<<endl<<endl;}if(person[i].numberchild==0)cout<<" 他没有孩子"<<endl<<endl;else{cout<<" 他有"<<person[i].numberchild<<"个孩子,他们的信息:"<<endl<<endl;for(k=0;k<person[i].numberchild;k++){cout<<" 姓名: "<<person[person[i].child[k]].name<<endl<<" 出生日期: "<<person[person[i].child[k]].brith<<" 第几代: "<<person[person[i].child[k]].generation<<endl<<" 婚否: "<<person[person[i].child[k]].marry<<" 地址:"<<person[person[i].child[k]].address<<endl<<" 是否健在: "<<person[person[i].child[k]].live;if(person[person[i].child[k]].live=='N'||person[person[i].child[k]].live==' n')cout<<" 死亡日期: "<<person[person[i].child[k]].dietime<<endl;cout<<endl<<endl;}}}}cout<<" 你是否想继续查看?请输入y/n"<<endl;cin>>again;if(toupper(again)=='Y'){cout<<endl;return;}if(toupper(again)=='N')exit(0);}void birtfdaysearch(per person[30],int &n2){char begbir[20],endbir[20],again;int i,flag=0;cout<<endl<<endl;cout<<" 请你输入两个时间,格式为1999.01.02!"<<endl;cout<<" 起始时间是: ";cin.getline(begbir,20);cout<<" 终止时间是: ";cin.getline(endbir,20);cout<<endl<<endl;for(i=0;i<n2;i++){if(strcmp(person[i].brith,begbir)>=0&&strcmp(person[i].brith,endbir)<= 0){cout<<" 姓名: "<<person[i].name;cout<<" 生日: "<<person[i].brith;flag=1;cout<<endl;}}cout<<endl<<endl;if(flag==0)cout<<" 在这段时间内没有人生日"<<endl<<endl;cout<<" 你是否想继续查看?请输入y/n"<<endl;cin>>again;if(toupper(again)=='Y'){cout<<endl;return;}if(toupper(again)=='N')exit(0);}void addchild(per person[30],int &n2){int i;char again;fstream file("person.txt",ios::in|ios::out|ios::binary|ios::app);cout<<endl<<endl;cout<<" 请输入孩子的信息"<<endl<<endl<<endl;cout<<" 姓名: ";cin.getline(person[n2].name,20);cout<<" 生日(日期样式为1999.01.02) : ";cin.getline(person[n2].brith,20);cout<<" 婚否y/n :";cin>>person[n2].marry;while(toupper(person[n2].marry)!='Y'&&toupper(person[n2].marry)!=' N'){cout<<" 你输入错误,请你重新输入!!"<<endl;cout<<" 婚否y/n :";cin>>person[n2].marry;}cin.ignore();cout<<" 地址: ";cin.getline(person[n2].address,20);cout<<" 是否健在y/n :";cin>>person[n2].live;while(toupper(person[n2].live)!='Y'&&toupper(person[n2].live)!='N') {cout<<" 你输入错误,请你重新输入!!"<<endl;cout<<" 婚否y/n :";cin>>person[n2].live;}cin.ignore();if(toupper(person[n2].live)=='N'){cout<<" 死亡日期(日期样式为1999.01.02) :";cin.getline(person[n2].dietime,20);}cout<<" 属于第几代: ";cin>>person[n2].generation;cin.ignore();if(person[n2].generation!=1){cout<<" 他的父亲: ";cin.getline(person[n2].parent,20);}for(i=0;i<n2;i++){if(strcmp(person[n2].parent,person[i].name)==0){person[n2].father=i;break;}}//if(i==n2){cout<<"输入信息有误!!"<<endl<<endl;return;}cout<<endl;for(i=0;i<n2;i++){if(strcmp(person[n2].parent,person[i].name)==0){person[n2].father=i;break;}}file.write((char*)&person[n2],sizeof(person[n2]));file.close();file.open("person.txt",ios::in|ios::out|ios::binary);file.seekp(i*sizeof(per),ios::beg);person[i].child[person[i].numberchild]=n2;person[i].numberchild++;file.write((char*)&person[i],sizeof(per));file.close();n2++;cout<<" 你是否想继续查看?请输入y/n"<<endl;cin>>again;if(toupper(again)=='Y'){cout<<endl;return;}if(toupper(again)=='N')exit(0);}void editmember(per person[30],int &n2){int i,flag=0,choice;char name[20],again;fstream file("person.txt",ios::in|ios::out|ios::binary);cout<<endl<<endl;cout<<" 请你输入你想修改的成员的名字: ";cin.getline(name,20);cout<<endl<<endl;for(i=0;i<n2;i++){if(strcmp(person[i].name,name)==0){flag=1;break;}}if(flag==0)cout<<" 家谱中没有这个人!!"<<endl<<endl<<endl;if(flag==1){cout<<"\t\t请你选择你要修改的项!!"<<endl;cout<<" 1.姓名"<<endl;cout<<" 2.地址"<<endl;cout<<" 3.婚否"<<endl;cout<<" 4.生日"<<endl;cout<<" 5.是否死亡"<<endl;cout<<" 6.死亡日期"<<endl;cin>>choice;while(choice!=1&&choice!=2&&choice!=3&&choice!=4&&choice!=5&&choice!=6){cout<<"you enter wrong!"<<endl;cout<<"please enter again!"<<endl;cin>>choice;}cin.ignore(1,'\n');switch(choice){case 1: cout<<endl<<" 请你输入新名字: ";cin.getline(person[i].name,20);break;case 2: cout<<endl<<" 请输入新的地址: ";cin.getline(person[i].address,20);break;case 3: cout<<endl<<" 请你输入新的是否结婚: ";cin>>person[i].marry;break;case 4: cout<<endl<<" 请你输入新的生日: ";cin.getline(person[i].brith,20);break;case 5: cout<<endl<<" 请你输入新的是否死亡: ";cin>>person[i].live;break;case 6: cout<<endl<<" 请你输入新的死亡日期: ";cin.getline(person[i].dietime,20);break;}for(int j=0;j<n2;j++)file.write((char*)&person[j],sizeof(per));}cout<<endl<<endl;cout<<" 你是否想继续查看?请输入y/n"<<endl;cin>>again;if(toupper(again)=='Y'){cout<<endl;return;}if(toupper(again)=='N')exit(0);}void sortbirthday(per person[30],int &n2){per person1;int i,j;char again;cout<<endl<<endl;for(i=0;i<n2-1;i++)for(j=i+1;j<n2;j++){if(strcmp(person[i].brith,person[j].brith)>=0){person1=person[i];person[i]=person[j];person[j]=person1;}}for(i=0;i<n2;i++)cout<<" 姓名: "<<person[i].name<<" 生日: "<<person[i].brith<<endl;cout<<endl<<endl;cout<<" 你是否想继续查看?请输入y/n"<<endl;cin>>again;if(toupper(again)=='Y'){cout<<endl;return;}if(toupper(again)=='N')exit(0);}void clear(per person[30],int &n2){fstream fp("person.txt",ios::out);int k,j,l,h=0,i=n2;char name[20],again;cout<<" 请你输入你想删除的成员的名字: ";cin.getline(name,20);for(k=0;k<i;k++){if(strcmp(name,person[k].name)==0)break;}if(person[k].father==-1){fp.write("",0);}else{h=0;for(l=0;l<person[person[k].father].numberchild;l++) {if(person[person[k].father].child[l]==k)continue;person[person[k].father].child[h]=person[person[k].father].child[l];h++;}person[person[k].father].numberchild--;person[person[k].father].child[h]=NULL;}if(person[k].numberchild!=0){for(j=0;j<i;j++){h=0;if(j==k)h=1;for(l=0;l<person[k].numberchild;l++)if(j==person[k].child[l])h=1;if(h==0)fp.write((char*)(person+j),sizeof(*person)); }}else{for(j=0;j<i;j++)if(j!=k)fp.write((char*)(person+j),sizeof(*person));n2--;}fp.close(); //关闭文件夹fstream inputFile("person.txt",ios::in|ios::out|ios::binary);if(!inputFile){cout<<"文件不存在!"<<endl;exit(0);}int count=0;inputFile.read((char*)&person[count],sizeof(person[count]));//从文件中读取指定大小的字节函数read(),读取字节函数while(!inputFile.eof()) //当文件没有读取完毕,进行循环{if(person[count].name[0]!='\0')//当名字不为空时{ count++; //统计人数inputFile.read((char*)(person+count),sizeof(*person));}}n2=count;inputFile.close();//关闭文件cout<<" 你是否想继续查看?请输入y/n"<<endl;cin>>again;if(toupper(again)=='Y'){cout<<endl;return;}if(toupper(again)=='N')exit(0);}void FixRelation(per person[30],int &n2)//输入两人姓名,确定其关系{int levo,levt,i,flag=0;char levone[20],levtwo[20],name[20],again;if(n2<=1){cout<<"该家谱,无法使用此功能!"<<endl;return ;}printf("请输入第一个人的姓名\n");scanf("%s",name);strcpy(levone,name);for(i=0;i<n2;i++){if(strcmp(person[i].name,name)==0){flag=1;break;}}if(flag==0){cout<<" 家谱中没有这个人!!"<<endl<<endl<<endl;return;}levo=person[i].generation;;flag=0;printf("请输入第二个人的姓名\n");scanf("%s",name);strcpy(levtwo,name);for(i=0;i<n2;i++){if(strcmp(person[i].name,name)==0){flag=1;break;}}if(flag==0){cout<<" 家谱中没有这个人!!"<<endl<<endl<<endl;return;}levt=person[i].generation;if(levo < levt){if((levt-levo)==1)printf("\t%s 是%s 的父辈\n",levone,levtwo);else if((levt-levo)==2)printf("\t%s 是%s 的爷爷辈\n",levone,levtwo);else printf("\t%s 比%s 大%d 辈\n",levone,levtwo,levt-levo);}else if(levo > levt){if((levo-levt)==1)printf("\t%s 是%s 的父辈\n",levtwo,levone);else if((levo-levt)==2)printf("\t%s 是%s 的爷爷辈\n",levtwo,levone);elseprintf("\t%s 比%s 大%d 辈\n",levtwo,levone,levo-levt);} else if(levo == levt)printf("\t\t%s 和%s 平辈\n",levone,levtwo);cout<<endl<<endl;cout<<" 你是否想继续查看?请输入y/n"<<endl;cin>>again;if(toupper(again)=='Y'){cout<<endl;return;}if(toupper(again)=='N')exit(0);}void display(per person[30],int &n1){int choice;while(1){cout<<"\t家族关系查询系统"<<endl;cout<<"0.退出系统"<<endl;cout<<"1.显示家谱"<<endl;cout<<"2.显示第n代人的所有信息"<<endl;cout<<"3.按照姓名查询某成员的信息"<<endl;cout<<"4.按照出生日期查询成员名单"<<endl;cout<<"5.某成员添加孩子"<<endl;cout<<"6.修改某成员信息"<<endl;cout<<"7.按生日日期对家谱中的所有人进行排序"<<endl;cout<<"8.删除一个成员"<<endl;cout<<"9.比较任意两成员的关系"<<endl;cin>>choice;while (choice>9||choice<0){cout<<"输入错误!请重新输入。