成绩管理系统C语言版
第一次做课程设计,做了一个学生成绩管理系统,还算完整,用了双链表,用C语言写的,放在这留作纪念,写的不好的地方也请指教。
整体框架
支持3类用户登录:管理员,教师和学生,上级可以管理下级,管理员只有一个,3类用户数据分别存放在3个文件中,账户和密码经过了简单的加密。
- 管理员:只有一个,可以更改自身信息和更改、添加教师信息
- 教师用户:教师用户的功能占了大部分,可以管理学生的成绩与账户密码:包括成绩的增删查改,成绩的综合统计与分析
- 学生用户:学生用户只提供查询和密码修改功能,可以查询自己的成绩和名次
- 数据的读取和写回:学生和教师的数据由于会在程序执行过程中较多的修改,所以程序开始时从磁盘读取,结束时写回磁盘
- 包括主函数文件main.c,管理员,教师和学生的函数各一个文件,公共函数一个文件,界面入口一个文件
主函数
#include "interface.h"
#include "pub_fun.h"
Link head_student,end_student; //学生链表的头结点和尾节点指针
int count_student=0; //学生数量计数
FILE *fp_student; //学生信息文件“student.dat”的指针
struct Teacher *head_teacher,*end_teacher;
int count_teacher = 0;
FILE *fp_teacher;
int main()
{
system("color 8f");
create_student_linkedlist();
read_student_data(); //从文件中读取学生数据,如果文件不存在,则创建
create_teacher_linkedlist();
read_teacher_data(); //从文件中读取教师数据,如果文件不存在,则创建
stu_system();
save_student_data();
save_teacher_data();
return 0;
}
公共函数
公共函数头文件
#ifndef PUB_FUN_H_INCLUDED
#define PUB_FUN_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define PUT_FORMAT "%12s%10s%7d%6d%6d%7d%6d%8.2f\n" //学生信息和成绩输出格式
#define PUT_DATA p->num,p->name,p->grade[1],p->grade[2],p->grade[3],p->grade[4],p->grade[0],p->average
#define M " " //为界面美观,输入距左边界5个空格
#define LEN_NODE sizeof(Node)
//学生结构体
typedef struct Student{
char num[15]; //学号
char passwd[15]; //学生的登录密码,在创建学生成绩时统一设置为“123456”,学生可以自行更改
char name[15]; //姓名
int grade[5]; //语数英和C语言4门课程成绩的数组 grade[0]总分
float average; //平均分
struct Student *next; //指向后一个结点
struct Student *pre; //指向前一个结点
}Node, *Link;
//教师结构体
struct Teacher
{
char num[15];
char name[15];
char passwd[15];
struct Teacher *pre;
struct Teacher *next;
};
void create_student_linkedlist();
void read_student_data();
void create_teacher_linkedlist();
void read_teacher_data();
void input_num_passwd_string(char *s,int len,char *notice);
void input_string(char *s,int len,char *notice);
void wrong();
void save_teacher_data();
void save_student_data();
Link search_student(char find_what[],int choice);
struct Teacher *search_teacher(char find_what[],int choice);
void print_grade_header();
void print_grade();
void anykey_continue();
void string_encryption(char *s);
void string_decipher(char *s);
int student_grade_ranking(char *account,int i);
void lookup_student_ranking (char *account);
void nofind(); //当无所查找信息时的输出
void clear_buffer();
#endif // PUB_FUN_H_INCLUDED
公共函数实现
#include "pub_fun.h"
extern FILE *fp_student;
extern Link head_student,end_student;
extern int count_student;
extern FILE *fp_teacher;
extern struct Teacher *head_teacher,*end_teacher;
extern int count_teacher;
void create_student_linkedlist() //创建双链表的头结点,用全局变量返回头指针和尾指针
{
head_student=malloc(sizeof(Node));
head_student->pre=NULL;
head_student->next=NULL;
end_student=head_student;
}
void create_teacher_linkedlist() //创建双链表的头结点,用全局变量返回头指针和尾指针
{
head_teacher=malloc(sizeof(struct Teacher));
head_teacher->pre=NULL;
head_teacher->next=NULL;
end_teacher=head_teacher;
}
void input_num_passwd_string(char *s,int len,char *notice) //输入编号密码时使用
{
int flag;//字符串是否合法的标志
do
{
printf(notice); //输出提示信息
scanf("%s",s);
if(strlen(s)>len)
{
printf(M"超出长度,请重新输入\n");
continue;
}
int i=0; //循环控制
flag=0;
while(s[i])
{
if(!((s[i]>='0'&&s[i]<='9')||(s[i]>='a'&&s[i]<='z')||(s[i]>='a'&&s[i]<='z')))
{
printf(M"输入不正确,请重新输入只字母、数字的字符串:\n");
clear_buffer();
flag=1;
break;
}
i++;
}
}
while(strlen(s)>len||flag);
}
void input_string(char *s,int len,char *notice) //输入字符串
{
do
{
printf(notice); //输出提示信息
scanf("%s",s);
if(strlen(s)>len)
{
printf(M"超出长度,请重新输入\n");
continue;
}
}
while(strlen(s)>len);
}
void wrong() //输入出错时的提示
{
printf("\n");
printf("输入错误\n\n");
}
void read_student_data() //从文件中读取学生数据,如果文件不存在,则创建
{
if((fp_student=fopen("student.dat","rb"))!=NULL)
{
while(!feof(fp_student))
{
Link p=malloc(LEN_NODE); //p依次指向一个学生数据
if(fread(p,LEN_NODE,1,fp_student)==1)
{
string_decipher(p->passwd);
string_decipher(p->num);
p->next=NULL;
p->pre=end_student;
end_student->next=p;
end_student=p;
count_student++;
}
}
}
else
fp_student=fopen("student.dat","w");
fclose(fp_student);
}
void read_teacher_data() //从文件中读取学生数据,如果文件不存在,则创建
{
if((fp_teacher=fopen("teacher.dat","rb"))!=NULL)
{
while(!feof(fp_teacher))
{
struct Teacher *p=malloc(sizeof(struct Teacher)); //p依次指向一个学生数据
if(fread(p,sizeof(struct Teacher),1,fp_teacher)==1)
{
string_decipher(p->passwd);
string_decipher(p->num);
p->next=NULL;
p->pre=end_teacher;
end_teacher->next=p;
end_teacher=p;
count_teacher++;
}
}
}
else
fp_teacher=fopen("teacher.dat","w");
fclose(fp_teacher);
}
void save_student_data()
{
if((fp_student=fopen("student.dat","wb"))==NULL)
printf("文件打开失败\n");
Link p=head_student->next; //p指向第一个数据结点
// for(int i=0;i<count_student;i++)
// {
// fwrite(p,LEN_NODE,1,fp_student);
// p=p->next;
// }
while(p)
{
string_encryption(p->passwd);
string_encryption(p->num);
fwrite(p,LEN_NODE,1,fp_student);
p=p->next;
}
}
void save_teacher_data()
{
if((fp_teacher=fopen("teacher.dat","wb"))==NULL)
printf("文件打开失败\n");
struct Teacher *p=head_teacher->next; //p指向第一个数据结点
// for(int i=0;i<count_student;i++)
// {
// fwrite(p,LEN_NODE,1,fp_student);
// p=p->next;
// }
while(p)
{
string_encryption(p->passwd);
string_encryption(p->num);
fwrite(p,sizeof(struct Teacher),1,fp_teacher);
p=p->next;
}
}
Link search_student(char find_what[],int choice) //按学号或者姓名定位学生,返回结点的指针,choice=1学号查,2姓名查
{
Link p;
if(choice==1)
{
p=head_student->next;
while(p)
{
if(strcmp(find_what,p->num)==0)
return p;
p=p->next;
}
}
else
{
if(choice==2)
{
p=head_student->next;
while(p)
{
if(strcmp(find_what,p->name)==0)
return p;
p=p->next;
}
}
else
wrong();
return NULL;
}
}
struct Teacher *search_teacher(char find_what[],int choice) //按工号或者姓名定位教师,返回结点的指针,choice=1工号查,2姓名查
{
struct Teacher *p;
if(choice==1)
{
p=head_teacher->next;
while(p)
{
if(strcmp(find_what,p->num)==0)
return p;
p=p->next;
}
}
else
{
if(choice==2)
{
p=head_teacher->next;
while(p)
{
if(strcmp(find_what,p->name)==0)
return p;
p=p->next;
}
}
else
wrong();
return NULL;
}
}
void print_grade_header()
{
printf(M" 学号 姓名 语文 数学 英语 C语言 总分 平均分\n");
}
void print_grade(Link p)
{
printf(M PUT_FORMAT,PUT_DATA);
}
void anykey_continue()
{
printf(M"按任意键继续...");
getch();
}
void string_encryption(char *s)
{
int i=0;
while(s[i]!='\0')
{
s[i]+=8;
i++;
}
}
void string_decipher(char *s)
{
int i=0;
while(s[i]!='\0')
{
s[i]-=8;
i++;
}
}
int student_grade_ranking(char *account,int i)
{
struct Student *p=head_student->next;
struct Student *target_pointer=search_student(account,1);
int ranking=1;
while(p)
{
if((p->grade[i])<(target_pointer->grade[i]))
ranking++;
p=p<