C语言文件实现学生成绩管理

时间:2022-06-07 08:12:41

C语言实现学生成绩管理

  • 项目简介

用C语言的链表及文件操作实现学生成绩的管理,实现主要的添加、修改、删除、查询的主要功能,并在程序关闭时将数据存储在二进制的文件中并加密。下一次打开程序,先解密二进制文件,然后将数据读入内存,再允许用户的操作。

  • 程序简示图

C语言文件实现学生成绩管理

  • 功能介绍

1. 加密数据:

程序结束时,现将生成的链表,写入二进制的临时文Temp.dat,再运用加密函数,将Temp.dat加密到文件Data.dat(就相当于数据库),并删除文件Temp.dat。程序开始运行时,先获取文件Data.dat的文件,并判断是数据,如果前两者之一的条件不满足则进入上图所示的添加数据并生成链表。如果获取到文件并且有数据,则解密到临时文件并将其读入到内存并生成链表。

2.加密算法:

加密算法采用简单XOR算法,也就是异或运算。利用了一个数与其自身相异或的到0,而与0异或也得到其本身。

  如b为原文,a为加密后的密文,c代表密码,则

 加密:
a=b^c; 解密
a^c=>b^c^c=>b

具体的该程序的加密,因为是对二进制文件加密,采用的是先将数据写入临时文件Temp.dat,再将其数据以一个一个字节读出加密,然后依次读入到文件Data.dat完成加密。

 #define KEY 0x85

 void secretFile(char *srcfile,char *dstfile){
FILE *fp1,*fp2; if((fp1=fopen(srcfile,"rb"))==NULL){ //获取被加密文件指针
return ;
} if((fp2=fopen(dstfile,"wb"))==NULL){ //获取加密文件指针
return;
} fseek(fp1,,SEEK_END);
int length=ftell(fp1); //获取文件的长度 fseek(fp1,,SEEK_SET); char *p=(char *)malloc(sizeof(char)*length);
fread(p,sizeof(char),length,fp1);//将文件数据读入p所指内存空间 for(int i=;i<length;i++){
p[i]^=KEY;
} //异或加密 fwrite(p,sizeof(char),length,fp2);//将加密后的数据读入目标文件 fclose(fp1);
fclose(fp2);
}
调用加密函数
 void jiemi(){        //解密
FILE *fp;
if((fp=fopen("Temp.dat","wb"))==NULL){
return;
} //生成临时文件
fclose(fp);
secretFile("Data.dat","Temp.dat"); //解密到临时文件
} void jiami(){ //加密
FILE *fp;
if((fp=fopen("Data.dat","wb"))==NULL){
return;
}
fclose(fp);
secretFile("Temp.dat","Data.dat"); //加密到目标文件
remove("Temp.dat"); //删除临时文件
}

执行后的二进制文件用WinHEX查看:

加密前的文件:

C语言文件实现学生成绩管理

加密后的文件:

C语言文件实现学生成绩管理

在具体的代码为了安全,生成加密文件Data.dat会删除临时文件Temp.dat,更安全的应该是由用户输入KEY值加密,然后输入KEY解密,就相当于文件的密码。这里定义宏写入了KEY的值。

3.写入、读取文件

读取Temp.dat的文件生成链表,返回头指针

 struct student *readData(){
jiemi(); //调用解密,生成解密后的文件Temp.dat struct student *head,*q,*p;
head=q=NULL;
int i=;
FILE *fp;
if((fp=fopen("Temp.dat","rb"))==NULL){
printf("打开文件 Temp.dat 失败\n");
}
//获取文件指针 fseek(fp,,SEEK_END);
int length=ftell(fp)/(sizeof(struct student));
//获取文件长度,确定链表的长度
fseek(fp,,SEEK_SET); while(i<length){ p=(struct student*)malloc(sizeof(struct student)); fread(p,sizeof(struct student),,fp); //读数据到p if(head==NULL){ //生成头结点
head=q=p;
}else{
q->next=p; //在尾节点添加数据
q=p;
}
i++;
}
q->next=NULL; //尾节点置为空
fclose(fp);
return head; }

将内存中的链表存储到文件

 void storeData(struct student *head){
struct student *q;
FILE *fp;
if((fp=fopen("Temp.dat","wb"))==NULL){
printf("打开文件 Temp.dat 失败\n");
return;
} //获取文件指针
for(q=head;q!=NULL;q=q->next){ fwrite(q,sizeof(struct student),,fp); //将链表上的节点依次写入文件
}
fclose(fp);
printf("存储数据成功");
}

