1,数据类型的定义。
定义所需变量。成绩,姓名,年龄,等等
2.为结构体类型定制的基本操作。
/* ①文件的完整内容 */
#ifndef _STUDENT /*条件编译,防止重复包含的错误*/
#define _STUDENT
#define NUM 20 /*定义学生人数常量,根据实际需要修改值*/
struct Student /*学生记录所属结构体类型的定义*/
{
long num; /*学号*/
char name[20]; /*姓名*/
char sex[10]; /*性别*/
int score[3]; /*3门课成绩*/
int total; /*总分*/
int rank; /*名次*/
};
typedef struct Student Student; /*定义类型的别名Student*/
#define sizeStu sizeof(Student) /*一个学生记录所需要的内存空间大小*/
int readStu(Student *stu,int n); /*读入学生记录,学号为0或读满停止*/
void printStu(Student *stu , int n); /*屏幕输出所有学生记录的值*/
int equal(Student s1,Student s2,int condition); /*根据condition判断s1与s2相等否*/
int larger(Student s1,Student s2,int condition);/*根据condition比较s1与s2的大小*/
void reverse(Student *stu,int n); /*学生记录数组元素逆置*/
void calcuTotal(Student *stu,int n) ; /*计算所有学生的总分*/
void calcuRank(Student *stu,int n) ; /*根据总分计算学生的名次允许并列*/
void calcuMark(double m[3][3],Student *stu,int n); /*求3门课的最高最低平均分*/
void sortStu(Student *stu,int n,int condition); /*根据条件用选择法从小到大排序*/
int searchStu(Student *stu,int n,Student s,int condition,int *f) ; /*根据条件查找数组*/
/*中与s相等的各元素,每一个与s相等元素的下标置于f数组中*/
int insertStu(Student *stu,int n,Student s); /*向数组中插入一个元素按学号有序*/
int deleteStu(Student *stu,int n,Student s) ; /*从数组中删除一个指定学号的元素*/
#endif
/*②文件的完整内容*/
#include ""
#include <>
#include <>
/*函数功能:从键盘读入学生的初始数据值
函数参数: 两个形式参数分别为结构体指针和预设记录条数
函数返回值:从键盘上实际读入的记录条数
*/
int readStu(Student *stu ,int n)
{ int i,j;
for (i=0;i<n;i++)
{ printf("Input one student\'s information\n");
printf("num: ");
scanf("%ld", &stu[i].num);
if (stu[i].num==0) break;
printf("name: ");
scanf("%s",stu[i].name);
printf("sex: ");
scanf("%s",stu[i].sex);
stu[i].total=0; /*总分需要计算求得,初值置为0*/
printf("Input three courses of the student:\n");
for (j=0;j<3;j++)
scanf("%d",&stu[i].score[j]);
stu[i].rank=0; /*名次要根据总分计算,初值置为0*/
}
return i; /*返回实际读入的记录条数*/
}
/*函数功能:输出所有学生记录的值
函数参数: 两个形式参数分别为结构体指针和记录条数
函数返回值:无返回值
*/
void printStu ( Student *stu , int n)
{
int i,j;
for (i=0;i<n;i++)
{
printf("%8ld ", stu[i].num);
printf("%8s", stu[i].name);
printf("%8s", stu[i].sex);
for (j=0;j<3;j++)
printf("%6d",stu[i].score[j]);
printf("%7d",stu[i].total);
printf("%5d\n",stu[i].rank);
}
}
/*函数功能:判断两个Student记录是否相等
函数参数: 3个形式参数分别为待比较的两个结构体变量、比较条件
函数返回值:比较的结果,相等返回1,不相等返回0
*/
int equal(Student s1,Student s2,int condition)
{
if (condition==1) /*如果参数condition的值为1,则比较学号*/
return ==;
else if (condition==2) /*如果参数condition的值为2,则比较姓名*/
{ if (strcmp(,)==0)
return 1;
else return 0;
}
else if (condition==3) /*如果参数condition的值为3,则比较名次*/
return ==;
else if (condition==4) /*如果参数condition的值为4,则比较总分*/
return ==;
else return 1; /*其余情况返回1*/
}
/*函数功能:比较两个Student记录的大小
函数参数: 3个形式参数分别为待比较的两个结构体变量、比较条件
函数返回值:比较的结果,第1个记录大于第2个则返回1,否则返回0
*/
int larger(Student s1,Student s2,int condition)
{
if (condition==1) /*若condition的值为1,则比较学号*/
return >;
else if (condition==2) /*若condition的值为2,则比较总分*/
return >;
else return 1; /*其余情况返回1*/
}
/*函数功能:数组的元素逆置
函数参数: 两个形式参数分别为结构体指针和记录条数
函数返回值:无返回值
*/
void reverse(Student *stu,int n)
{
int i;
Student temp;
for (i=0;i<n/2;i++) /*循环次数为元素数量的一半*/
{ temp=stu[i];
stu[i]=stu[n-1-i];
stu[n-1-i]=temp;
}
}
/*函数功能:计算所有学生的总分
函数参数: 两个形式参数分别为结构体指针和记录条数
函数返回值:无返回值
*/
void calcuTotal(Student *stu,int n)
{
int i,j;
for (i=0;i<n;i++) /*外层循环控制所有学生记录*/
{ stu[i].total =0;
for (j=0;j<3;j++) /*内层循环控制三门功课*/
stu[i].total +=stu[i].score[j];
}
}
/*函数功能:根据总分计算排名,同分同名次
函数参数: 两个形式参数分别为结构体指针和记录条数
函数返回值:无返回值
*/
void calcuRank(Student *stu,int n)
{
int i ;
sortStu(stu,n,2); /*调用sortStu算法按总分由小到大排序*/
reverse(stu,n); /*再逆置,则按总分由大到小排序了*/
stu[0].rank=1; /*第一条记录的名次一定是1*/
for (i=1;i<n;i++) /*从第二条记录一直到最后一条循环*/
{
if (equal(stu[i],stu[i-1],4)) /*当前记录与其前一条记录总分相等*/
stu[i].rank=stu[i-1].rank; /*当前记录名次等于其前一条记录名次*/
else
stu[i].rank=i+1; /*不相等时当前记录名次等于下标号+1*/
}
}
/*函数功能:求三门课最高、最低、平均分
函数参数: 第1个形式参数m第一维代表3门课,第二维代表最高、最低、平均分,第2个形参是结构体指针,第3个形参是记录条数
函数返回值:无返回值
*/
void calcuMark(double m[3][3],Student stu[],int n)
{
int i,j;
for (i=0;i<3;i++) /*求三门课的最高分*/
{
m[i][0]=stu[0].score[i];
for (j=1;j<n;j++)
if (m[i][0]<stu[j].score[i])
m[i][0]=stu[j].score[i];
}
for (i=0;i<3;i++) /*求三门课的最低分*/
{
m[i][1]=stu[0].score[i];
for (j=1;j<n;j++)
if (m[i][1]>stu[j].score[i])
m[i][1]=stu[j].score[i];
}
for (i=0;i<3;i++) /*求三门课的平均分*/
{
m[i][2]=stu[0].score[i];
for (j=1;j<n;j++)
m[i][2]+=stu[j].score[i];
m[i][2]/=n;
}
}
/*函数功能:按condition规定的条件由小到大排序
函数参数:3个形参分别是结构体指针、记录条数、排序依据的条件
函数返回值:无返回值
*/
void sortStu(Student *stu,int n,int condition)
{
int i,j,minpos; /*minpos存本趟最小元素所在的下标*/
Student t;
for (i=0;i<n-1;i++) /*控制循环的n-1趟*/
{
minpos=i;
for (j=i+1;j<n;j++) /*寻找本趟最小元素所在的下标*/
if (larger(stu[minpos],stu[j],condition))
minpos=j;
if (i!=minpos) /*保证本趟最小元素到达下标i的位置*/
{ t=stu[i];
stu[i]=stu[minpos];
stu[minpos]=t;
}
}
}
/*函数功能:按condition规定的条件查找指定记录是否存在
函数参数:5个形参分别是结构体指针、记录条数、待查找的记录、查找条件、查找到的多个元素对应下标所存放的数组f
函数返回值:查找到的记录条数
*/
int searchStu(Student *stu,int n,Student s,int condition,int *f[ ])
{
int i,j=0,find=0;
for (i=0;i<n;i++) /*待查找的元素为s*/
if (equal(stu[i],s,condition))
{
f[j++]=i; /*找到了将其下标放f数组中*/
find++; /*统计找到的元素个数*/
}
return find; /*返回find,值为0表示没找到*/
}
/*函数功能:向结构体数组中依学号递增插入一条记录
函数参数:3个形参分别是结构体指针、原来的记录条数、待插入的记录
函数返回值:插入后的实际记录条数
*/
int insertStu(Student *stu,int n,Student s)
{ int i;
sortStu(stu,n,1); /*先按学号排序*/
for (i=0;i<n;i++)
if (equal(stu[i],s,1)) /*学号相同不能插入,保证唯一*/
{ printf("this record exist,can not insert again!\n");
return n;
}
for (i=n-1;i>=0;i--) /*按学号从小到大有序*/
{
if (!larger(stu[i],s,1)) /*若s大于当前元素则退出循环*/
break;
stu[i+1]=stu[i]; /*否则元素stu[i]后移一个位置*/
}
stu[i+1]=s; /*在下标i+1处插入元素s*/
n++; /*元素个数增加1*/
return n; /*返回现有元素个数*/
}
/*函数功能:从结构体数组中删除指定学号的一条记录
函数参数:3个形参分别是结构体指针、原来的记录条数、待删除的记录
函数返回值:删除后的实际记录条数
*/
int deleteStu(Student *stu,int n,Student s)
{
int i,j;
for (i=0;i<n;i++) /*寻找待删除的元素*/
if (equal(stu[i],s,1)) break; /*若找到相等元素则退出循环*/
if (i==n) /*如果找不到待删除的元素*/
{ printf("This record does not exist!\n"); /*给出提示信息然后返回*/
return n;
}
for (j=i; j<n-1; j++) /*此处隐含条件为i<n且equal(stu[i],s,1)成立*/
stu[j]=stu[j+1]; /*通过覆盖删除下标为i的元素*/
n--; /*元素个数减少1*/
return n; /*返回现有元素个数*/
}
3.二进制文件实现数据的保存
/*③文件的内容如下:*/
#ifndef _FILE /*条件编译,防止重复包含的错误*/
#define _FILE
#include ""
int createFile(Student *stu); /*建立初始的数据文件*/
int readFile(Student *stu); /*将文件中的内容读出置于结构体数组stu中*/
void saveFile(Student *stu,int n) ; /*将结构体数组的内容写入文件*/
#endif
/*④ 文件的内容如下:*/
#include <>
#include <>
#include ""
#include ""
/*函数功能:将文件中内容读出置于数组中
函数参数:形参是结构体指针
函数返回值:从文件中读出的实际记录条数
*/
int readFile(Student *stu )
{
FILE *fp;
int i=0;
if((fp=fopen("d:\\", "rb")) == NULL) /*以读方式打开指定文件*/
{ printf("file does not exist,create it first:\n"); /*若打开失败输出提示信息*/
return 0; /*然后返回0*/
}
fread(&stu[i],sizeStu,1,fp); /*读出第一条记录*/
while(!feof(fp)) /*文件未结束时循环*/
{
i++;
fread(&stu[i],sizeStu,1,fp); /*再读出下一条记录*/
}
fclose(fp); /*关闭文件*/
return i; /*返回记录条数*/
}
/*函数功能:将结构体数组内容写入文件
函数参数:两个形参分别是结构体指针、实际记录条数
函数返回值:无返回值
*/
void saveFile(Student *stu,int n)
{ FILE *fp;
if((fp=fopen("d:\\", "wb")) == NULL) /*以写方式打开指定文件*/
{
printf("can not open file !\n"); /*若打开失败,输出提示信息*/
exit(0); /*然后退出*/
}
fwrite(stu,sizeStu,n,fp); /*一次性向文件写入n条记录*/
fclose(fp) ; /*关闭文件*/
}
/*函数功能:建立初始的数据文件
函数参数:形参分别为结构体指针
函数返回值:返回写入文件的记录条数
*/
int createFile(Student *stu)
{ FILE *fp;
int n;
if((fp=fopen("d:\\", "wb")) == NULL) /*指定文件名,以写方式打开*/
{ printf("can not open file !\n"); /*若打开失败,输出提示信息*/
exit(0); /*然后退出*/
}
printf("input students\' information:\n");
n=readStu (stu,NUM); /*调用中的函数读数据*/
fwrite(stu,sizeStu,n,fp); /*将读入的所有记录全写入文件*/
fclose(fp); /*关闭文件*/
return n; /*返回记录条数*/
}
4.两级菜单提示用户选择。
/*⑤*/
#ifndef _MENU /*条件编译,防止重复包含的错误*/
#define _MENU
void menu( ); /*顶层菜单函数*/
void menuBase( ); /*2、基本信息管理菜单函数*/
void menuScore( ); /*3、学生成绩管理菜单函数*/
void menuCount( ); /*4、考试成绩统计菜单函数*/
void menuSearch( ); /*5、根据条件查询菜单函数*/
#endif
/*⑥*/
#include <>
#include ""
void menu( ) /*顶层菜单函数*/
{
printf("******** 1. 显示基本信息 ********\n");
printf("******** 2. 基本信息管理 ********\n");
printf("******** 3. 学生成绩管理 ********\n");
printf("******** 4. 考试成绩统计 ********\n");
printf("******** 5. 根据条件查询 ********\n");
printf("******** 0. 退出 ********\n");
}
void menuBase( ) /*2、基本信息管理菜单函数*/
{
printf("%%%%%%%% 1. 插入学生记录 %%%%%%%%\n");
printf("%%%%%%%% 2. 删除学生记录 %%%%%%%%\n");
printf("%%%%%%%% 3. 修改学生记录 %%%%%%%%\n");
printf("%%%%%%%% 0. 返回上层菜单 %%%%%%%%\n");
}
void menuScore( ) /*3、学生成绩管理菜单函数*/
{
printf("@@@@@@@@ 1. 计算学生总分 @@@@@@@@\n");
printf("@@@@@@@@ 2. 根据总分排名 @@@@@@@@\n");
printf("@@@@@@@@ 0. 返回上层菜单 @@@@@@@@\n");
}
void menuCount( ) /*4、考试成绩统计菜单函数*/
{
printf("&&&&&&&& 1. 求课程最高分 &&&&&&&&\n");
printf("&&&&&&&& 2. 求课程最低分 &&&&&&&&\n");
printf("&&&&&&&& 3. 求课程平均分 &&&&&&&&\n");
printf("&&&&&&&& 0. 返回上层菜单 &&&&&&&&\n");
}
void menuSearch() /*5、根据条件查询菜单函数*/
{
printf("######## 1. 按学号查询 ########\n");
printf("######## 2. 按姓名查询 ########\n");
printf("######## 3. 按名次查询 ########\n");
printf("######## 0. 返回上层菜单 ########\n");
}
5.主控模块的设计与实现。
/*⑦*/
#ifndef _MAINCONTROL
#define _MAINCONTROL
void printHead( ); /*打印学生信息的表头*/
int baseManage(Student stu[],int n); /*基本信息管理,按唯一学号插入删除修改*/
void scoreManage(Student stu[],int n) ; /*学生成绩管理*/
void printMarkCourse(char *s,double m[3][3],int k); /*打印分数通用函数*/
void countManage(Student stu[],int n); /*考试成绩统计*/
void searchManage(Student stu[],int n); /*该函数完成根据条件查询功能*/
int runMain(Student stu[],int n,int choice); /*主控模块,选择执行于一级菜单功能*/
#endif
/*⑧*/
#include<>
#include""
#include""
#include ""
#include ""
/*函数功能:打印学生信息的表头
函数参数:无形参
函数返回值:无返回值
*/
void printHead( )
{
printf("%8s%10s%8s%6s%6s%8s%6s%6s\n","学号","姓名","性别","数学",
"英语","计算机","总分","名次");
}
/*函数功能:基本信息管理,按唯一学号插入、删除、修改
函数参数:两个形参分别为结构体指针和记录条数
函数返回值:某种操作结束之后实际的记录条数
*/
int baseManage(Student *stu,int n)
{ int choice,t,find[NUM];
Student s;
do
{ menuBase( ); /*显示对应的二级菜单*/
printf("choose one operation you want to do:\n");
scanf("%d",&choice); /*读入选项*/
switch(choice)
{
case 1: readStu(&s,1); /*读入一条待插入的学生记录*/
n=insertStu(stu,n,s); /*调用函数插入学生记录*/
break;
case 2: printf("Input the number deleted\n");
scanf("%ld",&); /*读入一个待删除的学生学号*/
n=deleteStu(stu,n,s); /*调用函数删除该学号学生记录*/
break;
case 3: printf("Input the number modified\n");
scanf("%ld",&); /*读入一个待修改的学生学号*/
t=searchStu(stu,n,s,1,find) ; /*调用函数查找该学号记录*/
if (t) /*如果该学号的记录存在*/
{ readStu(&s,1); /*读入一条完整的学生记录信息*/
stu[find[0]]=s; /*刚读入的记录赋给需改的记录*/ }
else /*如果该学号的记录不存在提示*/
printf("this student is not in,can not be modified.\n");
break;
case 0: break;
}
}while(choice);
return n; /*返回实际记录条数*/
}
/*函数功能:学生成绩管理,包括求总分及排名
函数参数:两个形参分别为结构体指针和记录条数
函数返回值:无返回值
*/
void scoreManage(Student *stu,int n)
{ int choice;
do
{ menuScore( ); /*显示对应的二级菜单*/
printf("choose one operation you want to do:\n");
scanf("%d",&choice); /*读入二级选项*/
switch(choice)
{ case 1: calcuTotal(stu,n);break; /*求所有学生的总分*/
case 2: calcuRank(stu,n); break; /*根据所有学生的总分排名次*/ case 0: break;
}
}while(choice);
}
/*函数功能:打印分数
函数参数:第1个形参是输出分数的提示信息串,第2个形参表示3门课最高、最低、平均分的数组,
第3个形参代表选项,0、1、2对应最高、最低、平均分
函数返回值:无返回值
*/
void printMarkCourse(char *s,double m[3][3],int k)
{
int i;
printf(s); /*s是输出分数的提示信息*/
for (i=0;i<3;i++) /*i控制哪一门课*/
printf("%10.2lf",m[i][k]);
printf("\n");
}
/*函数功能:考试成绩统计,求3门课的最高、最低、平均值
函数参数:两个形参分别为结构体指针和记录条数
函数返回值:无返回值
*/
void countManage(Student *stu,int n)
{
int choice;
double mark[3][3];
do
{ menuCount( ) ; /*显示对应的二级菜单*/
calcuMark(mark,stu,n); /*求3门课的最高、最低、平均值*/
printf("choose one operation you want to do:\n");
scanf("%d",&choice);
switch(choice)
{ case 1: printMarkCourse("三门课的最高分分别是:\n",mark,0);
break;
case 2: printMarkCourse("三门课的最低分分别是:\n",mark,1);
break;
case 3: printMarkCourse("三门课的平均分分别是:\n",mark,2);
break;
case 0: break;
}
}while (choice);
}
/*函数功能:根据条件查询
函数参数:两个形参分别为结构体指针和记录条数
函数返回值:无返回值
*/
void searchManage(Student *stu,int n)
{
int i,choice,findnum,f[NUM];
Student s;
do
{ menuSearch( ); /*显示对应的二级菜单*/
printf("choose one operation you want to do:\n");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Input a student\'s num will be searched:\n");
scanf("%ld",&); /*输入待查询学生的学号*/
break;
case 2: printf("Input a student\'s name will be searched:\n");
scanf("%s",); /*输入待查询学生的姓名*/
break;
case 3: printf("Input a rank will be searched:\n");
scanf("%d",&); /*输入待查询学生的名次*/
break;
case 0: break;
}
if (choice>=1&&choice<=3)
{
findnum=searchStu(stu,n,s,choice,f); /*符合条件元素的下标存于f*/
if (findnum) /*如果查找成功*/
{
printHead( ); /*打印表头*/
for (i=0;i<findnum;i++) /*循环控制f数组的下标*/
printStu(&stu[f[i]],1); /*每次输出一条记录*/
}
else
printf("this record does not exist!\n"); /*查找不到输出提示信息*/
}
}while (choice);
}
/*函数功能:主控模块,选择一级菜单功能执行
函数参数:两个形参分别为结构体指针和记录条数
函数返回值:返回记录条数
*/
int runMain(Student *stu,int n,int choice)
{
switch(choice)
{
case 1: printHead( ); /* 1. 显示基本信息*/
sortStu(stu,n,1); /*按学号由小到大的顺序排序记录*/
printStu(stu,n); /*按学号由小到大顺序输出所有记录*/
break;
case 2: n=baseManage(stu,n); /* 2. 基本信息管理*/
break;
case 3: scoreManage(stu,n); /* 3. 学生成绩管理*/
break;
case 4: countManage(stu,n); /* 4. 考试成绩统计*/
break;
case 5: searchManage(stu,n); /* 5. 根据条件查询*/
break;
case 0: break;
}
return n;
}
/*函数功能:主函数,负责读取或建立文件,然后根据一级菜单的提示调用runMain执行各功能,最后先按学号排序后将结果保存文件
函数参数:无
函数返回值:返回1
*/
int main( ) /*主函数,读取文件,根据一级菜单选择*/
{
Student stu[NUM]; /*定义实参一维数组存储学生记录*/
int choice,n;
n=readFile(stu); /*首先读取文件,记录条数返回赋值给n*/
if (!n) /*如果原来的文件为空*/
n=createFile(stu); /*则首先要建立文件,从键盘上读入记录*/
do
{
menu(); /*显示主菜单*/
printf("Please input your choice: ");
scanf("%d",&choice);
if (choice>=0&&choice<=5)
n=runMain(stu,n,choice); /*选择一级菜单对应的功能*/
else
printf("error input,please input your choice again!\n");
} while (choice);
sortStu(stu,n,1); /*存入文件前按学号由小到大排序*/
saveFile(stu,n); /*将结果存入文件*/
return 0;
}