基本要求:从文件中读入家庭成员建立家谱,以孩子兄弟表示法存储。
基本功能:
(1) 在家谱中添加新成员,并追加到文件中。
(2) 输出指定家庭的所有成员。
(3) 确定指定成员在家族中的辈份(第几代)。
(4) 输出指定辈的所有成员。
文件输入样本:(也可以是英文名字)
吴义昌(吴本宜、吴本质、吴本身)
吴本宜(吴正民、吴正权)
吴正民(吴鲲、吴鹏)
吴正权(吴德峰)
吴本质(吴正跃)
吴正跃(吴德红、吴德龙)
吴本身(吴正亮、吴正党)
吴正亮(吴昊、吴昱)
实验源程序:
#include #include #include #include #define NAME_length 50 //名字最大长度 #define LINE_length 100 //文本行最大长度 typedef struct cc { struct cc *child, *next;//next指向同辈份的人物 char Name[]; }JPNode; void clear(char p[],int n) //清空字符数组p { while(n-- > 0) *p++ = '\\0'; } static JPNode *last = NULL; static int last_level = 0; void AddJP(JPNode **head, char const name[], int level) { JPNode **s = head, *r = NULL; JPNode *p = (JPNode *)malloc( 2*sizeof(void *) + strlen(name) + 1 ); p->child = p->next = NULL; strcpy(p->Name,name); if( *s == NULL) { *s = p; last = p; return; } if(level - last_level == 1) {last->child = p; last = p;last_level = level;return;} if((level == last_level) && (*s != NULL)){last->next = p; last = p;last_level = level;return;} r = *s; //r指向家谱树 last_level = level; while( level-- > 0) //找到相同的辈分 { while(r->next != NULL)r = r->next; r = r->child; }//以兄弟连接 while( r->next != NULL) r = r->next; r->next = p; last = p; } void CreatJP(JPNode **head) { char name[NAME_length]=\"\ char *p = NULL; int level=0,i=0; //辈分,以制表符个数表示 FILE *fp = NULL; fp = fopen(\"jiapu_data.txt\ if(fp == NULL){ printf(\"open error!\\n\"); exit(1); } while(level=0, i=0, fgets(line,LINE_length,fp) != NULL) { p = line; while(*p++ == '\')level++; //计算辈分 ,计算完后p指向名字开始处 while(line[i++] != '\\n') ; line[i-1]='\\0'; //读入的换行符用字符串结束标识符替换 strcpy(name,p-1); AddJP(head,name,level); clear(name,NAME_length); clear(line,LINE_length); } fclose(fp); } void DispJP(JPNode *p)//从p指向的结点显示该家族 { static int level=0; int i; if(p != NULL) { for(i=0;i } else return; level++; DispJP(p->child); level--; DispJP(p->next); } /////////////////////////////////////////////////////////////////////////// /*在家谱中添加新成员,并追加到文件中*/ int Equal(char const *p,char const q[])//判断两个字符串是否相等 { while(*p++ == *q++)if(*p == '\\0' && *q == '\\0')return (1); return (0); } JPNode *Find_Name(JPNode *s, char *parent)//定位家谱中的成员。返回其指针(地址) { static JPNode *here = NULL; if(s == NULL)return here; if(Equal(s->Name,parent) == 1)return (here=s); here = Find_Name(s->child,parent); here = Find_Name(s->next,parent); return here; } void Print_FILE(JPNode *p,FILE *fp) { static int level=0; int i; if(p != NULL) { for(i=0;i } else return; level++; Print_FILE(p->child,fp); level--; Print_FILE(p->next,fp); } void ADD_number(JPNode *p) { //在家谱中添加新成员,并写入文件 char parent[NAME_length],name[NAME_length]; FILE *fp = NULL; JPNode *here = NULL; JPNode *s = (JPNode *)malloc( 2*sizeof(void *) + strlen(name) + 1 ); s->next = s->child = NULL; printf(\"请输入要添加的新成员的双亲姓名:\"); scanf(\"%s\ printf(\"请输入要添加的新成员的姓名:\"); scanf(\"%s\ strcpy(s->Name,name); here = Find_Name(p,parent); if(here->child == NULL)here->child = s; else { here = here->child; while(here->next != NULL)here = here->next; here->next = s; } fp = fopen(\"jiapu_data.txt\ Print_FILE(p,fp); fclose(fp); } ////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////// /*输出指定家庭的所有成员*/ void Dis_Family(JPNode *p) { char name[NAME_length]; JPNode *here = NULL; printf(\"请输入该家庭的首个成员:\"); scanf(\"%s\ here = Find_Name(p,name); if(here == NULL){ printf(\"无该家庭!\\n\"); return;} printf(\"\\n\"); DispJP(here); } /////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////// /*确定指定成员在家族中的辈份*/ int beifen(JPNode *p, char name[]) { static int n = 1; static int level = 0; if(p == NULL )return level; if(Equal(p->Name,name) == 1)return (level=n); n++; beifen(p->child,name); n--; beifen(p->next,name); //向右查询n不必加(先加后减)! return level; } void Bei_Fen(JPNode *p) { char name[NAME_length]; int n=0; printf(\"请输入要查明辈分的人的姓名:\"); scanf(\"%s\ n = beifen(p,name); if(n == 0)printf(\"该家族中无此人!\\n\"); else printf(\"\\n %s 是 %s 家族中的第%d辈 \\n\ } ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// /*输出指定辈的所有成员*/ void chabei(JPNode *p, int bei) { static int n = 1; static int tag = 0; if(p == NULL )return; if(bei == n){tag = 1;printf(\"%s \ n++; chabei(p->child,bei); n--; chabei(p->next,bei); //向右查询n不必加(先加后减)! if(tag == 0)printf(\"该家族中还没有这一辈呢....\\n\"); } void Disp_Pei(JPNode *p) { int bei; printf(\"\\n你想要查看那一辈的成员:\"); scanf(\"%d\ printf(\"\\n....该家族中辈分为%d的成员有....\\n\\n\ chabei(p,bei); printf(\"\\n\"); } ///////////////////////////////////////////////////////////////// void menu(void); int main(void) { JPNode *JP = NULL; //家谱无结点 char ch='1',cc; CreatJP(&JP); while(ch) { system(\"cls\"); menu(); printf(\"\\n...请选择:\"); scanf(\"%c\ //ch=getchar(); switch(ch) { case '1':ADD_number(JP);break; case '2':Dis_Family(JP);break; case '3':Bei_Fen(JP); break; case '4':Disp_Pei(JP); break; default:ch='\\0'; break; } getche();while( (cc=getchar()) != '\\n'); } return 0; } void menu(void) { printf(\"\\n ****************家谱操作菜单****************\\n\"); printf(\"\\ * (1) 在家谱中添加新成员,并追加到文件中。 *\\n\\ * (2) 输出指定家庭的所有成员。 *\\n\\ * (3) 确定指定成员在家族中的辈份(第几代)。 *\\n\\ * (4) 输出指定辈的所有成员。 *\\n\\ * (0) 退出操作! *\\n\\ ********************************************\\n\"); } 实验结果截图: 2010/6/20 因篇幅问题不能全部显示,请点此查看更多更全内容