具体代码:

头文件head.h:

 #include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h> #define KEY 0x85 //定义加密字符串 struct student{
char id[]; //学号
char name[]; //姓名
int math; //数学成绩
int english; //英语成绩
struct student *next;
}; //学生结构体 void secretFile(char *srcfile,char *dstfile);//加密函数
void jiemi(); //解密
void jiami(); //加密
bool isData(struct student *head,char tmp[]);//是否存在该节点
struct student* creatLink();//生成链表
struct student* findLink(struct student *head,char id[]);//查找节点
void infoDisplay(struct student *head);//查看所有节点信息
void chaxun(struct student *head);//查询学生信息
struct student* tianjia(struct student *head);//添加学生
struct student* deleteLink(struct student *head);//删除学生
struct student* xiugai(struct student *head);//修改学生信息
bool isFile(char filename[]);//判断是否存在文件
void storeData(struct student *head);//存储数据到文件
struct student *readData();//读入数据生成链表
33 void freeLink(struct sutdent *head);//释放链表

主函数main.cpp:

 #include"head.h"

 void menu(){
struct student *head=NULL;
system("cls");
if(false==isFile("Data.dat")){
printf("第一次进入:请先添加数据:\n");
head=creatLink(); } else{
head=readData(); }
int iSelect=;
while(iSelect!=){
system("cls");
printf("请输入选项:\n");
printf("1.查询成绩 2.添加成绩 3.删除成绩 4.修改成绩 5.数据一览 6.退出\n");
scanf("%d",&iSelect);
switch(iSelect){
case :chaxun(head);break;
case :head=deleteLink(head);break;
case :head=tianjia(head);break;
case :head=xiugai(head);break;
case :infoDisplay(head);break;
case :storeData(head);freeLink(head);jiami();system("pause");break;
default:printf("\n输入错误请重新输入:");system("pause");break;
}
}
} int main(){
menu();
return ;
}

