高级程序设计:学生管理系统(C语言)
本项目可以简单的实现学生信息的增、删、改、查、统计、存储等基本功能:(环境是Dev C++)
- 创建学生信息文件,根据提示输入学生的各项信息,然后按学号对学生信息进行排序,并将排序后的学生信息存储到文件中。
- 增加学生信息,在原有学生信息文件的基础上增加新的学生成绩信息。要求:增加后的学生信息仍按学号排序,并继续保存至原文件。
- 删除学生信息,提示用户输入要进行删除操作的学号,如果在文件中有该信息存在,则将该学号所对应的学生信息删除,否则输出提示信息,并提示用户选择是否继续进行删除操作。
- 修改学生信息,提示用户输入要进行修改操作的学号,如果在文件中有该息存在,则将提示用户输入该学号对应的要修改的选项,结果保存至原文件,并提示用户选择是否继续进行修改操作。
- 查询学生信息,按不同条件对学生信息进行查询操作,输出满足条件的学生信息。
- 基本统计信息,可对学生信息进行基本的统计分析。
功能模块
输入模块
增加信息模块
删除信息模块
修改信息模块
查询统计信息模块
项目源码
/********************************************************************************
* @File name: main.c
* @Description: 该程序主要实现的是学生信息管理,保存了学生的基本信息,包括学号、姓名、班级、
语文成绩、数学成绩、英语成绩、物理成绩以及总成绩这些数据,具体可实现的操作有
1. 创建学生信息文件,根据提示输入学生的各项信息,然后按学号对学生信息进行排序,
并将排序后的学生信息存储到文件中。
2. 增加学生信息,在原有学生信息文件的基础上增加新的学生成绩信息。
并且增加后的学生信息仍按学号排序,并继续保存至原文件。
3. 删除学生信息,提示用户输入要进行删除操作的学号,如果在文件中有该信息存在,
则将该学号所对应的学生信息删除,否则输出提示信息,并提示用户选择是否继续进行删除操作。
4. 修改学生信息,提示用户输入要进行修改操作的学号,如果在文件中有该息存在,
则将提示用户输入该学号对应的要修改的选项,结果保存至原文件,并提示用户选择是否继续进行修改操作。
5. 查询学生信息,按不同条件对学生信息进行查询操作,输出满足条件的学生信息。
6. 基本统计信息,可对学生信息进行基本的统计分析。
* @ Function List:
void show();//显示信息
void input();//输入信息
void search();//查询信息
void del();//删除信息
void modify();//修改信息
void order();//排序
void number();//学生人数的统计
void surface();//管理系统的界面显示
* @Author: 千阴
* @Date: 2019-12-22
* @History: 无
********************************************************************************/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>//C语言里面关于字符数组的函数定义的头文件,常用函数有strlen、strcmp、strcpy等等
#include<conio.h>//用getchar()、getch()就要包含<conio.h>的头文件
#include<dos.h>
#define LEN sizeof(struct student)//学生结构体数组的长度
#define FORM "%d%10s%16s%13d%15d%15d%15d%19.2f\n"//为了使得每次的输出信息时更加简单方便,把这个设为一个常量
#define DATE stu[i].num,stu[i].name,stu[i].clas,stu[i].chiness_score,stu[i].math_score,stu[i].english_score,stu[i].wuli_score,stu[i].sum//输出数据的信息
/*定义一个学生类型的结构体,用于存放学生的信息*/
struct student
{
int num;/*学号 */
char name[20];/*姓名 */
char clas[20];/*班级 */
int chiness_score;/*语文成绩 */
int math_score;/*数学成绩 */
int english_score;/*英语成绩*/
int wuli_score; /*物理成绩*/
float sum;/*总成绩 */
}stu[100];//由于不知道输入多少名学生信息,所以先开始将数组的长度设计得长一些
int main()
{
//对各函数模板进行声明
void show();//显示信息
void input();//输入信息
void search();//查询信息
void delet();//删除信息
void revise();//修改信息
void order();//排序
void number();//统计学生人数
void surface();//界面
//void bben();//界面信息
int n;
//bben();
surface();
scanf("%d",&n);//输入选择功能的编号
while(n)
{ switch(n)
{ case 1: input();break;
case 2: search();break;
case 3: delet();break;
case 4: revise();break;
case 5: order();break;
case 6: number();break;
case 7: show();printf("请按任意键返回菜单!\n");break;
default:break;
}
getch();
surface();//执行完功能再次显示菜单界面
scanf("%d",&n);//输入选择功能的编号
}
return 0;
}
void surface()
{
system("cls");//利用系统的API函数进行清屏处理
printf(" -------------学生信息管理系统-------------\n");
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");
printf(" | 0.退出 |\n");
printf(" ------------------------------------------\n");
printf(" 请输入您要执行的序号(0--7): ");
}
void show()
{ FILE *fp;
int i,a=0;//控制变量
fp=fopen("data.txt","rb");//打开文件
while(!feof(fp))//判断文件指针*fp是否指向文件的末尾
{
if(fread(&stu[a] ,LEN,1,fp)==1)
a++;
}
fclose(fp);//关闭文件
printf("学号 姓名 班级 语文 数学 英语 物理 成绩总分\t\n");
for(i=0;i<a;i++)
{
printf(FORM,DATE);//将信息在界面上显示出来,FORM表示的是数据的格式,DATE表示需要显示的数据
}
}
void input()//添加录入学生信息的小模块
{
int i,a=0,n;//a变量是记录学生信息的条数,i和n都充当循环变量
char ch[2];//保存判断的字符,分别是 Y和 N
FILE *fp;//定义文件指针
if((fp=fopen("data.txt","a+"))==NULL)//打开指定文件 a+:为读/写打开一个指定文件
//第一次打开文件,寻找原本存在的学生信息并且显示出来
{
printf("不能打开文件\n");
return;
}
while(!feof(fp))//feof是END Of File的缩写形式,用于测试流文件的结束
{
if(fread(&stu[a],LEN,1,fp)==1)// 用于文件流中读取数据
a++; //记录当前条数
}
fclose(fp);//关闭文件
if(a==0)
printf("不能记录!\n");
else
{
system("cls");//清屏操作,刷新结果
show();//显示主界面的信息和需要输出的结果
}
if((fp=fopen("data.txt","wb"))==NULL)//wb表示只写,为输出打开一个二进制文件
//第二次打开文件,往文件里写入学生信息
{
printf("不能打开文件\n");//如果打开文件为NULL,则会输出不能打开文件的信息
return ;
}
for(i=0;i<a;i++)
fwrite(&stu[i],LEN,1,fp);//LEN代表学生数组的长度
printf("请输入y/n(提示,输入y继续输入,输入n结束输入):");//为了防止错误删除信息,所以设置了提醒信息
scanf("%s",ch);
while(strcmp(ch,"Y")==0||strcmp(ch,"y")==0)
{
printf("学号:");
scanf("%d",&stu[a].num);//输入学号
for(i=0;i<a;i++)
if(stu[i].num==stu[a].num)//判断信息是否已经存在了 ,如果已经存在,就不写入信息
{
printf("该学号已存在,请按任何键继续!");
getch();
fclose(fp);
return;
}
printf("姓名:");
scanf("%s",stu[a].name);
printf("班级:");
scanf("%s",stu[a].clas);
printf("语文:");
scanf("%d",&stu[a].chiness_score);
printf("数学:");
scanf("%d",&stu[a].math_score);
printf("英语:");
scanf("%d",&stu[a].english_score);
printf("物理:");
scanf("%d",&stu[a].wuli_score);
stu[a].sum=stu[a].chiness_score+stu[a].math_score+stu[a].english_score+stu[a].wuli_score;
if(fwrite(&stu[a],LEN,1,fp)!=1)//将信息写入文件中
{
printf("不能保存!");
getch();
}
else
{
printf("%s 已被保存!\n",stu[a].name);
a++;
}
printf("是否继续y/n(提示,输入y继续输入,输入n结束输入):");//判断是否继续向里面输入数据
scanf("%s",ch);
}
fclose(fp);
printf("OK!请按任意键返回主菜单!\n");
}
void search()//查询学生信息
{
FILE *fp;
int snum,i,a=0;//snum是一个用于记录学号的中间变量
char ch[2];
if((fp=fopen("data.txt","rb"))==NULL)//rb是以二进制的方式对文件进行只读操作
{
printf("不能打开文件\n");
return;
}
while(!feof(fp)) //测试流文件是否结束
{
if(fread(&stu[a],LEN,1,fp)==1)//向文件里面读数据
a++;
}
fclose(fp);
if(a==0)
{
printf("没有记录!\n");
return;
}
printf("请输入要查询学生的学号:");//以下操作是按照学号来查找学生的信息
scanf("%d",&snum);
for(i=0;i<a;i++)
if(snum==stu[i].num)
{
printf("已经找出该学生,是否要显示(y/n):");
scanf("%s",ch);
if(strcmp(ch,"Y")==0||strcmp(ch,"y")==0)
{
printf("学号 姓名 班级 语文 数学 英语 物理 成绩总分\t\n");
printf(FORM,DATE);
break;
}
}
if(i==a) printf("未能找到要查询的信息!\n");
printf("请按任意键返回主菜单!\n");
}
void delet()//删除学生信息
{
FILE *fp;
int snum,i,j,a=0;
char ch[2];
if((fp=fopen("data.txt","r+"))==NULL)//只读取文件的操作
{
printf("不能打开文件\n");
return;
}
while(!feof(fp))
if(fread(&stu[a],LEN,1,fp)==1)
a++;
fclose(fp);
if(a==0)
{
printf("没有记录!\n");
return;
}
printf("请输入要删除学生的学号:");
scanf("%d",&snum);
for(i=0;i<a;i++)
if(snum==stu[i].num)//判断要删除的学生的学号是否存在文件中
break;
printf("已经找到该学生,是否删除(y/n):");
scanf("%s",ch);
if(strcmp(ch,"Y")==0||strcmp(ch,"y")==0)//判断是否要进行删除
for(j=i;j<a;j++)
stu[j]=stu[j+1];//将后一个记录移到前一个记录的位置
a--;//记录的总的学生个数将会减少1
if((fp=fopen("data.txt","wb"))==NULL)//wb为只写,为输出的数据打开一个二进制文件
{
printf("不能打开文件\n");
return;
}
for(j=0;j<a;j++)//将更改后的记录重新写入指定的文件中,此时的顺序不变,和原来排序相同
if(fwrite(&stu[j] ,LEN,1,fp)!=1)
{
printf("不能保存!\n");
getch();
}
fclose(fp);
printf("修改成功!\n");
printf("请按任意键返回主菜单!\n");
}
void revise()//根据学号来修改学生信息
{
FILE *fp;
int snum,i,j,a=0;
if((fp=fopen("data.txt","r+"))==NULL)//读取文件中的数据
{
printf("不能打开文件!\n");
return;
}
while(!feof(fp)) //判断文件指针是否指到文件的末尾
if(fread(&stu[a],LEN,1,fp)==1)
a++;
if(a==0)
{
printf("没有记录!\n");
fclose(fp);
return;
}
printf("请输入你想修改的信息的学生学号!\n");
scanf("%d",&snum);
for(i=0;i<a;i++)
if(snum==stu[i].num)//匹配学号是否相同,如果学号是相同的,就进行相关信息的修改
break;
printf("已经找到该学生,请进行修改!\n");
printf("姓名:");
scanf("%s",stu[i].name);
printf("语文:");
scanf("%d",&stu[i].chiness_score);
printf("数学:");
scanf("%d",&stu[i].math_score);
printf("英语:");
scanf("%d",&stu[i].english_score);
printf("物理:");
scanf("%d",&stu[i].wuli_score);
stu[a].sum=stu[a].chiness_score+stu[a].math_score+stu[a].english_score+stu[a].wuli_score;
if((fp=fopen("data.txt","wb"))==NULL)//wb为只写,为输出的数据打开一个二进制文件
{
printf("不能够打开文件!\n");
return;
}
for(j=0;j<a;j++)
if(fwrite(&stu[j],LEN,1,fp)!=1)
{
printf("不能保存!\n");
getch();
}
fclose(fp);
printf("请按任意键返回主菜单!\n");
}
void order()//将成绩进行排序并输出
{
FILE *fp;
struct student t;
int i,j,m=0;
if((fp=fopen("data.txt","r+"))==NULL)//读取学生文件
{
printf("不能够打开文件!\n");
return;
}
while(!feof(fp))
if(fread(&stu[m],LEN,1,fp)==1)
m++;
fclose(fp);
if(m==0)
{
printf("没有记录!\n");
return;
}
if((fp=fopen("data.txt","wb"))==NULL)//wb为只写,为输出的数据打开一个二进制文件
{
printf("不能打开文件!\n");
return;
}
for(i=0;i<m-1;i++)
for(j=i+1;j<m;j++)
if(stu[i].sum<stu[j].sum)
{
t=stu[i];
stu[i]=stu[j];
stu[j]=t;
}
if((fp=fopen("data.txt","wb"))==NULL)//wb为只写,为输出的数据打开一个二进制文件
{
printf("不能打开!\n");
return;
}
for(j=0;j<m;j++)
if(fwrite(&stu[j],LEN,1,fp)!=1)
{
printf("%s不能保存!\n");
getch();
}
fclose(fp);
show();
printf("请按任意键返回主菜单!\n");
}
void number()//统计学生数量
{
FILE *fp;
int m=0;
if((fp=fopen("data.txt","r+"))==NULL)//读取文件中的数据
{
printf("不能够打开文件!\n");
return;
}
while(!feof(fp))
if(fread(&stu[m],LEN,1,fp)==1)
m++;
if(m==0)
{
printf("不能够记录!\n");
fclose(fp);
return;
}
printf("这个班共有%d个学生!\n",m);
fclose(fp);
printf("请按任意键返回主菜单!\n");
}
项目总结
(1)总体功能:
该系统的总体功能是实现的是学生信息的管理,保存学生的基本信息,包括学号、姓名、班级、语文成绩、数学成绩、英语成绩、物理成绩以及总成绩这些数据,在这个学生信息管理系统中具体可实现的操作有:1、创建学生信息文件,根据提示输入学生的各项信息;2、增加学生信息,在原有学生信息文件的基础上增加新的学生成绩信息;3、删除学生信息;4、修改学生信息;5、查询学生信息,并且按照总分排序和输出,并且进行系统中学生人数的基本统计分析。
(2)不足之处:
1、没有使用动态的数组或者是链表来实现,而是用了一个数组来盛放所有的数据,占用系统内存过大,没有合理释放数组空间。
2、四门学科的成绩单独用变量来表示,没有将其放在数组中,操作起来过程有些繁琐,没有像放在数组中的简洁明了。
3、具体实现的统计模块的功能简单,只能统计系统中学生的人数,以及按照学生的各科总分进行排序输出。
(3)进一步改进方向:
1、使用链表,动态分配内存空间,不过多占用系统的内存资源,保证资源的随时释放。
2、在统计信息模块,增加平均分、各科单独成绩综合的排序输出模块,从而使最终的系统功能更加丰富,统计的功能更加多。
(4)开发心得:
1、通过此次的项目,了解了基本的文件操作,知道怎样向文件中写入数据,并且将文件中的数据进行储存,知道怎样通过二进制的方法进行文件读写。
2、加深了解链表的基本知识,以及动态数组的实现,在此过程中,知道一个程序要尽可能少的占用系统内存资源。
补充:动态数组类
#include <stdio.h>
#include <stdlib.h>
#define SIZE_BLOCK 5
//动态数组类
class rArray
{
int *data;
int size;//0
int max_size;//10
public:
//创建动态数组
rArray(int array_size);
//释放动态数组
~rArray( );
//获取动态数组中元素个数
int get_size( );
//获取动态数组大小
int get_maxsize( );
//增大数组
void growth(int growth_size);
//获取、设置动态数组元素
int* at_value(int index);
//输出数组元素
void output();
};
//构造函数:创建动态数组
rArray::rArray(int array_size)
{
//rArray arr;
size = 0;
max_size = array_size;
data = (int *)malloc(sizeof(int)*array_size);
for(int i=0;i<max_size;i++)
data[i]=0;
}
//析构函数
rArray::~rArray( )
{
free(data);
data = NULL;
size = 0;
max_size = 0;
}
//获取动态数组中元素个数
int rArray::get_size()
{
return size;
}
//获取动态数组大小
int rArray::get_maxsize()
{
return max_size;
}
//增大数组
void rArray::growth(int growth_size)//5
{
printf("数组长度不够,增加长度:%d",growth_size);
int *p;
max_size += growth_size;
p=(int *)malloc(sizeof(int)*(max_size));
int i;
for(i=0;i<size;i++)
{
p[i] = data[i];
}
free(data);
data = p;
}
//获取、设置动态数组元素
int* rArray::at_value(int index)//index=10
{
size++;
if(index >= max_size)
{
growth(SIZE_BLOCK);
}
return &(data[size-1]);
}
void rArray::output()
{
int i;
for(i=0;i<size;i++)
printf("%5d",data[i]);
printf("\n");
}
int main()
{
rArray arr(10);
printf("数组原始大小:%d,数组中元素个数:%d\n",arr.get_maxsize(),arr.get_size());
int number,count=0;
printf("向数组里输入数据(-1结束)\n");
do
{
scanf("%d",&number);//110
if(number!=-1)
*(arr.at_value(count++))=number;//count=10
}while(number!=-1);
printf("当前数组大小:%d,数组中元素的个数%d\n",arr.get_maxsize(),arr.get_size());
printf("数组数据:");
arr.output();
return 0;
}