段程序如何解决?
程序代码:
#include <stdio.h> /*标准io库 */ #include <stdlib.h> /*定义杂项函数及内存分配函数的头文件 */ #include <string.h> /*字符串处理函数的头文件 */ #include <malloc.h> /*动态存储分配函数头文件 */ #define JUDEGNUM 3 /* 裁判数 */ #define NAMELEN 20 /* 姓名最大字符数 */ #define CODELEN 10 /* 号码最大字符数 */ #define FNAMELEN 80 /* 文件名最大字符数 */ #define BUFFSIZE 128 /* 缓冲区最大字符数 */ char judgement[JUDEGNUM][NAMELEN + 1] = { "judgementA", "judgementB", "judgementC" }; /*定义一个二维数组,用于存放裁判员的名字 */ /*定义一个结构体,用于存放运动员的比赛信息*/ struct AthleteScore { char name[NAMELEN + 1]; /* 姓名 */ char code[CODELEN + 1]; /* 学号 */ int score[JUDEGNUM]; /* 各裁判给的成绩 */ int total; /* 总成绩 */ }; /*定义一个链表,用于存放各个运动员的比赛信息*/ struct LinkNode { char name[NAMELEN + 1]; /* 姓名 */ char code[CODELEN + 1]; /* 号码 */ int score[JUDEGNUM]; /* 各裁判给的成绩 */ int total; /* 总成绩 */ struct LinkNode *next; } *head; /* 链表首指针 */ int total[JUDEGNUM]; /* 各裁判给的总成绩 */ FILE *filepoint; /* 文件指针 */ char filename[FNAMELEN]; /* 文件名 */ /* 从指定文件读入一个记录 */ int GetRecord(FILE * fpt, struct AthleteScore *sturecord) { char buf[BUFFSIZE]; /*声明一个字符数组当作缓冲区,用于缓存读入的记录 */ int i; /*声明一个整型变量 */ if (fscanf(fpt, "%s", buf) != 1) /*判断把文件读入缓冲区的字符情况,如果读入的字符串长度不等于1,表示结 束; 如果等于1,则读入一条记录 */ return 0; /* 文件结束 */ strncpy(sturecord->name, buf, NAMELEN); /*把缓冲区的前20个字符复制给sturecord指向的结构体的姓名 */ fscanf(fpt, "%s", buf); /*将文件中的内容继续读入到缓冲区中 */ strncpy(sturecord->code, buf, CODELEN); /*把缓冲区中的10个字符复制给sturecord指向的结构体的学号 */ for (i = 0; i < JUDEGNUM; i++) fscanf(fpt, "%d", &sturecord->score[i]); /*将文件中各个裁判给的成绩存放在一个数组中 */ for (sturecord->total = 0, i = 0; i < JUDEGNUM; i++) /*计算总成绩 */ sturecord->total += sturecord->score[i]; return 1; } /* 对指定文件写入一个记录 */ void PutRecord(FILE * fpt, struct AthleteScore *sturecord) { int i; /*声明一个整型变量 */ fprintf(fpt, "%s\n", sturecord->name); /*把sturecord指向的结构体的姓名输出到指定文件 */ fprintf(fpt, "%s\n", sturecord->code); /*把sturecord指向的结构体的学号输出到指定文件 */ for (i = 0; i < JUDEGNUM; i++) /*把各个裁判所给的成绩输出到指定文件中 */ fprintf(fpt, "%d\n", sturecord->score[i]); return; } /* 显示运动员记录 */ void ShowAthleteRecord(struct AthleteScore *rpt) { int i; /*声明一个整型变量 */ printf("\nName : %s\n", rpt->name); /*打印出运动员的姓名 */ printf("Code : %s\n", rpt->code); /*打印出运动员的学号 */ printf("score :\n"); /*打印出运动员的各裁判员所给的成绩 */ for (i = 0; i < JUDEGNUM; i++) printf(" %-15s : %4d\n", judgement[i], rpt->score[i]); printf("Total : %4d\n", rpt->total); /*打印出总成绩 */ } /* 列表显示运动员成绩 */ void Listathleteinfo(char *fname) { FILE *fp; /*声明一个文件指针 */ struct AthleteScore s; /*声明一个AthleteScore结构体 */ system("clear"); /*清屏 */ if ((fp = fopen(fname, "r")) == NULL) { /*只读打开文件,判断所读文件是否为空,如果不为空,显示运动员成绩 */ printf("Can't open file %s.\n", fname); /*文件若为空,则输出所读的文件不能打开 */ return; /*返回 */ } while (GetRecord(fp, &s) != 0) { /*当所取的记录不为0,显示从 指定文件中读入的记录 */ ShowAthleteRecord(&s); /*调用显示运动员记录的函数 */ } fclose(fp); /*关闭文件 */ return; /*返回 */ } /* 构造链表 */ struct LinkNode *CreatLinklist(char *fname) { FILE *fp; /*声明一个文件指针 */ struct AthleteScore s; /*声明一个运动员得分的结构体 */ struct LinkNode *p, *u, *v, *h; /*声明链表结点 */ int i; /*声明一个整型变量 */ if ((fp = fopen(fname, "r")) == NULL) { /*只读打开文件,判断所读文件是否为空,如果不为空,则构造链表 */ printf("Can't open file %s.\n", fname); /*文件若为空,则输出所读的文件不能打开 */ return NULL; /*返回空 */ } h = NULL; /*定义一个变量,并赋值为空 */ p = (struct LinkNode *)malloc(sizeof(struct LinkNode)); /*函数malloc分配一个类型为LikeNode的结点变量的空间, 并将其首地址放入指针变量p中 */ while (GetRecord(fp, (struct AthleteScore *)p) != 0) { /*指定文件写入的记录不为0时, */ v = h; /*将h赋值给v */ while (v && p->total <= v->total) { /*v为真并且p指向的总成绩小于等于v指向的总成绩 */ u = v; /*将v赋值给u */ v = v->next; /*v指向下一个结点 */ } if (v == h) /*判断v是否等于h */ h = p; /*如果v等于h,则将p赋值给h */ else u->next = p; /*如果v不等于h,则让u的下一个结点指向p */ p->next = v; /*p的下一个结点指向v */ p = (struct LinkNode *)malloc(sizeof(struct LinkNode)); /*函数malloc分配一个类型为LikeNode的结点变量的空间, 并将其首地址放入指针变量p中 */ } free(p); /*释放p指向的空间 */ fclose(fp); /*关闭文件 */ return h; /*返回h */ } /* 顺序显示链表各表元 */ void OutputLinklist(struct LinkNode *h) { system("clear"); /*清屏 */ while (h != NULL) { /*判断h指向的链表是否为空 */ ShowAthleteRecord((struct AthleteScore *)h); /*如果链表不为空,则调用函数 ShowAthleteRecord()来显示运动员记录 */ printf("\n"); /*换行 */ while (getchar() != '\n') ; /*当输入的字符不为换行时,h指向下一个结点 */ h = h->next; } return; /*返回 */ } /* 按运动员姓名查找记录 */ int SearchbyName(char *fname, char *key) { FILE *fp; /*声明一个文件指针 */ int c; /*声明一个整型变量 */ struct AthleteScore s; /*声明一个指向运动员得分的结构体 */ system("clear"); /*清屏 */ if ((fp = fopen(fname, "r")) == NULL) { /*只读打开文件,判断所读文件是否为空 */ printf("Can't open file %s.\n", fname); /*文件若为空,则输出所读的文件不能打开 */ return 0; /*返回 */ } c = 0; /*如果文件不为空,把c赋值为0 */ while (GetRecord(fp, &s) != 0) { /*当从指定文件写入的记录不为0时,则显示 */ if (strcmp(s.name, key) == 0) { /*让写入的记录的运动员的姓名与输入的运动员姓名进行比较 */ ShowAthleteRecord(&s); /*若相等,则显示运动员的记录 */ c++; /*c递增 */ } } fclose(fp); /*关闭文件 */ if (c == 0) /*判断c是否为0 */ printf("The athlete %s is not in the file %s.\n", key, fname); /*输出文件中不存在所输入姓名的运动员的记录 */ return 1; /*返回 */ } /* 按运动员号码查找记录 */ int SearchbyCode(char *fname, char *key) { FILE *fp; /*声明一个文件指针 */ int c; /*声明一个整型变量 */ struct AthleteScore s; /*声明一个指向运动员得分的结构体 */ system("clear"); /*清屏 */ if ((fp = fopen(fname, "r")) == NULL) { /*只读打开文件,判断所读文件是否为空 */ printf("Can't open file %s.\n", fname); /*文件若为空,则输出所读的文件不能打开 */ return 0; /*返回 */ } c = 0; /*如果文件不为空,把c赋值为0 */ while (GetRecord(fp, &s) != 0) { /*当从指定文件写入的记录不为0时,则显示 */ if (strcmp(s.code, key) == 0) { /*让写入的记录的运动员的学号与输入的运动员学号进行比较 */ ShowAthleteRecord(&s); /*若相等,则显示运动员的记录 */ c++; /*c递增 */ break; /*完成本次循环,跳出循环 */ } } fclose(fp); /*关闭文件 */ if (c == 0) /*判断c是否为0 */ printf("The athlete %s is not in the file %s.\n", key, fname); /*输出文件中不存在所输入姓名的运动员的记录 */ return 1; /*返回 */ } /*向文件中输入运动员记录*/ void InsertRecord() { FILE *fp; /*声明一个文件指针 */ char c, i, j, n; /*声明字符变量 */ struct AthleteScore s; /*声明一个指向运动员得分的结构体 */ system("clear"); /*清屏 */ printf("请输入运动员得分记录的文件名: \n"); /*输出字符串 */ scanf("%s", filename); /*输入文件名 */ if ((fp = fopen(filename, "r")) == NULL) { /*只读打开文件,判断所读文件是否为空 */ printf("The file %s doesn't exit.\ndo you want to creat it? (Y/N) ", filename); /*如果为空,则输出文件不存在,并询问是否要从新输入 */ getchar(); /*读入字符 */ c = getchar(); /*将读入的字符赋值给c */ if (c == 'Y' || c == 'y') { /*判断c是否等于Y或者是y */ fp = fopen(filename, "w"); /*如果相等,打开只写文件,若文件存在则文件长度清为0, 即该文件内容会消失。若文件不存在则建立该文件。 */ printf("请输入记录号 : "); /*输出 */ scanf("%d", &n); /*输入记录号 */ for (i = 0; i < n; i++) { /*做循环,输入运动员的记录 */ printf("请输入运动员的姓名: "); /*输出字符串 */ scanf("%s", &s.name); /*输入运动员的姓名 */ printf("请输入运动员的学号: "); /*输出字符串 */ scanf("%s", &s.code); /*输入运动员的学号 */ for (j = 0; j < JUDEGNUM; j++) { /*做循环,输入各个裁判的所打的分数 */ printf("请输入 %s 的分数: ", judgement[j]); /*输出字符串 */ scanf("%d", &s.score[j]); /*输入分数 */ } PutRecord(fp, &s); /*调用函数,对指定文件写入记录 */ } fclose(fp); /*关闭文件 */ } } fclose(fp); /*关闭文件 */ return; /*返回 */ } int main() { /*主函数 */ int i, j, n; /*声明整型变量 */ char c; /*声明字符变量 */ char buf[BUFFSIZE]; /*定义字符数组作为缓冲区 */ while (1) { system("clear"); /*清屏 */ printf("********************************************\n"); /*输出字符串 */ printf("*** 选择项 ****\n"); printf("*** 1:向文件插入一条记录. ****\n"); printf("*** 2:按运动员的姓名寻找记录. ****\n"); printf("*** 3:按运动员的号码寻找记录 . ****\n"); printf("*** 4:列出所有运动员记录. ****\n"); printf("*** 5:按总分从高到低排列显示. ****\n"); printf("*** 6:退出. ****\n"); printf("********************************************\n"); printf("请输入一个选择项的标号:\n"); scanf("%c", &c); /* 输入选择命令 */ switch (c) { /*做分支选择,对相应的输入号做相应的选择 */ case '1': InsertRecord(); /*调用 InsertRecord(),向文件输入运动员的记录 */ getchar(); /*读入字符 */ break; case '2': /* 按运动员的姓名寻找记录 */ printf("请输入所要查询的运动员的姓名:\n"); /*输出字符串 */ scanf("%s", buf); /*输入字符串并存放在缓冲区中 */ SearchbyName(filename, buf); /*调用SearchbyName(), 按运动员的姓名寻找记录 */ getchar(); /*读入字符 */ break; case '3': /* 按运动员的学号寻找记录 */ printf("请输入所要查询的运动员的号码:\n"); /*输出字符串 */ scanf("%s", buf); /*输入字符串并存放在缓冲区中 */ SearchbyCode(filename, buf); /*调用SearchbyName(), 按运动员的学号寻找记录 */ getchar(); /*读入字符 */ break; case '4': /* 列出所有运动员记录 */ Listathleteinfo(filename); /*调用Listathleteinfo(), 列出所有运动员记录 */ getchar(); break; case '5': /* 按总分从高到低排列显示 */ if ((head = CreatLinklist(filename)) != NULL) /*判断构造的链表是否为空 */ OutputLinklist(head); /*若不为空,则调用OutputLinklist(),按总分从高到低排列显示 */ getchar(); break; case '6': return 1; /*返回 */ default: break; } } return 1; /*返回 */ }