1、/*11.3.2 源程序*/*xuesheng.c*/*头文件( .h)*/#include “stdio.h“ /*I/O 函数*/#include “stdlib.h“ /*其它说明*/#include “string.h“ /*字符串函数*/#include “mem.h“ /*内存操作函数*/#include “ctype.h“ /*字符操作函数*/#include “alloc.h“ /*动态地址分配函数*/#define N 3 /*定义常数*/typedef struct z1 /*定义数据结构*/char no11;char name15;int scoreN;float su
2、m;float average;int order;struct z1 *next;STUDENT;/*以下是函数原型*/STUDENT *init(); /*初始化函数*/STUDENT *create(); /*创建链表*/STUDENT *delete(STUDENT *h); /*删除记录*/void print(STUDENT *h); /* 显示所有记录*/void search(STUDENT *h); /*查找*/void save(STUDENT *h); /*保存*/STUDENT *load(); /*读入记录*/void computer(STUDENT *h); /*
3、计算总分和均分 */STUDENT *insert(STUDENT *h); /*插入记录*/void append(); /*追加记录*/void copy(); /*复制文件*/STUDENT *sort(STUDENT *h); /*排序*/STUDENT *index(STUDENT *h); /*索引*/void total(STUDENT *h); /*分类合计 */int menu_select(); /*菜单函数*/*主函数开始 */main()int i;STUDENT *head; /*链表定义头指针*/clrscr(); /*清屏*/for(;) /*无限循环*/swit
4、ch(menu_select() /*调用主菜单函数,返回值整数作开关语句的条件*/ /*值不同,执行的函数不同,break 不能省略*/case 0:head=init();break; /*执行初始化 */case 1:head=create();break; /*创建链表*/case 2:head=delete(head);break; /*删除记录*/case 3:print(head);break; /*显示全部记录*/case 4:search(head);break; /*查找记录*/case 5:save(head);break; /*保存文件*/case 6:head=loa
5、d(); break; /*读文件*/case 7:computer(head);break; /*计算总分和均分*/case 8:head=insert(head); break; /*插入记录*/case 9:copy();break; /*复制文件*/case 10:head=sort(head);break; /*排序*/case 11:append();break; /*追加记录*/case 12:head=index(head);break; /*索引*/case 13:total(head);break; /*分类合计*/case 14:exit(0); /*如菜单返回值为 14
6、 程序结束*/*菜单函数,返回值为整数*/menu_select()char *menu=“*MENU*“, /*定义菜单字符串数组*/“ 0. init list“, /*初始化*/“ 1. Enter list“, /*输入记录*/“ 2. Delete a record from list“, /*从表中删除记录*/“ 3. print list “, /*显示单链表中所有记录*/“ 4. Search record on name“, /*按照姓名查找记录*/“ 5. Save the file“, /*将单链表中记录保存到文件中*/“ 6. Load the file“, /*从文件
7、中读入记录 */“ 7. compute the score“, /*计算所有学生的总分和均分 */“ 8. insert record to list “, /*插入记录到表中*/“ 9. copy the file to new file“, /*复制文件*/“ 10. sort to make new file“, /*排序*/“ 11. append record to file“, /*追加记录到文件中*/“ 12. index on nomber“, /*索引*/“ 13. total on nomber“, /*分类合计 */“ 14. Quit“; /*退出*/char s3;
8、 /*以字符形式保存选择号*/int c,i; /*定义整形变量 */gotoxy(1,25); /*移动光标*/printf(“press any key enter menun“); /*压任一键进入主菜单*/getch(); /*输入任一键*/clrscr(); /*清屏幕*/gotoxy(1,1); /*移动光标*/textcolor(YELLOW); /*设置文本显示颜色为黄色*/textbackground(BLUE); /*设置背景颜色为蓝色 */gotoxy(10,2); /*移动光标*/putch(0xc9); /*输出左上角边框*/for(i=1;i14); /*选择项不在
9、 014 之间重输*/return c; /*返回选择项,主程序根据该数调用相应的函数*/STUDENT *init()return NULL;/*创建链表*/STUDENT *create()int i; int s;STUDENT *h=NULL,*info; /* STUDENT 指向结构体的指针*/for(;)info=(STUDENT *)malloc(sizeof(STUDENT); /*申请空间*/if(!info) /*如果指针 info 为空*/printf(“nout of memory“); /*输出内存溢出*/inputs(“enter no:“,info-no,11)
10、; /*输入学号并校验*/if(info-no0=) break; /*如果学号首字符为则结束输入*/inputs(“enter name:“,info-name,15); /*输入姓名,并进行校验*/printf(“please input %d score n“,N); /*提示开始输入成绩*/s=0; /*计算每个学生的总分,初值为 0*/for(i=0;iscorei); /*输入成绩*/if(info-scorei100|info-scoreiscorei100|info-scoreiscorei; /*累加各门课程成绩*/info-average=(float)s/N; /*求出平
11、均值 */info-order=0; /*未排序前此值为 0*/info-next=h; /*将头结点做为新输入结点的后继结点*/h=info; /*新输入结点为新的头结点*/*输入字符串,并进行长度验证*/inputs(char *prompt, char *s, int count)char p255;doprintf(prompt); /*显示提示信息*/scanf(“%s“,p); /*输入字符串*/if(strlen(p)count)printf(“n too long! n“); /*进行长度校验,超过 count 值重输入*/while(strlen(p)count);strcp
12、y(s,p); /*将输入的字符串拷贝到字符串 s 中*/*输出链表中结点信息*/void print(STUDENT *h)int i=0; /* 统计记录条数*/STUDENT *p; /*移动指针*/clrscr(); /*清屏*/p=h; /*初值为头指针*/printf(“nnn*STUDENT*n“);printf(“|rec|nO | name | sc1| sc2| sc3| sum | ave |order|n“);printf(“|-|-|-|-|-|-|-|-|-|n“);while(p!=NULL)i+;printf(“|%3d |%-10s|%-15s|%4d|%4d
13、|%4d| %4.2f | %4.2f | %3d |n“, i, p-no,p-name,p-score0,p-score1,p-score2,p-sum,p-average,p-order);p=p-next;printf(“*end*n“);/*删除记录*/STUDENT *delete(STUDENT *h)STUDENT *p,*q; /*p 为查找到要删除的结点指针,q 为其前驱指针*/char s11; /*存放学号*/clrscr(); /*清屏*/printf(“please deleted non“); /*显示提示信息 */scanf(“%s“,s); /*输入要删除记录
14、的学号 */q=p=h; /*给 q 和 p 赋初值头指针*/while(strcmp(p-no,s) /*将 p 指针值赋给 q 作为 p 的前驱指针*/if(p=NULL) /*如果 p 为空,说明链表中没有该结点*/printf(“nlist no %s studentn“,s);else /*p 不为空,显示找到的记录信息*/printf(“*have found*n“);printf(“|no | name | sc1| sc2| sc3| sum | ave |order|n“);printf(“|-|-|-|-|-|-|-|-|n“);printf(“|%-10s|%-15s|%
15、4d|%4d|%4d| %4.2f | %4.2f | %3d |n“, p-no,p-name,p-score0,p-score1,p-score2,p-sum,p-average,);printf(“*end*n“);getch(); /*压任一键后,开始删除*/if(p=h) /*如果 p=h,说明被删结点是头结点*/h=p-next; /*修改头指针指向下一条记录*/elseq-next=p-next; /*不是头指针,将 p 的后继结点作为 q 的后继结点*/free(p); /*释放 p 所指结点空间*/printf(“n have deleted No %s studentn“,
16、s);printf(“Dont forget saven“);/*提示删除后不要忘记保存文件*/return(h); /*返回头指针*/*查找记录*/void search(STUDENT *h)STUDENT *p; /* 移动指针*/char s15; /*存放姓名的字符数组*/clrscr(); /*清屏幕*/printf(“please enter name for searchn“);scanf(“%s“,s); /*输入姓名*/p=h; /*将头指针赋给 p*/while(strcmp(p-name,s) /*显示没有该学生*/else /*显示找到的记录信息*/printf(“n
17、n*havefound*n“);printf(“|nO | name | sc1| sc2| sc3| sum | ave |order|n“);printf(“|-|-|-|-|-|-|-|-|n“);printf(“|%-10s|%-15s|%4d|%4d|%4d| %4.2f | %4.2f | %3d |n“, p-no,p-name,p-score0,p-score1,p-score2,p-sum,p-average,p-order);printf(“*end*n“);/*插入记录*/STUDENT *insert(STUDENT *h)STUDENT *p,*q,*info; /*
18、p 指向插入位置,q 是其前驱,info 指新插入记录*/char s11; /*保存插入点位置的学号*/int s1,i;printf(“please enter location before the non“);scanf(“%s“,s); /*输入插入点学号*/printf(“nplease new recordn“); /*提示输入记录信息*/info=(STUDENT *)malloc(sizeof(STUDENT); /*申请空间*/if(!info)printf(“nout of memory“); /*如没有申请到,内存溢出*/inputs(“enter no:“,info-
19、no,11); /*输入学号 */inputs(“enter name:“,info-name,15); /*输入姓名*/printf(“please input %d score n“,N); /*提示输入分数*/s1=0; /*保存新记录的总分,初值为 0*/for(i=0;iscorei);if(info-scorei100|info-scoreiscorei100|info-scoreiscorei; /*计算总分*/info-sum=s1; /*将总分存入新记录中*/info-average=(float)s1/N; /*计算均分*/info-order=0; /*名次赋值 0*/i
20、nfo-next=NULL; /*设后继指针为空*/p=h; /*将指针赋值给 p*/q=h; /*将指针赋值给 q*/while(strcmp(p-no,s) /*保存指针 p,作为下一个 p 的前驱*/if(p=NULL) /*如果 p 指针为空,说明没有指定结点*/if(p=h) /*同时 p 等于 h,说明链表为空 */h=info; /*新记录则为头结点*/elseq-next=info; /*p 为空,但 p 不等于 h,将新结点插在表尾 */elseif(p=h) /*p 不为空,则找到了指定结点*/info-next=p; /*如果 p 等于 h,则新结点插入在第一个结点之前*
21、/h=info; /*新结点为新的头结点*/elseinfo-next=p; /*不是头结点,则是中间某个位置,新结点的后继为 p*/q-next=info; /*新结点作为 q 的后继结点 */printf(“n -have inserted %s student-n“,info-name); printf(“-Dont forget save-n“); /*提示存盘*/return(h); /*返回头指针*/*保存数据到文件*/void save(STUDENT *h)STUDENT *p; /* 定义移动指针*/char outfile10; /*保存输出文件名*/printf(“Ent
22、er outfile name,for example c:f1te.txt:n“); /*提示文件名格式信息*/scanf(“%s“,outfile);if(fp=fopen(outfile,“wb“)=NULL) /*为输出打开一个二进制文件,如没有则建立*/printf(“can not open filen“);exit(1);printf(“nSaving filen“); /*打开文件,提示正在保存*/p=h; /*移动指针从头指针开始*/while(p!=NULL) /*如 p 不为空*/fwrite(p,sizeof(STUDENT),1,fp);/*写入一条记录*/fclos
23、e(fp); /*关闭文件*/printf(“-save success!-n“); /*显示保存成功*/* 从文件读数据*/STUDENT *load()STUDENT *p,*q,*h=NULL; /*定义记录指针变量 */FILE *fp; /* 定义指向文件的指针*/char infile10; /*保存文件名*/printf(“Enter infile name,for example c:f1te.txt:n“); scanf(“%s“,infile); /*输入文件名 */if(fp=fopen(infile,“rb“)=NULL) /*打开一个二进制文件,为读方式*/print
24、f(“can not open filen“); /*如不能打开,则结束程序*/exit(1);printf(“n -Loading file!-n“);if(!p)printf(“out of memory!n“); /*如没有申请到,则内存溢出*/return h; /*返回空头指针*/h=p; /*申请到空间,将其作为头指针*/while(!feof(fp) /*循环读数据直到文件尾结束*/if(1!=fread(p,sizeof(STUDENT),1,fp)break; /*如果没读到数据,跳出循环*/p-next=(STUDENT *)malloc(sizeof(STUDENT);
25、/*为下一个结点申请空间*/if(!p-next)printf(“out of memory!n“); /*如没有申请到,则内存溢出 */return h;p=p-next; /*指针后移,新读入数据链到当前表尾*/q-next=NULL; /*最后一个结点的后继指针为空 */fclose(fp); /*关闭文件*/printf(“-You have success read data from file!-n“);return h; /*返回头指针*/*追加记录到文件*/void append()FILE *fp; /*定义指向文件的指针*/STUDENT *info; /*新记录指针*/i
26、nt s1,i;char infile10; /*保存文件名*/printf(“nplease new recordn“);info=(STUDENT *)malloc(sizeof(STUDENT); /*申请空间*/if(!info)printf(“nout of memory“); /*没有申请到,内存溢出本函数结束*/return ;inputs(“enter no:“,info-no,11); /*调用 inputs 输入学号*/inputs(“enter name:“,info-name,15); /*调用 inputs 输入姓名*/printf(“please input %d
27、score n“,N); /*提示输入成绩*/s1=0;for(i=0;iscorei); /*输入成绩*/if(info-scorei100|info-scoreiscorei100|info-scoreiscorei; /*求总分*/info-sum=s1; /*保存总分*/info-average=(float)s1/N; /*求均分*/info-order=0; /*名次初始值为 0*/info-next=NULL; /*将新记录后继指针赋值为空*/printf(“Enter infile name,for example c:f1te.txt:n“); scanf(“%s“,infi
28、le); /*输入文件名*/if(fp=fopen(infile,“ab“)=NULL) /*向二进制文件尾增加数据方式打开文件*/printf(“can not open filen“); /*显示不能打开*/exit(1); /*退出程序*/printf(“n -Appending record!-n“);if(1!=fwrite(info,sizeof(STUDENT),1,fp) /*写文件操作*/printf(“-file write error!-n“);return; /*返回*/printf(“-append sucess!-n“);fclose(fp); /*关闭文件*/*文
29、件拷贝*/void copy()char outfile10,infile10;FILE *sfp,*tfp; /*源和目标文件指针 */STUDENT *p=NULL; /*移动指针*/clrscr(); /*清屏*/printf(“Enter infile name,for example c:f1te.txt:n“);scanf(“%s“,infile); /*输入源文件名 */if(sfp=fopen(infile,“rb“)=NULL) /*二进制读方式打开源文件*/printf(“can not open input filen“);exit(0);printf(“Enter ou
30、tfile name,for example c:f1te.txt:n“); /*提示输入目标文件名*/scanf(“%s“,outfile); /*输入目标文件名*/if(tfp=fopen(outfile,“wb“)=NULL) /*二进制写方式打开目标文件*/printf(“can not open output file n“);exit(0);while(!feof(sfp) /*读文件直到文件尾*/if(1!=fread(p,sizeof(STUDENT),1,sfp)break; /*块读*/fwrite(p,sizeof(STUDENT),1,tfp); /*块写*/fclos
31、e(sfp); /*关闭源文件*/fclose(tfp); /*关闭目标文件*/printf(“you have success copy file!n“); /*显示成功拷贝*/*排序*/STUDENT *sort(STUDENT *h)int i=0; /*保存名次*/STUDENT *p,*q,*t,*h1; /*定义临时指针*/h1=h-next; /*将原表的头指针所指的下一个结点作头指针*/h-next=NULL; /*第一个结点为新表的头结点 */while(h1!=NULL) /*当原表不为空时,进行排序*/t=h1; /*取原表的头结点*/h1=h1-next; /*原表头结
32、点指针后移 */p=h; /*设定移动指针 p,从头指针开始*/q=h; /*设定移动指针 q 做为 p 的前驱,初值为头指针*/while(t-sumsum /*待排序点值小,则新表指针后移*/p=p-next;if(p=q) /*p=q,说明待排序点值大,应排在首位*/t-next=p; /*待排序点的后继为 p*/h=t; /*新头结点为待排序点 */else /*待排序点应插入在中间某个位置 q 和 p 之间,如p 为空则是尾部*/t-next=p; /*t 的后继是 p*/q-next=t; /*q 的后继是 t*/p=h; /*已排好序的头指针赋给 p,准备填写名次*/while(
33、p!=NULL) /*当 p 不为空时,进行下列操作*/i+; /*结点序号*/p-order=i; /*将名次赋值*/p=p-next; /*指针后移*/printf(“sort sucess!n“); /*排序成功*/return h; /*返回头指针*/*计算总分和均值*/void computer(STUDENT *h)STUDENT *p; /*定义移动指针*/int i=0; /*保存记录条数初值为 0*/long s=0; /*总分初值为 0*/float average=0; /*均分初值为 0*/p=h; /*从头指针开始*/while(p!=NULL) /*当 p 不为空时
34、处理*/s+=p-sum; /*累加总分*/i+; /*统计记录条数*/p=p-next; /*指针后移*/average=(float)s/i;/* 求均分,均分为浮点数,总分为整数,所以做类型转换*/printf(“n-All students sum score is:%ld average is %5.2fn“,s,average);/*索引*/STUDENT *index(STUDENT *h)STUDENT *p,*q,*t,*h1; /*定义临时指针*/h1=h-next; /*将原表的头指针所指的下一个结点作头指针*/h-next=NULL; /*第一个结点为新表的头结点 */
35、while(h1!=NULL) /*当原表不为空时,进行排序*/t=h1; /*取原表的头结点*/h1=h1-next; /*原表头结点指针后移 */p=h; /*设定移动指针 p,从头指针开始*/q=h; /*设定移动指针 q 做为 p 的前驱,初值为头指针*/while(strcmp(t-no,p-no)0 /*待排序点值大,应往后插,所以新表指针后移*/p=p-next;if(p=q) /*p=q,说明待排序点值小,应排在首位*/t-next=p; /*待排序点的后继为 p*/h=t; /*新头结点为待排序点 */else /*待排序点应插入在中间某个位置 q 和 p 之间,如p 为空则是尾部*/t-next=p; /*t 的后继是 p*/q-next=t; /*q 的后继是 t*/printf(“index sucess!n“); /*索引排序成功*/return h; /*返回头指针*/*分类合计*/void total(STUDENT *h)STUDENT *p,*q; /*定义临时指针变量*/char sno9,qno9,*ptr; /*保存班级号的*/float s1,ave; /*保存总分和均分*/int i; /*保存班级人数*/