具体函数function.cpp:

 #include"head.h"

 void freeLink(struct student *head){
struct student *p,*q;
p=head;
while(p!=NULL){
q=p;
p=p->next;
free(q);
}
} void secretFile(char *srcfile,char *dstfile){
FILE *fp1,*fp2;
if((fp1=fopen(srcfile,"rb"))==NULL){
return ;
}
if((fp2=fopen(dstfile,"wb"))==NULL){
return;
}
fseek(fp1,,SEEK_END);
int length=ftell(fp1);
fseek(fp1,,SEEK_SET);
char *p=(char *)malloc(sizeof(char)*length);
fread(p,sizeof(char),length,fp1);
for(int i=;i<length;i++){
p[i]^=KEY;
}
fwrite(p,sizeof(char),length,fp2);
fclose(fp1);
fclose(fp2);
} void jiemi(){
FILE *fp;
if((fp=fopen("Temp.dat","wb"))==NULL){
return;
}
fclose(fp);
secretFile("Data.dat","Temp.dat");
} void jiami(){
FILE *fp;
if((fp=fopen("Data.dat","wb"))==NULL){
return;
}
fclose(fp);
secretFile("Temp.dat","Data.dat");
remove("Temp.dat");
} bool isData(struct student *head,char tmp[]){
struct student *q;
printf("flag\n");
for(q=head;q!=NULL;q=q->next){
if(strcmp(tmp,q->id)==){
return true;
}
} return false;
} //创建链表
struct student* creatLink(){
struct student *head,*q,*p;
head=q=NULL;
char id[];
int i=; head=q=NULL;
while(){
printf("(#结束输入)\n请输入学号:");
scanf("%s",id);
if(strcmp("#",id)==){
break;
}
p=(struct student*)malloc(sizeof(struct student));
strcpy(p->id,id); fflush(stdin);
printf("请输入姓名:");
scanf("%s",p->name); fflush(stdin);
printf("请输入数学成绩:");
scanf("%d",&(p->math)); fflush(stdin);
printf("请输入英语成绩:");
scanf("%d",&(p->english));
if(head==NULL){
head=q=p;
q->next=NULL;
}else{
if(isData(head,p->id)==true){
printf("已经存在该学生,该次数据无效\n");
}
else{
q->next=p;
q=p;
q->next=NULL;
}
}
}
q->next=NULL;
return head;
} struct student* findLink(struct student *head,char id[]){
struct student *p;
for(p=head;p!=NULL;p=p->next){
if(strcmp(id,p->id)==)break;
}
if(p!=NULL){
return p;
}
return NULL;
} void infoDisplay(struct student *head){
struct student *p;
system("cls");
printf("学号\t姓名\t英语\t数学\n");
for(p=head;p!=NULL;p=p->next){
printf("%s\t%s\t%d\t%d\n",p->id,p->name,p->english,p->math);
}
system("pause");
} void chaxun(struct student *head){
char temp[];
system("cls");
fflush(stdin);
printf("请输入要查询学生的学号:");
scanf("%s",temp);
struct student *p;
for(p=head;p!=NULL;p=p->next){
if(strcmp(temp,p->id)==)break;
}
if(p!=NULL){
printf("学号\t姓名\t英语\t数学\n");
printf("%s\t%s\t%d\t%d\n",p->id,p->name,p->english,p->math);
}else{
printf("没有查到学生\n");
}
system("pause");
} struct student* tianjia(struct student *head){
struct student *add=(struct student*)malloc(sizeof(struct student));
struct student *p=NULL,*q=NULL;
system("cls");
fflush(stdin);
printf("请输入学号:");
scanf("%s",add->id); fflush(stdin);
printf("请输入姓名:");
scanf("%s",add->name); fflush(stdin);
printf("请输入英语成绩:");
scanf("%d",&(add->english)); fflush(stdin);
printf("请输入数学成绩:");
scanf("%d",&(add->math)); for(q=head;q!=NULL;q=q->next){
if(strcmp(add->id,q->id)==)
{
printf("已存在该学生,此次输入无效");
break;
}
}
if(q==NULL){
add->next=head;
head=add;
printf("添加数据成功\n");
} system("pause");
return head;
} //删除链表节点
struct student* deleteLink(struct student *head){
struct student *p,*q;
char tmp[];
system("cls"); fflush(stdin);
printf("请输入要删除学生的学号:\n");
scanf("%s",tmp); for(p=head,q=NULL;p!=NULL;q=p,p=p->next){
if(strcmp(tmp,p->id)==)break;
}
if(p!=NULL){
if(q==NULL){
head=p->next;
}else{
q->next=p->next; } free(p);
}
printf("删除成功");
system("pause");
return head;
} struct student* xiugai(struct student *head){
char tmp[];
struct student *q;
system("cls"); fflush(stdin);
printf("请输入要修改学生的学号:");
scanf("%s",tmp); for(q=head;q!=NULL;q=q->next){
if(strcmp(q->id,tmp)==){
break;
}
} if(q==NULL){
printf("修改失败,不存在该学生\n");
}else{ fflush(stdin);
printf("请输入姓名:");
scanf("%s",q->name); fflush(stdin);
printf("请输入英语成绩:");
scanf("%d",&(q->english)); fflush(stdin);
printf("请输入数学成绩:");
scanf("%d",&(q->math)); printf("修改成功\n");
} system("pause");
return head;
}
bool isFile(char filename[]){
FILE *fp;
if((fp=fopen(filename,"rb"))==NULL){ return false;
}
fseek(fp,,SEEK_END);
int length=ftell(fp)/(sizeof(struct student));
if(length<){
return false;
}
fclose(fp);
return true;
} void storeData(struct student *head){
struct student *q;
FILE *fp;
if((fp=fopen("Temp.dat","wb"))==NULL){
printf("打开文件 Temp.dat 失败\n");
}
for(q=head;q!=NULL;q=q->next){ fwrite(q,sizeof(struct student),,fp);
} fclose(fp);
printf("存储数据成功");
} struct student *readData(){
jiemi();
struct student *head,*q,*p;
head=q=NULL;
int i=;
FILE *fp;
if((fp=fopen("Temp.dat","rb"))==NULL){
printf("打开文件 Temp.dat 失败\n");
}fseek(fp,,SEEK_END);
int length=ftell(fp)/(sizeof(struct student));
fseek(fp,,SEEK_SET);
while(i<length){ p=(struct student*)malloc(sizeof(struct student)); fread(p,sizeof(struct student),,fp); if(head==NULL){
head=q=p;
}else{
q->next=p;
q=p;
}
i++;
}
q->next=NULL;
fclose(fp);
return head; }

运行截图:

C语言文件实现学生成绩管理

存在的不足:

该程序还存在许多不足,比如说很多出错处理没有处理,比如所要求输入整形时输入字符型,输入超过范围的处理等。程序在处理数据比较小的时候较好,但如果处理数据过大就不是很适用。界面比较简单。