由于写的是学生成绩管理系统,需要用结构体来存储学生的各项成绩,当然还有学号 班级 姓名
#define LEN 20
typedef struct student {
char name[LEN];
char num[10];
char theClassName[LEN];
int grade1;
int grade2;
int grade3;
char accountNumber[LEN];//学生账好
char passWord[LEN]; //账户密码
struct student* next;
}STU;
三个界面:
//打印界面 。
//学生
void printSTUScreen() {
printf("\t\t\t\t\t---------------------------------\n");
printf("\t\t\t\t\t|-------学生成绩管理系统--------|\n");
printf("\t\t\t\t\t|-------请输入:0~5之间的数字 --|\n");
printf("\t\t\t\t\t|-------1.查询我的成绩----------|\n");
printf("\t\t\t\t\t|-------2.查询本班成绩----------|\n");
printf("\t\t\t\t\t|-------3.成绩分析--------------|\n");
printf("\t\t\t\t\t|-------4.我要申诉--------------|\n");
printf("\t\t\t\t\t|-------5.返回------------------|\n");
printf("\t\t\t\t\t|-------0.退出系统--------------|\n");
printf("\t\t\t\t\t---------------------------------\n");
}
//老师
void printTEScreen() {
printf("\t\t\t\t\t------------------------------------------\n");
printf("\t\t\t\t\t|-------学生成绩管理系统-----------------|\n");
printf("\t\t\t\t\t|-------请输入:0~9之间的数字 -----------|\n");
printf("\t\t\t\t\t|-------1.增加新的学生信息---------------|\n");
printf("\t\t\t\t\t|-------2.删除学生信息-------------------|\n");
printf("\t\t\t\t\t|-------3.修改学生信息-------------------|\n");
printf("\t\t\t\t\t|-------4.查询学生信息-------------------|\n");
printf("\t\t\t\t\t|-------5.输出本班成绩-------------------|\n");
printf("\t\t\t\t\t|-------6.下载到文件中-------------------|\n");
printf("\t\t\t\t\t|-------7.成绩分析-----------------------|\n");
printf("\t\t\t\t\t|-------8.提醒管理员进行成绩的更新-------|\n");
printf("\t\t\t\t\t|-------9.返回上一层---------------------|\n");
printf("\t\t\t\t\t|-------0.退出系统-----------------------|\n");
printf("\t\t\t\t\t------------------------------------------\n");
}
//管理员
void printADScreen() {
printf("\t\t\t\t\t---------------------------------------\n");
printf("\t\t\t\t\t|-------学生成绩管理系统--------------|\n");
printf("\t\t\t\t\t|-------请输入:0~a之间的数字 --------|\n");
printf("\t\t\t\t\t|-------1.查看代办事项----------------|\n");
printf("\t\t\t\t\t|-------2.进入教师端进行信息修改------|\n");
printf("\t\t\t\t\t|-------3.增加账号及密码--------------|\n");
printf("\t\t\t\t\t|-------4.删除账号及密码--------------|\n");
printf("\t\t\t\t\t|-------5.修改账号及密码--------------|\n");
printf("\t\t\t\t\t|-------6.查找账号及密码--------------|\n");
printf("\t\t\t\t\t|-------7.录入所有账号及密码----------|\n");
printf("\t\t\t\t\t|-------8.输出所有账号级密码----------|\n");
printf("\t\t\t\t\t|-------9.手动重新录入学生信息--------|\n");
printf("\t\t\t\t\t|-------a.返回上一层------------------|\n");
printf("\t\t\t\t\t|-------0.退出系统--------------------|\n");
printf("\t\t\t\t\t---------------------------------------\n");
}
打开文件
FILE* fopen(“文件路径名称”,“模式字符串”);
模式字符串:
r:以读模式打开文件,若文件不存在会报错。
w:以写模式打开文件,若文件已存在则文件原有内容会丢失,若文件不存在,则创建一个新的文件。
a:以写模式打卡文件,不会使原来的数据丢失,会以追加的方式,继续向文件写数据。
其他的模式不常用,这次写系统我也没有用到,略过。
关闭文件
int fclose(FILE* fp);
成功关闭时返回值为0
若未能成功关闭,则返回EOF(-1)
与printf各种方式较为类似,fprintf的第一个参数是文件指针,后面的是格式化列表(与字符串(也可能没有))。
可以用fprintf向文件中输入数据。
feof()是检测流上的文件结束符的函数,如果文件结束,则返回非0值,否则返回0
管理系统要求是有三个界面,应对不同人群:学生,教师,管理员
这里是另外的两种结构体:
//教师账户 。
typedef struct teachers {
char accountNumber[LEN];
char passWord[LEN];
struct teachers* next;
}TE;
//有管理权限的账号 。
typedef struct administrators {
char accountNumber[LEN];
char passWord[LEN];
struct administrators* next;
}AD;
我的思路是用文件来记录账户和密码,程序开始先调用函数把文件中的账户和密码用链表来存储,然后在登录验证时把链表遍历,当找到符合的节点时便登陆成功,遍历完没有找到即登陆失败。
此处再附上登录验证的函数和文件信息录入链表的函数:
//这里是main的一部分代码:
char sn;
printf("a.登录 b.注册\n");
scanf("%c",&sn);
//学生登录
if(sn == 'a') {
start = logOn1(STUlist);
}
//学生账号注册
if(sn == 'b') {
char sacc[LEN],spas[LEN];
printf("注册:\n");
printf("请输入账号:\n");
scanf("%s",&sacc);
getchar();
printf("请输入密码:\n");
scanf("%s",&spas);
getchar();
logIn1(sacc, spas);
}
//登录 。
int logOn1(STU* list) {
char acc1[LEN],pas1[LEN];
printf("登录:\n");
printf("请输入学生账号:\n");
scanf("%s",&acc1);
printf("请输入密码:\n");
scanf("%s",&pas1);
STU* quiry1 = list;
while(quiry1) {
if(strcmp((quiry1 -> accountNumber), acc1) == 0)
{
if(strcmp((quiry1 -> passWord), pas1) == 0) {
printf("登录成功!\n");
return 1;
}
}
quiry1 = quiry1 -> next;
}
printf("输入有误\n");
return 0;
}
遍历链表中的账号密码来判断是否输入了正确的账号密码。
把输入的信息录入文件中保存。
void logIn1(char* accountNumber, char* passWord) {
FILE* fp1 = fopen("C:\\Users\\zds\\Desktop\\.vs\\账户信息1.txt", "a");
fprintf(fp1, "%s ", accountNumber);//这里%s后应有空格
fprintf(fp1, "%s\n", passWord);
int ret = fclose(fp1);
if(ret == 0) {
printf("注册完成。\n");
} else {
printf("文件关闭失败,请重新启动。\n");
exit(1);
}
}
另外的两种结构体对应的登录、注册函数:
void logIn2(char* accountNumber, char* passWord) {
FILE* fp2 = fopen("C:\\Users\\zds\\Desktop\\.vs\\账户信息2.txt", "a");
fprintf(fp2, "%s ", accountNumber);//这里%s后应有空格
fprintf(fp2, "%s\n", passWord);
int ret = fclose(fp2);
if(ret == 0) {
printf("注册完成。\n");
} else {
printf("文件关闭失败,请重新启动。\n");
exit(1);
}
}
void logIn3(char* accountNumber, char* passWord) {
FILE* fp3 = fopen("C:\\Users\\zds\\Desktop\\.vs\\账户信息3.txt", "a");
fprintf(fp3, "%s ", accountNumber);//这里%s后应有空格
fprintf(fp3, "%s\n", passWord);
int ret = fclose(fp3);
if(ret == 0) {
printf("注册完成。\n");
} else {
printf("文件关闭失败,请重新启动。\n");
exit(1);
}
}
登录
//教师登录 。
int logOn2(TE* list) {
char acc2[LEN],pas2[LEN];
printf("登录:\n");
printf("请输入教师账号:\n");
scanf("%s",&acc2);
printf("请输入教师密码:\n");
scanf("%s",&pas2);
TE* quiry2 = list;
while(quiry2) {
if(strcmp((quiry2 -> accountNumber), acc2) == 0)
{
if(strcmp((quiry2 -> passWord), pas2) == 0) {
printf("登录成功!\n");
return 1;
}
}
quiry2 = quiry2 -> next;
}
printf("输入有误\n");
return 0;
}
//管理员登录 。
int logOn3(AD* list) {
char acc3[LEN],pas3[LEN];
printf("登录:\n");
printf("请输入管理员账号:\n");
scanf("%s",&acc3);
printf("请输入密码:\n");
scanf("%s",&pas3);
AD* quiry3 = list;
while(quiry3) {
if(strcmp((quiry3 -> accountNumber), acc3) == 0)
{
if(strcmp((quiry3 -> passWord), pas3) == 0) {
printf("登录成功!\n");
return 1;
}
}
quiry3 = quiry3 -> next;
}
printf("输入有误\n");
return 0;
}
增:
//增加账号及密码
void addAccount1(STU* tail) {
STU* node = (STU*)malloc(sizeof(STU));
node->next=NULL;
printf("输入账号");
scanf("%s", &node->accountNumber);
printf("输入密码");
scanf("%s",&node->passWord);
tail -> next = node;
tail = tail -> next;
}
这里是用的尾插法来增加节点。
删:
// 删除账号
STU* delAccount1(STU* head){
printf("请输入需删除账号:\n");
char delNum[LEN];
scanf("%s", &delNum);
STU* phead = head;
if(strcmp(phead->accountNumber,delNum)==0){
return head -> next;
}
while(phead&&phead->next){
if(strcmp(phead->next->num,delNum)==0){
phead -> next = phead -> next -> next;
}else {
phead = phead -> next;
}
}
return head;
}
改:
STU* modAccount1(STU* head) {
printf("请输入需修改信息的帐号:\n");
char delNum[LEN];
scanf("%s", &delNum);
STU* phead = head;
while(phead) {
if(strcmp(phead->accountNumber, delNum)==0){
printf("输入账号\n");
scanf("%s",&phead->accountNumber);
printf("输入密码\n");
scanf("%s",&phead->passWord);
break;
}
else {
phead = phead->next;
}
}
return head;
}
利用结构体内部的accountNumber来判断节点,也就是说用账号来查找要修改的学生节点。这里使用strcmp()函数来进行判断。当找到节点并修改完成后,直接break跳出,减少无用的循环。
查:
//教师端查找学生信息
void queryGrade(STU* head){
printf("请输入需修改信息的学生的学号:\n");
char delNum[LEN];
scanf("%s", &delNum);
STU* phead = head;
while(phead){
if(strcmp(phead->next->num,delNum)==0){
printf("姓名: 学号: 班级: 成绩1: 成绩2: 成绩3:\n");
printf("%6s %6s %6s %3d %3d %3d\n", phead->name, phead->num, phead->theClassName, phead->grade1, phead->grade2, phead->grade3);
} else {
phead = phead -> next;
}
}
return ;
}
遍历链表来查找学生信息