功能模块
具体功能如下:
- 添加学生信息
- 修改学生信息(按学号)
- 排序(分别按总分升序、降序、以及按姓名升序)
- 查找学生(按学号)
- 删除学生
- 查看所有学生信息
数据结构体设计
本表设计一个学生信息的结构体就行:
//学生信息结构体
typedef struct student
{
char ID[10];//学号
char name[20]; //姓名
char sex; //性别
float score[5]; //成绩
float total; //总成绩
float avg; //平均成绩
}STU;
这样就定义了学生信息的结构体STU,STU student[N]定义多个学生
总体设计流程图
在主函数中首先调用load函数,把文件中的学生信息全部读取到结构数组中,然后调用display函数显示主菜单,接着输入选择项,然后根据选择项调用不同的函数执行相应功能。
这样就得到了系统的整体流程
主要功能模块
下面是功能模块函数的声明:
//函数声明
void display(void);//显示菜单
void load(STU stu[],int *nPtr);//输入学生信息
void save(STU stu[],int n);//保存学生信息
void sort(STU stu[],int n);//排序
void InputRecord(STU stu[],int i);//输入一条记录
void find(STU stu[],int n);//查找
void del(STU stu[],int *nPtr);//删除
void add(STU stu[],int *nPtr);//增加
void edit(STU stu[],int n);//修改
void DeleteAll(STU stu[],int *nPtr);//删除所有记录
void DeleteRecord(STU stu[],int *nPtr);//删除一条记录
int FindByNum(STU stu[],int n,char *str);//按学号查找
void output(STU stu[],int n);//输出学生信息
void PrintRecord(STU *sPtr);//输出一条记录
主函数代码编写
定义结构体数组,然后使用Switch来设置进入界面菜单
int main()
{
STU stu[100];//学生信息结构体数组
int n;
int select;
load(stu,&n);//读取文件信息
while (1)
{
display();//显示菜单
scanf("%d",&select);
switch (select)
{
case 1:
add(stu,&n);//增加
break;
case 2:
edit(stu,n);//修改
break;
case 3:
sort(stu,n);//排序
break;
case 4:
find(stu,n);//查找
break;
case 5:
del(stu,&n);//删除
break;
case 6:
output(stu,n);//输出学生信息
break;
case 7:
return 0;
default:
printf("输入错误,请重新输入!\n");
break;
}
}
return 0;
}
显示主菜单display
void display(void)
{
system("cls");//清屏
printf("欢迎使用学生信息管理系统!\n");
printf("说明:在本系统输入功能对应数字即可!\n");
printf("1.增加学生信息\n");
printf("2.修改学生信息\n");
printf("3.排序\n");
printf("4.查找\n");
printf("5.删除\n");
printf("6.输出学生信息\n");
printf("7.退出\n");
}
学生信息加载到数组stu的函数load
运用文件读写fread将文件中的学生信息读取到stu数组中去,记录下当前学生数量
//输入学生信息
void load(STU stu[],int *nPtr)
{
FILE *fp;
int i;
if((fp=fopen("stu.dat","r"))==NULL)
{
*nPtr=0;
printf("文件打开失败!\n");
return;
}
//把文件中的信息读取到结构体数组中
for ( i = 0;fread(&stu[i],sizeof(STU),1,fp)!=0 ; i++);
*nPtr=i;//记录文件中当前学生数量
fclose(fp);
}
保存数据save
//保存数据
void save(STU stu[],int n)
{
FILE *fp;
if((fp=fopen("stu.dat","w"))==NULL)
{
printf("文件打开失败!\n");
return;
}
//把n个记录写入文件
fwrite(stu,n*sizeof(stu[0]),1,fp);
fclose(fp);
}
输入记录InputRecord
//输入一条记录InputRecord
void InputRecord(STU stu[],int i)//输入一条记录
{
int j;
//输入学号,并验证其合法性
printf("请输入第%d个学生的学生信息:",i+1);
printf("请输入学号(学号小于9位数字组成)\n");
scanf("%s",&stu[i].ID);
//输入姓名
printf("请输入姓名(姓名小于20位字符组成)\n");
scanf("%s",&stu[i].name);
//输入性别
printf("请输入性别(男性用m或女性用f)\n");
scanf(" %c",&stu[i].sex);
//输入成绩总和
printf("请输入5门课的成绩(成绩为0-100之间的整数)\n");
stu[i].total=0;
for ( j = 0; j < 5; j++)
{
scanf("%f",&stu[i].score[j]);
stu[i].total+=stu[i].score[j];
}
//计算平均成绩
stu[i].avg=stu[i].total/5;
}
添加记录add
/*调用InputRecord函数添加若干学生信息,并把新添加的学生信息依次保存到文件中 */
//添加记录add
void add(STU stu[],int *nPtr)
{
int i=0;
char sel='y';
while (sel=='y')
{
InputRecord(stu,(*nPtr)++);//添加第n+1个学生信息
(*nPtr)++;
printf("是否继续添加(y/n)?\n");
scanf(" %c",&sel);
}
save(stu,*nPtr);//保存学生信息
}
输出指针sPtr所指记录的内容PrintRecord
//输出指针sPtr所指记录的内容PrintRecord
void PrintRecord(STU *sPtr)
{
int i;
printf("%8s%8s%4c",sPtr->ID,sPtr->name,sPtr->sex);
for ( i = 0; i < 5; i++)
{
printf("%8.2f",sPtr->score[i]);
}
printf("%8.2f%8.2f",sPtr->total,sPtr->avg);
printf("\n");
}
输出学生信息output()
首先输出表头,然后在循环中调用PrintRecord来显示每一个记录的内容
//输出学生信息output
void output(STU stu[],int n)
{
int i;
printf("学号\t姓名\t性别\t课程1\t课程2\t课程3\t课程4\t课程5\t总成绩\t平均成绩\n");
for ( i = 0; i < n; i++)
{
PrintRecord(&stu[i]);
}
system("pause");
}
按学号查找学生信息FindByNum
按学号查询信息,返回学生下标
//按学号查找学生信息FindByNum
int FindByNum(STU stu[],int n,char *str)
{
for ( int i = 0; i < n; i++)
if(strcmp(stu[i].ID,str)==0)
return i;
return -1;
}
修改学生信息函数edit()
该函数首先按用户输入的学号,调用函数FindByName找到要修改的记录,然后调用PrintRecord显示该记录的内容,再逐项询问是否需要修改,最后调用save更新文件。
//edit修改学生信息
void edit(STU stu[],int n)
{
int i,index;
char sel;
char str[20];
printf("请输入学号:\n");
scanf("%s",str);
index=FindByNum(stu,n,str);//查找学号为str的学生信息
if(index<0)
{
printf("没有找到学号为%s的学生信息!\n",str);
return;
}
else
{
printf("找到学号为%s的学生信息!\n",str);
PrintRecord(&stu[index]);
}
//修改姓名
printf("是否修改姓名(y/n)?\n");
scanf(" %c",&sel);
if(sel=='y')
{
printf("请输入新的姓名:\n");
scanf("%s",stu[index].name);
}
//修改性别
printf("是否修改性别(y/n)?\n");
scanf(" %c",&sel);
if(sel=='y')
{
printf("请输入f or m:\n");
scanf("%s",stu[index].sex);
}
//修改成绩
printf("是否修改成绩(y/n)?\n");
scanf(" %c",&sel);
if(sel=='y')
{
stu[index].total=0;
for ( i = 0; i < 5; i++)
{
printf("请输入第%d门课的成绩:\n",i+1);
scanf("%f",&stu[index].score[i]);
stu[index].total+=stu[index].score[i];
}
stu[index].avg=stu[index].total/5;
}
save(stu,n);//保存修改后的学生信息
}
排序sort的功能流程图
排序代码编写
//排序sort
//菜单编写
void sort(STU stu[],int n)
{
int select,i,j;
int (*cmp)(STU a,STU b);//函数指针
int ScoreAsc(STU a,STU b);//成绩升序
int ScoreDesc(STU a,STU b);//成绩降序
int NameAsc(STU a,STU b);//姓名升序
printf("请选择排序方式(1.成绩升序 2.成绩降序 3.姓名升序):\n");
scanf("%d",&select);
switch (select)
{
case 1:
cmp=ScoreAsc;
break;
case 2:
cmp=ScoreDesc;
break;
case 3:
cmp=NameAsc;
break;
default:
return;
}
//比较函数编写
//按照指定规则,进行比较交换排序
for ( i = 0; i < n-1; i++)
for ( j = i+1;j<n;j++)
if((*cmp)(stu[i],stu[j])>0)//若逆序,cmp返回正数
{
STU temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
output(stu,n);//输出排序后的学生信息
}
//成绩升序
int ScoreAsc(STU a,STU b)
{
return a.total>b.total?1:-1;//如果a>b,返回1,否则返回-1
}
//成绩降序
int ScoreDesc(STU a,STU b)
{
return a.total<b.total?1:-1;//如果a<b,返回1,否则返回-1
}
//姓名升序
int NameAsc(STU a,STU b)
{
return strcmp(a.name,b.name);//按照姓名升序排列
/*若 a 和 b 相等,则返回值为 0;
若 a 按字典序小于 b,则返回值为负整数;
若 a 按字典序大于 b,则返回值为正整数。*/
}
查询信息find
//查询find
//在数组stu的前n个元素中,查找学号为str的学生信息
void find(STU stu[],int n)
{
int index;
char str[20];
printf("请输入学号:\n");
scanf("%s",str);
index=FindByNum(stu,n,str);//查找学号为str的学生信息
if(index<0)
{
printf("没有找到学号为%s的学生信息!\n",str);
return;
}
else
{
printf("找到学号为%s的学生信息!\n",str);
PrintRecord(&stu[index]);
}
system("pause");
}
删除del
调用FindByName得到对应下标,然后删除记录,save更新文件
//删除指定记录del
void del(STU stu[],int *nPtr)
{
int i,index;
char str[20];
printf("请输入学号:\n");
scanf("%s",str);
index=FindByNum(stu,*nPtr,str);//查找学号为str的学生信息
if(index<0)
{
printf("没有找到学号为%s的学生信息!\n",str);
return;
}
for ( i = index; i < *nPtr-1; i++)
{
stu[i]=stu[i+1];
}
(*nPtr)--;
printf("删除成功\n");
save(stu,*nPtr);//保存修改后的学生信息
system("pause");
}
删除全部
//删除全部delALL
void DeleteAll(STU stu[],int *nPtr)
{
char str[20];
*nPtr=0;
save(stu,*nPtr);//保存修改后的学生信息
system("pause");
}
整体代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//学生信息结构体
typedef struct student
{
char ID[10];//学号
char name[20]; //姓名
char sex; //性别
float score[5]; //成绩
float total; //总成绩
float avg; //平均成绩
}STU;
//函数声明
void display(void);//显示菜单
void load(STU stu[],int *nPtr);//输入学生信息
void save(STU stu[],int n);//保存学生信息
void sort(STU stu[],int n);//排序
void InputRecord(STU stu[],int i);//输入一条记录
void find(STU stu[],int n);//查找
void del(STU stu[],int *nPtr);//删除
void add(STU stu[],int *nPtr);//增加
void edit(STU stu[],int n);//修改
void DeleteAll(STU stu[],int *nPtr);//删除所有记录
void DeleteRecord(STU stu[],int *nPtr);//删除一条记录
int FindByNum(STU stu[],int n,char *str);//按学号查找
void output(STU stu[],int n);//输出学生信息
void PrintRecord(STU *sPtr);//输出一条记录
int main()
{
STU stu[100];//学生信息结构体数组
int n;
int select;
load(stu,&n);//读取文件信息
while (1)
{
display();//显示菜单
scanf("%d",&select);
switch (select)
{
case 1:
add(stu,&n);//增加
break;
case 2:
edit(stu,n);//修改
break;
case 3:
sort(stu,n);//排序
break;
case 4:
find(stu,n);//查找
break;
case 5:
del(stu,&n);//删除
break;
case 6:
output(stu,n);//输出学生信息
break;
case 7:
return 0;
default:
printf("输入错误,请重新输入!\n");
break;
}
}
return 0;
}
//显示菜单
void display(void)
{
system("cls");//清屏
printf("欢迎使用学生信息管理系统!\n");
printf("说明:在本系统输入功能对应数字即可!\n");
printf("1.增加学生信息\n");
printf("2.修改学生信息\n");
printf("3.排序\n");
printf("4.查找\n");
printf("5.删除\n");
printf("6.输出学生信息\n");
printf("7.退出\n");
}
//输入学生信息
void load(STU stu[],int *nPtr)
{
FILE *fp;
int i;
if((fp=fopen("stu.dat","rb"))==NULL)
{
*nPtr=0;
printf("文件打开失败!\n");
return;
}
//把文件中的信息读取到结构体数组中
for ( i = 0;fread(&stu[i],sizeof(STU),1,fp)!=0 ; i++);
*nPtr=i;//记录文件中当前学生数量
fclose(fp);
}
//保存数据
void save(STU stu[],int n)
{
FILE *fp;
if((fp=fopen("stu.dat","wb"))==NULL)
{
printf("文件打开失败!\n");
return;
}
//把n个记录写入文件
fwrite(stu,n*sizeof(stu[0]),1,fp);
fclose(fp);
}
//输入一条记录InputRecord
void InputRecord(STU stu[],int i)//输入一条记录
{
int j;
//输入学号,并验证其合法性
printf("请输入第%d个学生的学生信息:",i+1);
printf("请输入学号(学号小于9位数字组成)\n");
scanf("%s",&stu[i].ID);
//输入姓名
printf("请输入姓名(姓名小于20位字符组成)\n");
scanf("%s",&stu[i].name);
//输入性别
printf("请输入性别(男性用m或女性用f)\n");
scanf(" %c",&stu[i].sex);
//输入成绩总和
printf("请输入5门课的成绩(成绩为0-100之间的整数)\n");
stu[i].total=0;
for ( j = 0; j < 5; j++)
{
scanf("%f",&stu[i].score[j]);
stu[i].total+=stu[i].score[j];
}
//计算平均成绩
stu[i].avg=stu[i].total/5;
}
//添加记录add
void add(STU stu[],int *nPtr)
{
int i=0;
char sel='y';
while (sel=='y')
{
InputRecord(stu,(*nPtr)++);//添加第n+1个学生信息
(*nPtr)++;
printf("是否继续添加(y/n)?\n");
scanf(" %c",&sel);
}
save(stu,*nPtr);//保存学生信息
}
//输出指针sPtr所指记录的内容PrintRecord
void PrintRecord(STU *sPtr)
{
int i;
printf("%8s%8s%4c",sPtr->ID,sPtr->name,sPtr->sex);
for ( i = 0; i < 5; i++)
{
printf("%8.2f",sPtr->score[i]);
}
printf("%8.2f%8.2f",sPtr->total,sPtr->avg);
printf("\n");
}
//输出学生信息output
void output(STU stu[],int n)
{
int i;
printf("学号\t姓名\t性别\t课程1\t课程2\t课程3\t课程4\t课程5\t总成绩\t平均成绩\n");
for ( i = 0; i < n; i++)
{
PrintRecord(&stu[i]);
}
system("pause");
}
//按学号查找学生信息FindByNum
int FindByNum(STU stu[],int n,char *str)
{
for ( int i = 0; i < n; i++)
if(strcmp(stu[i].ID,str)==0)
return i;
return -1;}
//edit修改学生信息
void edit(STU stu[],int n)
{
int i,index;
char sel;
char str[20];
printf("请输入学号:\n");
scanf("%s",str);
index=FindByNum(stu,n,str);//查找学号为str的学生信息
if(index<0)
{
printf("没有找到学号为%s的学生信息!\n",str);
return;
}
else
{
printf("找到学号为%s的学生信息!\n",str);
PrintRecord(&stu[index]);
}
//修改姓名
printf("是否修改姓名(y/n)?\n");
scanf(" %c",&sel);
if(sel=='y')
{
printf("请输入新的姓名:\n");
scanf("%s",stu[index].name);
}
//修改性别
printf("是否修改性别(y/n)?\n");
scanf(" %c",&sel);
if(sel=='y')
{
printf("请输入f or m:\n");
scanf("%s",stu[index].sex);
}
//修改成绩
printf("是否修改成绩(y/n)?\n");
scanf(" %c",&sel);
if(sel=='y')
{
stu[index].total=0;
for ( i = 0; i < 5; i++)
{
printf("请输入第%d门课的成绩:\n",i+1);
scanf("%f",&stu[index].score[i]);
stu[index].total+=stu[index].score[i];
}
stu[index].avg=stu[index].total/5;
}
save(stu,n);//保存修改后的学生信息
}
//排序sort
void sort(STU stu[],int n)
{
int select,i,j;
int (*cmp)(STU a,STU b);//函数指针
int ScoreAsc(STU a,STU b);//成绩升序
int ScoreDesc(STU a,STU b);//成绩降序
int NameAsc(STU a,STU b);//姓名升序
printf("请选择排序方式(1.成绩升序 2.成绩降序 3.姓名升序):\n");
scanf("%d",&select);
switch (select)
{
case 1:
cmp=ScoreAsc;
break;
case 2:
cmp=ScoreDesc;
break;
case 3:
cmp=NameAsc;
break;
default:
return;
}
//按照指定规则,进行比较交换排序
for ( i = 0; i < n-1; i++)
for ( j = i+1;j<n;j++)
if((*cmp)(stu[i],stu[j])>0)//若逆序,cmp返回正数
{
STU temp=stu[i];
stu[i]=stu[j];
stu[j]=temp;
}
output(stu,n);//输出排序后的学生信息
}
//成绩升序
int ScoreAsc(STU a,STU b)
{
return a.total>b.total?1:-1;//如果a>b,返回1,否则返回-1
}
//成绩降序
int ScoreDesc(STU a,STU b)
{
return a.total<b.total?1:-1;//如果a<b,返回1,否则返回-1
}
//姓名升序
int NameAsc(STU a,STU b)
{
return strcmp(a.name,b.name);//按照姓名升序排列
/*若 a 和 b 相等,则返回值为 0;
若 a 按字典序小于 b,则返回值为负整数;
若 a 按字典序大于 b,则返回值为正整数。*/
}
//查询find
//在数组stu的前n个元素中,查找学号为str的学生信息
void find(STU stu[],int n)
{
int index;
char str[20];
printf("请输入学号:\n");
scanf("%s",str);
index=FindByNum(stu,n,str);//查找学号为str的学生信息
if(index<0)
{
printf("没有找到学号为%s的学生信息!\n",str);
return;
}
else
{
printf("找到学号为%s的学生信息!\n",str);
PrintRecord(&stu[index]);
}
system("pause");
}
//删除指定记录del
void del(STU stu[],int *nPtr)
{
int i,index;
char str[20];
printf("请输入学号:\n");
scanf("%s",str);
index=FindByNum(stu,*nPtr,str);//查找学号为str的学生信息
if(index<0)
{
printf("没有找到学号为%s的学生信息!\n",str);
return;
}
for ( i = index; i < *nPtr-1; i++)
{
stu[i]=stu[i+1];
}
(*nPtr)--;
printf("删除成功\n");
save(stu,*nPtr);//保存修改后的学生信息
system("pause");
}
//删除全部delALL
void DeleteAll(STU stu[],int *nPtr)
{
char str[20];
*nPtr=0;
save(stu,*nPtr);//保存修改后的学生信息
system("pause");
}
运行截图:
代码还是有点小问题,
后续希望完善。