班级成绩管理系统

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

#include
#include
#include
#include

#define MAX 7 //最大的课程处理数量
#define NSIZE 15 //学生名字的最大长度
#define SUBSIZE 20 //课程名称的最大长度
#define FNAME_MAX 100 //保存文件名最大长度
#define MENU 1 //让get_choose()输出基础功能菜单
#define SORT_MENU 2 //让get_choose()输出排序功能菜单
#define REVISE_MENU 3 //让get_choose()输出修改功能菜单
#define YES 1 //是
#define NO 0 //否
#define SIZE sizeof(STUDENT)
#define PASSWORD "123456" //修改功能的密码
#define PWMAX 10 //密码的最大长度

struct Student
{
int num; //学号
char name[NSIZE]; //姓名
float score[MAX]; //各科成绩
float total; //总分
float average; //平均分
struct Student *next;
};
typedef struct Student STUDENT;
int COUNT = 0; //科目的数量
char SUBJECT[MAX][SUBSIZE]; //学科的名称
int FULL_MARK[MAX] = {100, 100, 100, 100, 100, 100, 100}; //各学科满分

int verify_password(void);
void welcome(void);
void print_star(void);
void print_menu(void);
void print_revise(void);
void print_submenu(void);
void stop(void);
int get_sure(void);
FILE *get_fname(void);
float get_score(int);
int get_num(void);
void get_information(void);
char get_choose(int);
int get_subject(void);
void swap_date(STUDENT *, STUDENT *);
void input(STUDENT *);
STUDENT *create(STUDENT *);
void output(STUDENT *);
int save(STUDENT *);
void sort(STUDENT *);
STUDENT *revise(STUDENT *);
void insert(STUDENT *);
STUDENT *del(STUDENT *);
void statistics(STUDENT *);
void freeall(STUDENT *);

int main(void)
{
STUDENT *head = NULL;
char ch = '\0';
int saved = NO;

welcome();
stop();

get_information();

do
{
while((ch = get_choose(MENU)) != 'g') //输入g时退出循环
{
switch(ch)
{
case 'a' : head = create(head); break; //成绩输入
case 'b' : output(head); break; //成绩显示
case 'c' : saved = save(head); break; //成绩保存
case 'd' : sort(head); break; //成绩排序
case 'e' : head = revise(head); break; //成绩修改
case 'f' : statistics(head); break; //成绩统计
default : puts("没有该功能!请查看菜单后再次选择。");
}

stop();
putchar('\n');
}

if(saved == NO && head != NULL) //提示未保存
{
printf("录入成绩尚未保存,确认推出(y/n)?:");
if(get_sure() == YES)
saved = YES;
}
}
while(!saved);

freeall(head);
puts("已退出系统!");
return 0;
}

