一、系统需求分析
实现对一个有32个学生的班级,每个学生有7门课程,实现对他们的班级成绩进行添加、修改、删除、查找、统计输出等基本信息进行一系列的操作。每个学生包括如下信息:学号、姓名、7门课程名称。
二、系统功能模块设计
主要包含以下七个模块:
①密码登录
该模块进行登录密码验证,输入账号、密码,输入错误进行提示,3次不对,退出;正确则根据提示进行其他操作
②增加数据
该模块完成将输入的数据存入数据文件中,用户一次可输入多个学生的基本信息。
③更新数据
该模块用于实现对记录的修改,首先用户输入学生的学号,然后查询该学生的基本信息,最后更新该学生的基本信息。
④查询数据
该模块可选择按学生的学号查询,或者按学生的姓名查询,然后列出满足条件的且未作删除标记的学生基本信息。
⑤删除数据
该模块用于删除指定编号的学生基本信息,可通过学号或姓名进行删除为提高效率,只作删除标记,不在物理上删除信息,可称为逻辑删除。
⑥显示数据
该模块用于以列表方式显示所有未作删除标记的学生基本信息。
⑦统计输出(加分项)
- 显示每门课程成绩最高的学生的基本信息。
- 显示每门课程的平均成绩。
- 显示超过某门课程平均成绩的学生人数。
三、系统程序设计
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 30
#define FORMAT1 "--------------------------------------------------------------------------------------------------------------------------------------\n"
#define FORMAT2 "| 学号 | 姓名 | 思修成绩 | 形势与政策成绩 | 高数成绩 | 英语成绩 | 线性代数成绩 | 信息技术成绩| C语言成绩| 总分 | 排名 | 平均分 | \n"
#define FORMAT3 "|---------|--------|----------|----------------|----------|----------|--------------|-------------|----------|-------|------|---------|\n"
#define FORMAT4 "|%9d|%8s| %7d | %8d| %8d| %8d| %8d| %7d| %6d|%7d|%6d|%9f| \n"
#define DATA p->num,p->name,p->sscore,p->cscore,p->mscore,p->escore,p->xscore,p->xxscore,p->cyscore,p->total,p->rank,p->ave
typedef struct student {
int num;
char name[20];
int sscore;
int cscore;
int mscore;
int escore;
int xscore;
int xxscore;
int cyscore;
int total;
float ave;
int rank;
}STU;
typedef struct pointer_info {
STU* pHead; //指向第一个数据单元的指针
int count; //数据单元的个数
char fname[20]; //数据记录的文件名
int saveflag; //1:未保存,0:已保存
}PI;
void Menu(); //主界面
void Add(PI* pi); //添加数据记录
void Display(PI* pi); //显示数据记录
void Delete(PI* pi); //删除数据记录
void Save(PI* pi); //保存数据记录
void Query(PI* pi); //查询数据记录
void Most(PI* pi); //排序数据记录
void Modify(PI* pi); //修改数据记录
void Load(PI* pi); //加载数据记录文件
void New(PI* pi); //新建数据记录文件
void Wrong(); //错误提示
void printheader(); //格式化输出表头
int pass();
int main()
{
int sel;
STU* pstu;
PI pi;
pstu = (STU*)malloc(sizeof(STU) * N); //分配数据单元内存
pi.pHead = pstu; //初始化 pi 的成员
pi.count = 0;
pi.fname[19] = '\0';
pi.saveflag = 0;
char password[10];
int i;
printf("请输入密码:\n");
for(i = 0;i < 3;i++)
{scanf("%s",password);
if(strcmp(password,"123456") == 0)
{ break;}
else
{printf("密码错误,请输入密码:\n");
getchar();}}
if(i == 3)
printf("退出系统\n");
else
{Menu(); //显示主界面
do {
printf("请输入您的选择[0-11]:");
scanf("%d", &sel); //获取键盘输入
if (sel == 0) { //输入 0,退出
if (pi.saveflag == 1) { //如果数据被修改但没有保存,则先保存
if (strlen(pi.fname)) {
Save(&pi);
}
else {
New(&pi);
Save(&pi);
}
}
break;
}
switch (sel)
{
case 1: Add(&pi); break;
case 2: Display(&pi); break;
case 3: Delete(&pi); break;
case 4: Modify(&pi); break;
case 5: Query(&pi); break;
case 6: Most(&pi);break;
case 7: Load(&pi); break;
case 8: New(&pi); break;
case 9: Save(&pi); break;
default: Wrong(); break;
}
} while (1);}
pstu = pi.pHead;
free(pstu);
return 0;
}
void printheader() {
printf(FORMAT1);
printf(FORMAT2);
}
void Menu() {
system("cls");
printf("\t\t\t\t**********************************************\n");
printf("\t\t\t\t* 学生成绩管理系统 *\n");
printf("\t\t\t\t**********************************************\n");
printf("\t\t\t\t* 1、增加数据 *\n");
printf("\t\t\t\t* 2、显示数据 *\n");
printf("\t\t\t\t* 3、删除数据 *\n");
printf("\t\t\t\t* 4、更新数据 *\n");
printf("\t\t\t\t* 5、查询数据 *\n");
printf("\t\t\t\t* 6、统计输出 *\n");
printf("\t\t\t\t* 7、打开文件 *\n");
printf("\t\t\t\t* 8、新建文件 *\n");
printf("\t\t\t\t* 9、保存文件 *\n");
printf("\t\t\t\t* 0、退出 *\n");
printf("\t\t\t\t**********************************************\n");
}
void Wrong() { //按键错误信息
printf("输入有误!\n");
}
void Add(PI* pi) { //由键盘录入学生成绩记录
int i,num;
int numRepeatFlag = 0;
STU* pstu, * p;
do {
pstu = pi->pHead + pi->count; //pstu 指向下一个需要写入数据的单元
p = pi->pHead; //p 用来寻找重复的学号,因此指向数据的第一个单元
printf("请输入学号(输入 0 返回主界面):");
scanf("%d", &num);
for (i = 1; i <= pi->count; i++) { //学号重复处理,学号不能重复
if (num == p->num) {
printf("该学号已存在,请重新输入其它学号!\n");
numRepeatFlag = 1;
break;
}
p++;
}
if (numRepeatFlag) {
numRepeatFlag = 0;
continue;
}
if (num != 0) { //如果输入不为 0,则继续输入学生数据,否则退回主界面
pstu->num = num;
}
else {
Menu();
break;
}
printf("请输入姓名:");
scanf("%s", pstu->name);
printf("请输入思修成绩:");
scanf("%d",&pstu->sscore);
printf("请输入形势与政策成绩:");
scanf("%d", &pstu->cscore);
printf("请输入数学成绩:");
scanf("%d", &pstu->mscore);
printf("请输入英语成绩:");
scanf("%d", &pstu->escore);
printf("请输入线代成绩:");
scanf("%d", &pstu->xscore);
printf("请输入信息技术成绩:");
scanf("%d", &pstu->xxscore);
printf("请输入c语言成绩:");
scanf("%d", &pstu->cyscore);
pstu->total= pstu->sscore + pstu->cscore + pstu->mscore+pstu->escore+pstu->xscore+pstu->xxscore+pstu->cyscore;//计算总分
pstu->ave=pstu->total/8.0;//平均
pstu->rank=0; //排名暂时置 0
pi->count++; //数据单元自增 1
pi->saveflag = 1; //数据改变,为保存标志置 1
} while (1);
}
void Display(PI* pi) { //在屏幕上显示学生数据记录
STU* p;
int i;
Menu();
p = pi->pHead;
if (pi->count == 0) {
printf("没有学生信息!\n");
return;
}
printheader(); //打印表格头部
for (i = 1; i <= pi->count; i++) { //打印数据序列
printf(FORMAT3);
printf(FORMAT4, DATA);
p++;
}
printf(FORMAT1); //打印表格结尾
}
void Query(PI* pi) {
int sel;
int num;
int i;
STU* p;
char name[20];
p = pi->pHead; //p 指向数据序列首部的指针
Menu();
printf("根据学号查询--1\n"); //1:根据学号查询,2:根据姓名查询,其它:返回
printf("根据姓名查询--2\n");
printf("返回------其它\n");
printf("请输入你的选择:");
scanf("%d", &sel);
if (sel == 1) { //按学号查询
printf("请输入你要查询的学号:");
scanf("%d", &num);
for (i = 0; i <= pi->count; i++) { //学号搜索
if (num == p->num) {
break;
}
p++;
}
if (i > pi->count) {
printf("找不到这个学生学号!\n");
return;
}
else {
printheader(); //找到则打印输出
printf(FORMAT4, DATA);
printf(FORMAT1);
}
}
else if (sel == 2) { //按姓名查询
printf("请输入你要查询的姓名:");
scanf("%s", name);
for (i = 1; i <= pi->count; i++) { //按姓名搜索
if (!strcmp(name, p->name)) {
break;
}
p++;
}
if (i > pi->count) {
printf("找不到这个学生姓名!\n");
return;
}
else { //找到则打印输出
printheader();
printf(FORMAT4, DATA);
printf(FORMAT1);
}
}
else {
return;
}
}
void Modify(PI* pi) {
STU* pstu;
int sel;
int num;
char name[20];
int i;
STU* p;
p = pi->pHead;
pstu=pi->pHead;
Menu();
Display(pi);
printf("1----根据学号修改\n"); //1:根据学号修改,2:根据姓名修改,其它:返回
printf("2----根据姓名修改\n");
printf("其它---返回\n");
printf("请输入你的选择:");
scanf("%d", &sel);
if (sel == 1) {
printf("请输入要修改的学生的学号:");
scanf("%d", &num);
for (i = 1; i <= pi->count; i++) {
if (num == p->num) {
break;
}
p++;
}
if (i > pi->count) {
printf("找不到这个学生学号!\n");
return;
}
else {
printf("请输入姓名:");
scanf("%s", p->name);
printf("请输入思修成绩:");
scanf("%d", &pstu->sscore);
printf("请输入形势与政策成绩:");
scanf("%d", &pstu->cscore);
printf("请输入数学成绩:");
scanf("%d", &pstu->mscore);
printf("请输入英语成绩:");
scanf("%d", &pstu->escore);
printf("请输入线代成绩:");
scanf("%d", &pstu->xscore);
printf("请输入信息技术成绩:");
scanf("%d", &pstu->xxscore);
printf("请输入c语言成绩:");
scanf("%d", &pstu->cyscore);
pstu->total= pstu->sscore + pstu->cscore + pstu->mscore+pstu->escore+pstu->xscore+pstu->xxscore+pstu->cyscore;//计算总分
pstu->ave=pstu->total/8.0;//平均
pstu->rank=0; //排名暂时置 0
pi->saveflag = 1;
} //数据单元自增 1
}
else if (sel == 2) {
printf("请输入要修改的学生的姓名:");
scanf("%s", name);
for (i = 1; i <= pi->count; i++) {
if (!strcmp(name, p->name)) {
break;
}
p++;
}
if (i > pi->count) {
printf("找不到这个学生姓名!\n");
return;
}
else {
printf("请输入姓名:");
printf("请输入思修成绩:");
scanf("%d", &pstu->sscore);
printf("请输入形势与政策成绩:");
scanf("%d", &pstu->cscore);
printf("请输入数学成绩:");
scanf("%d", &pstu->mscore);
printf("请输入英语成绩:");
scanf("%d", &pstu->escore);
printf("请输入线代成绩:");
scanf("%d", &pstu->xscore);
printf("请输入信息技术成绩:");
scanf("%d", &pstu->xxscore);
printf("请输入c语言成绩:");
scanf("%d", &pstu->cyscore);
pstu->total= pstu->sscore + pstu->cscore + pstu->mscore+pstu->escore+pstu->xscore+pstu->xxscore+pstu->cyscore;//计算总分
pstu->ave=pstu->total/8.0;//平均
pstu->rank=0; //排名暂时置 0 //数据单元自增 1
pi->saveflag = 1;
}
}
else {
return;
}
}
void Delete(PI* pi) {
int sel;
int num;
char name[20];
int i;
STU* p;
p = pi->pHead;
Menu();
printf("1----根据学号删除\n"); //1:根据学号删除,2:根据姓名删除,其它:返回
printf("2----根据姓名删除\n");
printf("其它---返回\n");
printf("请输入你的选择:");
scanf("%d", &sel);
if (sel == 1) {
printf("请输入你要删除的学号:");
scanf("%d", &num);
for (i = 1; i <= pi->count; i++) {
if (num == p->num) {
break;
}
p++;
}
if (i > pi->count) {
printf("找不到这个学生学号!\n");
return;
}
else if (i == pi->count) {
pi->count--;
pi->saveflag = 1;
printf("删除成功!\n");
}
else {
memcpy(p, p + 1, (pi->pHead + pi->count - p) * sizeof(STU));
pi->count--;
pi->saveflag = 1;
printf("删除成功!\n");
}
}
else if (sel == 2) {
printf("请输入你要删除的姓名:");
scanf("%s", name);
for (i = 1; i <= pi->count; i++) {
if (!strcmp(name, p->name)) {
break;
}
p++;
}
if (i > pi->count) {
printf("找不到这个学生姓名!\n");
return;
}
else if (i == pi->count) {
pi->count--;
pi->saveflag = 1;
printf("删除成功!\n");
}
else {
memcpy(p, p + 1, (pi->pHead + pi->count - p) * sizeof(STU));
pi->count--;
pi->saveflag = 1;
printf("删除成功!\n");
}
}
else {
return;
}
}
void Swap(STU* p1, STU* p2) { //交换两个数据单元
STU stmp;
stmp = *p1;
*p1 = *p2;
*p2 = stmp;
}
void Most(PI* pi) {
int i,max;
int sel;
STU* p,*p1;
p = pi->pHead;
printf("1. 查询思修最高分\n");
printf("2.查询形势与政策最高分\n");
printf("3.查询数学最高分\n");
printf("4.查询英语最高分\n");
printf("5. 查询线性代数最高分\n");
printf("6.查询信息技术最高分\n");
printf("7.查询C语言最高分\n");
printf("其它---返回\n");
printf("请输入你的选择:");
scanf("%d", &sel);
p1=pi->pHead;
p = pi->pHead;
if (sel == 1) {
max=p->sscore;
for (i = 1; i <=pi->count; i++,p++) {
if(max<=p->sscore)
{
max=p->sscore;
p1=p;
}
}
p=p1;
printf("%d",max);
printf("最高分学生成绩如下:");
printheader(); //找到则打印输出
printf(FORMAT4, DATA);
printf(FORMAT1);
pi->saveflag=1; }
else if (sel == 2) {
max=p->cscore;
for (i = 1; i <=pi->count; i++,p++) {
if(max<=p->cscore)
{
max=p->cscore;
p1=p;
}
}
p=p1;
printf("%d",max);
printf("最高分学生成绩如下:");
printheader(); //找到则打印输出
printf(FORMAT4, DATA);
printf(FORMAT1);
pi->saveflag=1; }
else if (sel == 3) {
max=p->mscore;
for (i = 1; i <=pi->count; i++,p++) {
if(max<=p->mscore)
{
max=p->mscore;
p1=p;
}
}
p=p1;
printf("%d",max);
printf("最高分学生成绩如下:");
printheader(); //找到则打印输出
printf(FORMAT4, DATA);
printf(FORMAT1);
pi->saveflag=1;}
else if (sel == 4) { //冒泡法,按学号排序
max=p->escore;
for (i = 1; i <=pi->count; i++,p++) {
if(max<=p->escore)
{
max=p->escore;
p1=p;
}
}
p=p1;
printf("%d",max);
printf("最高分学生成绩如下:");
printheader(); //找到则打印输出
printf(FORMAT4, DATA);
printf(FORMAT1);
pi->saveflag=1; }
else if (sel == 5) {
max=p->xscore;
for (i = 1; i <=pi->count; i++,p++) {
if(max<=p->xscore)
{
max=p->xscore;
p1=p;
}
}
p=p1;
printf("%d",max);
printf("最高分学生成绩如下:");
printheader(); //找到则打印输出
printf(FORMAT4, DATA);
printf(FORMAT1);
pi->saveflag=1;}
else if (sel == 6) {
max=p->xxscore;
for (i = 1; i <=pi->count; i++,p++) {
if(max<=p->xxscore)
{
max=p->xxscore;
p1=p;
}
}
p=p1;
printf("%d",max);
printf("最高分学生成绩如下:");
printheader(); //找到则打印输出
printf(FORMAT4, DATA);
printf(FORMAT1);
pi->saveflag=1;}
else if (sel == 7) {
max=p->cyscore;
for (i = 1; i <=pi->count; i++,p++) {
if(max<=p->cyscore)
{
max=p->cyscore;
p1=p;
}
}
p=p1;
printf("%d",max);
printf("最高分学生成绩如下:");
printheader(); //找到则打印输出
printf(FORMAT4, DATA);
printf(FORMAT1);
pi->saveflag=1;}
else
{
exit(1);
}
pi->saveflag=1;
}
void New(PI* pi) { //新建数据记录文件
FILE* fp;
char name[20];
char fname[20] = ".\\"; //当前文件夹
printf("请输入创建文件名字:");
scanf("%s", name);
strcat(fname, name); //文件名称
strcat(fname, ".dat"); //文件后缀 ".dat"
fp = fopen(fname, "wb"); //以只写方式打开二进制文件
if (fp == NULL) {
printf("新建文件失败!\n");
return;
}
strcpy(pi->fname, fname);
printf("新建数据文件 %s 成功!\n", name);
fclose(fp);
}
void Load(PI* pi) { //加载数据记录文件
FILE* fp;
STU* p = pi->pHead;
char name[20];
char fname[20] = ".\\";
printf("请输入打开文件名字:");
scanf("%s", name);
strcat(fname, name);
fp = fopen(fname, "rb"); //以只读方式打开二进制文件
if (fp == NULL) {
printf("新建文件失败!\n");
return;
}
pi->count = 0;
pi->saveflag = 0;
while (!feof(fp)) {
if (fread(p, sizeof(STU), 1, fp)) {
pi->count++;
p++;
}
}
strcpy(pi->fname, name);
printf("加载数据文件 %s 成功!\n", name);
fclose(fp);
}
void Save(PI* pi) {
FILE* fp;
int numwriten;
if (!strlen(pi->fname)) { //判断数据记录文件是否存在,如果不存在则新建一个
New(pi);
}
fp = fopen(pi->fname, "wb");
if (fp == NULL) {
printf("打开文件失败!\n");
fclose(fp);
return;
}
if (pi->count) { //如果数据不为空,则写入文件
numwriten = fwrite(pi->pHead, 1, pi->count * sizeof(STU), fp);
pi->saveflag = 0;
printf("保存文件成功!\n");
}
else {
printf("保存文件失败!\n");
}
fclose(fp);
}
四、程序运行分析
1、密码登陆界面
系统登录界面,输入账号、密码,输入错误进行提示,3次不对,退出;正确则根据提示进行其他操作。
2、增加数据模块
该模块完成将输入的数据存入数据文件中,用户一次可输入多个学生的基本信息。
3、显示数据模块
该模块用于以列表方式显示所有未作删除标记的学生基本信息。
4、删除数据模块
该模块用于删除指定编号的学生基本信息,可通过学号或姓名进行删除,为提高效率,只作删除标记,不在物理上删除信息,可称为逻辑删除。
5、更新数据模块
该模块用于实现对记录的修改,首先用户输入学生的学号,然后查询该学生的基本信息,最后更新该学生的基本信息。
6、查询数据模块
该模块可选择按学生的学号查询,或者按学生的姓名查询,然后列出满足条件的且未作删除标记的学生基本信息。
7、统计输出模块
a显示每门课程成绩最高的学生的基本信息。
b显示每门课程的平均成绩。
c显示超过某门课程平均成绩的学生人数。