/*
函数功能:输出欢迎界面
入口参数:无
出口参数:无
返回值 :无
*/
void welcome(void)
{
puts(" ☆☆☆☆

☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
puts(" ☆☆☆☆ ☆☆☆☆");
puts(" ☆☆☆☆ 欢迎使用成绩管理系统 ☆☆☆☆");
puts(" ☆☆☆☆ ☆☆☆☆");
puts(" ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
}

/*
函数功能:输入课程数量及各科名称
入口参数:无
出口参数:无
返回值 :无
*/
void get_information(void)
{
int i;

puts("将会收集相关信息");
print_star();

printf("请输入课程的数量(最多支持%d门):", MAX);
while(scanf("%d", &COUNT) !=1 || COUNT > MAX)
{
fflush(stdin);
printf("输入有误!请输入一个不大于%d的数字,例如5,%d:", MAX, MAX);
}

print_star();
putchar('\n');

fflush(stdin);

print_star();

for(i = 0; i < COUNT; i++)
{
printf("请输入第%d门学科的名称:", i+1);
gets(SUBJECT[i]);
}

print_star();
putchar('\n');

print_star();

printf("各科满分均为100,是否修改(y/n)?:");
if(get_sure() == YES)
{
for(i = 0; i < COUNT; i++)
{
printf("请输入%s满分:", SUBJECT[i]);
FULL_MARK[i] = get_num();
}
}

print_star();

fflush(stdin);
}

/*
函数功能:选择需要排序的科目
入口参数:无
出口参数:int sub(所选择的科目)
返回值 :返回的数字与用户开始定义的科目先对应
*/
int get_subject(void)
{
int sub = 0;

print_submenu();

printf("请选择:");
while(scanf("%d", &sub) != 1 || sub > COUNT + 1)
{
fflush(stdin);
printf("选择有误!请正确选择!(1~%d):", COUNT + 1);
}

fflush(stdin);

return sub;
}

/*
函数功能:输入成绩并验证正确性
入口参数:无
出口参数:float score
返回值 :一个合法成绩
*/
float get_score(int i)
{
float score = 0;

while(scanf("%f", &score) != 1 || score <0 || score >FULL_MARK[i])
{
fflush(stdin);

printf("输入错误!请输入一个合法成绩(0~%d):", FULL_MARK[i]);
}

fflush(stdin);

return score;
}

/*
函数功能:输入学号并验证正确性
入口参数:无
出口参数:int num
返回值 :一个合法的学号
*/
int get_num(void)
{
int num =0;

while(scanf("%d", &num) != 1 || num <0)
{
fflush(stdin);

printf("输入错误!请输入一个合法学号(只支持纯数字学号):");
}

fflush(stdin);

return num;
}

/*
函数功能:输出基础功能菜单
入口参数:无
出口参数:无
返回值 :无
*/
void print_menu(void)
{
print_star();

puts(" ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
puts(" ☆☆☆☆☆☆本系统具有的功能如下☆☆☆☆☆☆");
puts(" ☆a)成绩录入 b)成绩显示 c)成绩保存☆");
p

uts(" ☆d)成绩排序 e)成绩修改 f)成绩统计☆");
puts(" ☆g)退出系统 ☆");
puts(" ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");

print_star();
}

/*
函数功能:输出修改菜单
入口参数:无
出口参数:无
返回值 :无
*/
void print_revise(void)
{
print_star();

puts(" ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆:");
puts(" ☆☆☆☆☆请选择修改的方式☆☆☆☆☆:");
puts(" ☆a)修改单人成绩 b)删除单人成绩☆");
puts(" ☆c)返回上级菜单 ☆");
puts(" ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆:");

print_star();
}

/*
函数功能:输出排序菜单
入口参数:无
出口参数:无
返回值 :无
*/
void print_sort(void)
{
print_star();

puts(" ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
puts(" ☆☆☆☆请选择排序关键字☆☆☆☆");
puts(" ☆a)学号 b)总分 c)平均分☆");
puts(" ☆d)单个科目 e)返回上级菜单 ☆");
puts(" ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");

print_star();
}

/*
函数功能:输出可供选择的课程关键字
入口参数:无
出口参数:无
返回值 :无
*/
void print_submenu(void)
{
int i;

print_star();

puts(" ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
puts(" ☆☆☆☆☆☆请选择科目☆☆☆☆☆☆☆");
printf(" ");
for(i = 0; i < COUNT; i++)
{
printf("%d)%-12s", i + 1, SUBJECT[i]);

if(((i + 1) % 3) == 0) // 每输出三个科目换行
{
putchar('\n');
printf(" ");
}
}

printf("%d)返回上级菜单\n", i+1);
puts(" ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
putchar('\n');

print_star();
}

/*
函数功能:显示各功能菜单,并返回用户的选择
入口参数:无
出口参数:char ch(选择功能)
返回值 :a~f分别对应主函数中的6个功能,g退出程序
*/
char get_choose(int mode)
{
char ch = '\0';

switch(mode)
{
case MENU : print_menu(); break;
case SORT_MENU : print_sort(); break;
case REVISE_MENU : print_revise(); break;
default : ;
}

printf("请输入所需的功能:");
while(!isalpha(ch = getchar()))
{
fflush(stdin);
printf("输入有误!请输入字母,例如c,f:");
}

putchar('\n');

fflush(stdin);

return tolower(ch);
}

/*
函数功能:打印一串*号
入口参数:无
出口参数:无
返回值 :无
*/
void print_star(void)
{
puts("§====================================================

========================§");
}

/*
函数功能:暂停输出,按任意字符后继续
入口参数:无
出口参数:无
返回值 :无
*/
void stop(void)
{
puts("按回车继续...");
getchar();
fflush(stdin);
}

/*
函数功能:根据用户的输入,返回一个是或否的值(1和0)
入口参数:无
出口参数:int response
返回值 :YES(确定),NO(放弃)
*/
int get_sure(void)
{
int response = YES;
char ch;

fflush(stdin);
//检验输入,只允许输入y和n
while((ch = tolower(getchar())) != 'y' && ch != 'n')
{
fflush(stdin);
printf("只能识别y和n!:");
}

if(ch != 'y')
response = NO;

fflush(stdin);
return response;
}
/*
函数功能:让用户输入一个合法的用户名,并返回文件指针
入口参数:无
出口参数:FILE *fp
返回值 :一个合法的文件指针
*/
FILE *get_fname(void)
{
char fname[FNAME_MAX] = {'\0'};
FILE *fp = NULL;

print_star();
puts("说明:");
puts("输入“D:\\\\CC\\\\temp\\\\score.txt”,");
puts("则生成文件socre.txt文件保存在D盘CC文件夹中temp文件夹中");
puts("请确保使用\\\\,并以.txt结尾,所储存文件夹已经建立,否则可能出错。");
puts("保存文件可用文件夹打开");
print_star();

while(1)
{
puts("请按说明格式输入文件名:");
scanf("%s", fname);
fflush(stdin);

if((fp = fopen(fname, "w")) == NULL)
{
puts("建立文件失败");
printf("是否尝试重新输入文件名再次建立(y/n)?:");
if(get_sure() == YES)
continue;
else
break;
}
else
break;
}

return fp;
}

/*
函数功能:交换两个节点内的数据
入口参数:STUDENT *a, STUDENT *b(代交换的两个节点)
出口参数:无
返回值 :无
*/
void swap_date(STUDENT *a, STUDENT *b)
{
STUDENT temp;

temp = *a;
*a = *b;
*b = temp;
b->next = a->next;
a->next = temp.next;
}

/*
函数功能:密码的验证
入口参数:无
出口参数:int sure(代表密码是否正确)
返回值 :YES密码正确,NO密码不正确
*/
int verify_password(void)
{
int sure = YES;
char pw[PWMAX+1] = {'\0'};

print_star();
printf("请输入密码(最长支持%d位):", PWMAX);
gets(pw);

if(strcmp(pw, PASSWORD) != 0)
sure = NO;

return sure;
}

/*
函数功能:输入学生信息及成绩
入口参数:STUDENT *current
出口参数:无
返回值 :无
*/
void input(STUDENT *current)
{
int i;

while(1) //输入数据,确认后循环结束
{
print_star();
printf("请输入学号:");
current->num = get_num();
fflush(stdin);

printf("请输入姓名:");
gets(current->name);
fflush(stdin);

for(i = 0, current->total = 0; i < COUNT; i++)
{
printf("请输入%s成绩:", SUBJECT[i]);
current->score[i] = get_score(i);
current->total += current->scor

e[i];
}

current->average = current->total / COUNT;

printf("确认输入(y/n)?");
if(get_sure() == YES)
{
print_star();
break;
}
else
{
print_star();
puts("已经放弃输入,请重新输入!");
}

}
putchar('\n');
}

/*
函数功能:建立链表
入口参数:无
出口参数:STUDENT *head
返回值 :链表的入口
*/
STUDENT *create(STUDENT *head)
{
STUDENT *nhead = NULL;
STUDENT *prev = NULL;
STUDENT *current = NULL;

while(1)
{
current = (STUDENT *)malloc(SIZE);

input(current);

if(nhead == NULL)
nhead = current;
else
prev->next = current;

current->next = NULL;

printf("是否继续输入(y/n)?");
if(get_sure() == NO)
break;
else
prev = current;
}

puts("输入结束!");

if(head == NULL)
{
head = nhead;
}
else
{
//把新链表接到原链表尾部
current = head;
while(current->next != NULL)
current = current->next;

current->next = nhead;
}

return head;
}

/*
函数功能:输出链表
入口参数:STUDENT *head
出口参数:无
返回值 :无
*/
void output(STUDENT *head)
{
int i;

print_star();
if(head == NULL)
{
puts("数据为空!!!");
}
else
{
printf("%-15s%-8s", "学号", "姓名");
for(i = 0; i < COUNT; i++)
{
printf("%-8s", SUBJECT[i]);
}
printf("%-8s%-8s\n", "总分", "平均分");

while(head != NULL)
{
printf("%-15d%-8s", head->num, head->name);

for(i = 0; i < COUNT; i++)
{
printf("%-8.1f", head->score[i]);
}

printf("%-8.1f%-8.2f", head->total, head->average);

putchar('\n');
head = head->next;
}
}
print_star();
}

/*
函数功能:将数据保存到文件
入口参数:STUDENT *head
出口参数:int saved
返回值 :NO(未保存),YES(保存成功)
*/
int save(STUDENT *head)
{
FILE *fp = NULL;
int saved = NO;
int i;

if(head == NULL)
{
puts("数据为空!!!");
return saved;
}
else
{
if((fp = get_fname()) == NULL)
{
puts("保存失败");
return saved;
}
fprintf(fp, "%-15s%-8s", "学号", "姓名");
for(i = 0; i < COUNT; i++)
{
fprintf(fp, "%-8s", SUBJECT[i]);
}
fprintf(fp, "%-8s%-8s\n", "总分", "平均分");

while(head != NULL)
{
fprintf(fp, "%-15d%-8s", head->num, head->name);

for(i = 0; i < COUNT; i++)
{
fprintf(fp, "%-8.1f", head->score[i]);
}

fprintf(fp, "%-8.1f%-8.2f", head->total, head->average);

fputc('\n', fp);
head = head->next;
}

fclose(fp);
puts("已成功保存");

saved = YES;
return saved;
}
}

/*
函数功能:对数据进行排序
入口参数:STUDENT *head(链表入口)
出口参数:无
返回值 :无
*/
void sort(STUDENT *head)
{
STUDENT *current = NULL;
STUDENT *round = NULL;
STUDENT *ptemp = N

ULL;
char mode = '\0';
int flag = NO;
int sub = 0; //排序的科目

if(head == NULL)
{
puts("数据为空!!!!");
}
else
{
puts("请选择排序的关键字(均为升序排列)");

while((mode = get_choose(SORT_MENU)) > 'c')
{
if(mode == 'd')
{
if((sub = get_subject()) > COUNT) //获得大于科目数的返回值者返回上一级菜单
continue;
else
break;
}
else
{
if(mode == 'e')
return;
else
{
printf("请选择正确关键字排序!");
stop();
}
}
}

current = head;
while(current->next != NULL)
{
ptemp = current;

for(round = current->next; round != NULL; round = round->next)
{
switch(mode)
{
case 'a' : if(ptemp->num > round->num)
flag = YES;
break;
case 'b' :
case 'c' : if(ptemp->total > round->total) // 关键字按平均分和总分排序的结果一样
flag = YES;
break;
case 'd' : if(ptemp->score[sub - 1] > round->score[sub - 1])
flag = YES;
break;
default :;
}

if(flag)
{
ptemp = round;
flag = NO;
}
}

if(ptemp != current)
{
swap_date(ptemp, current);
}
current = current->next;
}

puts("排序结束!!!可使用(成绩显示)功能查看");
}
}

/*
函数功能:修改及删除链表
入口参数:STUDENT *head(链表入口)
出口参数:STUDENT *head
返回值 :修改后的链表入口
*/
STUDENT *revise(STUDENT *head)
{
char choose = '\0';

if(head == NULL)
{
puts("数据为空!!!");
}
else
{
while(verify_password() == NO)
{
printf("密码错误!!!是否重新输入密码(y/n)?");
if(get_sure() == NO)
return head;
}

while((choose = get_choose(REVISE_MENU)) != 'c')
{
switch(choose)
{
case 'a' : insert(head);
break;
case 'b' : head = del(head);
break;
default : puts("无此功能!!!查看菜单后重新选择!");
}

stop();

if(head == NULL)
{
puts("数据为空!!!继续后自动返回上级菜单");
break;
}
}

puts("修改结束...");
}

return head;
}


/*
函数功能:对单个学生成绩进行修改
入口参数:STUDENT *head(链表入口)
出口参数:无
返回值 :无
*/
void insert(STUDENT *head)
{
STUDENT *current = NULL;
int tnum = 0;

while(1)
{
output(head);
print_star();
printf("请输入要修改的学生学号:");
scanf("%d", &tnum);

for(current = head; current != NULL; current = current->next) //查找要修改的学生
{
if(current->num == tnum)
break;
}

if(current == NULL)
{
puts("没有此学号!!!请确认后重新输入!!");
}
else
{
input(current);
}
print_

star();

printf("是否继续修改其他数据(y/n)?");
if(get_sure() == NO)
break;
}

puts("修改结束...");
}

/*
函数功能:对单个学生成绩进行删除
入口参数:STUDENT *head(链表入口)
出口参数:STUDENT *head
返回值 :修改后的链表入口
*/
STUDENT *del(STUDENT *head)
{
STUDENT *current = NULL;
STUDENT *prev = NULL;
int tnum = 0;

while(1)
{
output(head);
print_star();
printf("请输入要修改的学生学号:");
scanf("%d", &tnum);

current = prev = head;
while(current != NULL) //查找要删除的学生
{
if(current->num == tnum)
break;
else
{
if(current == head)
{
current = current->next;
}
else
{
prev = current;
current = current->next;
}
}
}

if(current == NULL)
{
puts("没有此学号!!!请确认后重新输入!!");
}
else
{
printf("是否删除(y/n)?");
if(get_sure() == YES)
{
if(current == head)
{
head = current->next;
}
else
{
prev->next = current->next;
}

free(current);
}
else
{
puts("已经放弃删除!");
}
}
print_star();

printf("是否继续删除其他数据(y/n)?");
if(get_sure() == NO || head == NULL)
break;
}

puts("删除结束...");
return head;
}

/*
函数功能:对数据进行分析
入口参数:STUDENT *head(链表入口)
出口参数:无
返回值 :无
*/
void statistics(STUDENT *head)
{
STUDENT *sub_max[MAX] = {NULL}; //各科最高分的学生信息
STUDENT *current = NULL;
int over[MAX] = {0}; //超出某门课程平均分的人数
float sub_aver[MAX] = {0}; //平均分
int people = 0; //统计人数
int i;

print_star();
if(head == NULL)
{
puts("数据为空!!!");
}
else
{
for(i = 0; i < COUNT; i++) //假设头指针指向的数据均为最高分
sub_max[i] = head;

current = head;
while(current != NULL)
{
for(i = 0; i < COUNT; i++)
{
if(current->score[i] > sub_max[i]->score[i])
sub_max[i] = current;
sub_aver[i] += current->score[i]; //暂时保留总分
}
people++;
current = current->next;
}

for(i = 0; i < COUNT; i++) //计算平均分
{
sub_aver[i] = sub_aver[i] / people;
}

current = head;
while(current != NULL) //统计超过平均分的人数
{
for(i = 0; i < COUNT; i++)
{
if(current->score[i] > sub_aver[i])
over[i]++;
}

current = current->next;
}

printf("%20s", " ");
for(i = 0; i < COUNT; i++) //输出课程名称
{
printf("%-10s", SUBJECT[i]);
}
putchar('\n');

printf("%-20s", "最高分学号"); //输出各科最高分的学号
for(i = 0; i < COUNT; i++)
{
printf("%-10d", sub_max[i]->num);

}
putchar('\n');

printf("%-20s", "最高分姓名"); //输出各科最高分的姓名
for(i = 0; i < COUNT; i++)
{
printf("%-10s", sub_max[i]->name);
}
putchar('\n');

printf("%-20s", "最高分"); //输出各科最高分
for(i = 0; i < COUNT; i++)
{
printf("%-10.1f", sub_max[i]->score[i]);
}
putchar('\n');

printf("%-20s", "平均分"); //输出各科平均分
for(i = 0; i < COUNT; i++)
{
printf("%-10.2f", sub_aver[i]);
}
putchar('\n');

printf("%-20s", "超过平均分人数"); //输出各科超过平均分的人数
for(i = 0; i < COUNT; i++)
{
printf("%-10d", over[i]);
}
putchar('\n');
}
print_star();
}

/*
函数功能:释放内存
入口参数:STUDENT *head
出口参数:无
返回值 :无
*/
void freeall(STUDENT *head)
{
STUDENT *current = NULL;
while(head != NULL)
{
current = head->next;
free(head);
head = current;
}
}

相关文档
最新文档