设计目的
实现将用户分为 学生 老师 管理者 三部分
老师和学生是两个独立的个体只能使用自身的权限
一、 老师权限:自身的信息、自身的课程查询、课程的申请。 二、 学生权限:自身的信息、成绩查询,选课。
管理者拥有更改的权限可以管理老师和学生
三、 管理者权限:学生信息、老师信息、添加老师、添加学生、信息的查询。
编写之中的难点
多文件编程
使用数组指针
使用了外部的文件来存储用户的信息
整体的逻辑关系
编程内容
希望可以耐心看完
一、"main.cpp"运行文件——此文件进行最后的运行,因所包含的头文件已经完成了主程序的编写,所以使得此运行文件异常的简洁。
#include "Constants.h" #include "Manager.h" int main(){ //欢迎界面 welcome(); login(); return 0; }
二、"constants.h"头文件之一
此头文件之中大量的使用了结构体来编写学生和老师的信息。
使用了"pragma once"宏定义——作用是:防止编程之中对头文件的多次使用,用于想要防止被多次使用的头文件的开始,而且一旦被多次使用系统就会忽略随后的使用来避免发生错误。
#pragma once #include
//定义常量和结构体 多个地方需要用到 //年级 typedef enum { GradeOne, //大一 GradeTwo, //大二 GradeThree, //大三 GradeFour //大四 }Grade; //学生 typedef struct student { char s_id[15]; //学生学号 Grade s_grade; //学生年级 char s_name[20]; //学生姓名 char s_pwd[6]; //学生密码 int age; //学生年龄 char s_addr[40]; //学生地址 char *c_ids[15]; //上课课程id组成的数组 } Student; //老师 typedef struct teacher { char t_id[15]; //教师工号 char t_name[20]; //教师姓名 char t_pwd[6]; //教师密码 int age; //教师年龄 char t_addr[40]; //教师地址 char *c_ids[15]; //教授课程id组成的数组 } Teacher; //管理员 typedef struct admin{ char a_name[20]; //管理员姓名 char a_pwd[6]; //管理员密码 }Admin; //课程 typedef struct course { char c_id[15]; //课程id char c_name[20]; //课程名称 Grade c_grade; //课程年级要求 char t_id[15]; //任何老师id } Course; //用户类型 typedef enum { UserTypeNone, //没有身份 UserTypeStudent, //学生 UserTypeTeacher, //老师 UserTypeAdmin //管理员 }UserType; //用户的结构体 typedef struct user { char name[20]; //用户名 char pwd[7]; //用户密码 UserType type; //用户类型 char details[50]; //文件名 } User; //保存用户信息的文件的完整路径 #define USER_INFO_PATH "users.txt"
三"manager.cpp"源文件之一用于实现主要的程序编写,后使用其头文件放入到运行文件之中,使得运行和编写更加的简便和整洁。
#include "Manager.h" #include "FileOperation.h" #include
//菜单信息 char *s_menu[] = {"个人信息","成绩查询","选课","退出"}; char *t_menu[] = {"个人信息","课程查询","申请课程","退出"}; char *a_menu[] = {"学生信息","老师信息","添加学生","添加老师","信息查询","退出"}; //全局化 查出来的用户 User global_user = {}; //选择操作 int choice (int max){ int num; while(1){ printf("请选择操作:"); scanf("%d",&num); if(num <= max && num >=1){ return num; } else{ printf("输入不合法\n"); } } } //显示学生的详细信息 void showStudentDetail(Student s){ printf("id:%s\n",s.s_id); printf("name:%s\n",s.s_name); printf("age:%d\n",s.age); printf("addr:%s\n",s.s_addr); if(s.s_grade == GradeOne){ printf("grade:大一\n"); }else if(s.s_grade == GradeTwo){ printf("grade:大二\n"); } else if(s.s_grade == GradeThree){ printf("grade:大三\n"); } else{ printf("grade:大四\n"); } } //显示老师的详细信息 void showTeacherDetail(Teacher t){ printf("id:%s\n",t.t_id); printf("name:%s\n",t.t_name); printf("age:%d\n",t.age); printf("pwd:%s\n",t.t_pwd); printf("addr:%s\n",t.t_addr); } //按任意键继续 void pressToContinue(){ fflush(stdin); printf("按任意键继续"); getchar(); } //处理学生的选择 void detailStudentChoice(int result){ //把学生的详细信息读取出来 Student s = {}; loadDetail(&s,global_user); switch (result){ case 1: //个人信息 showStudentDetail(s); break; case 2: //成绩查询 break; case 3: //选课 break; case 4: //退出 break; } pressToContinue(); } //处理老师的选择 void detailTeacherChoice(int result){ //把老师的详细信息读取出来 Teacher t = {}; loadDetail(&t,global_user); switch (result){ case 1: //个人信息 showTeacherDetail(t); break; case 2: //课程查询 break; case 3: //申请课程 break; case 4: //退出 break; } pressToContinue(); } //处理管理员的选择 void detailAdminChoice(int result){ switch (result){ case 1: //学生信息 break; case 2: //老师信息 break; case 3: //添加学生 break; case 4: //添加老师 break; case 5: //信息查询 break; case 6: //退出 break; } pressToContinue(); } int count = 0; int result = 0; switch(type){ case UserTypeStudent: count = sizeof(s_menu)/sizeof(char *); while(1){ //显示菜单 show_Menu_Detail(s_menu,count); //输入操作 result = choice(count); //处理选择 detailStudentChoice(result); } break; case UserTypeTeacher: count = sizeof(t_menu)/sizeof(char *); while(1){ //显示菜单 show_Menu_Detail(t_menu,count); //输入操作 result = choice(count); //处理选择 detailTeacherChoice(result); } break; case UserTypeAdmin: count = sizeof(a_menu)/sizeof(char *); while(1){ //显示菜单 show_Menu_Detail(a_menu,count); //输入操作 result = choice(count); //处理选择 detailAdminChoice(result); } break; } } //显示菜单详情 char **array void show_Menu_Detail(char *array[],int count){ printf("**************************\n"); int i; for(i = 0;i < count;i++){ printf("%d.%s\n",i+1,array[i]); } printf("**************************\n"); } //欢迎界面 void welcome(){ printf("************************\n"); printf(" 欢迎使用学生管理系统 \n"); printf("************************\n"); } //添加用户 void add_User(void *pUser,UserType type){ //1.创建这个用户对应的User结构体 User user; //泛型->强制转化 if(type == UserTypeStudent){ Student *stu = (Student *)pUser; strcpy(user.name,stu->s_name); strcpy(user.pwd,stu->s_pwd); user.type = UserTypeStudent; }else if(type == UserTypeTeacher){ Teacher *tea = (Teacher *)pUser; strcpy(user.name,tea->t_name); strcpy(user.pwd,tea->t_pwd); user.type = UserTypeTeacher; }else{ } //2.创建文件保存这个用户的详细信息 //拼接用户对应的详细信息的文件名 sprintf(user.details,"%s.txt",user.name); //保存用户信息 save(user); //保存具体的信息 if(type != UserTypeAdmin){ save_Detail(pUser,type); } } //登录界面 void login(){ printf("请输入用户名:"); scanf("%s",global_user.name); //fflush(stdin); printf("请输入密码:"); scanf("%s",global_user.pwd); /** **1.从文件里面依次读取一个用户信息 作比较 **2.先将所有的用户读取出来用数组保存 再去遍历 **3.将所有的老师形成一个链表 将所有的学生形成一个链表 将所有的管理员形成一个链表 ** */ //用户查询 bool result = select(&global_user); if(result == true){ printf("登陆成功!!!\n"); //显示菜单 show_Menu(global_user.type); } else{ if (global_user.type != UserTypeNone) { printf("密码错误!!!\n"); }else{ printf("用户不存在\n"); } } }
-
"magaer.h"头文件之一
#pragma once
#include "Constants.h"
//欢迎界面
void welcome();
//添加用户
void add_User(void *pUser,UserType type);
//用户登录界面
void login();
//展示菜单
void show_Menu(UserType type);
-
"fileoperation.cpp"源文件之一——用于对外部文件的操作。
-
"注意对外部文件的读取和关闭的方法。
#include "stdlib.h"
#include "string.h"
//保存数据
void save(User user){
//打开文件
FILE *fp = fopen(USER_INFO_PATH,"a+");
//判断是否打开成功
if(fp == NULL){
printf("打开文件出错\n");
exit(EXIT_FAILURE);
}
//保存数据
fwrite(&user,sizeof(User),1,fp);
//关闭文件,释放占用的文件指针
fclose(fp);
}
//打开文件
FILE *open(char *path,char *mode){
//打开文件
FILE *fp = fopen(path,mode);
//判断是否打开成功
if(fp == NULL){
printf("打开文件出错\n");
perror("fopen");
exit(EXIT_FAILURE);
}
return fp;
}
//读取数据
User load(FILE *fp){
//读取数据
User temp;
fread(&temp,sizeof(User),1,fp);
//关闭文件,释放占用的文件指针
//fclose(fp);
return temp;
}
//查询用户
//1.不存在
//2.存在 - > 完整信息
//3.存在,密码不正确 -> 不给完整信息
bool select(User *pUser){
//打开文件
FILE *fp = open(USER_INFO_PATH,"r");
while(1){
//从文件加载一个用户信息
User temp = load(fp);
printf("查询中...\n");
//判断用户是否有效
if(temp.type == UserTypeNone) {
//没有找到该用户
fclose(fp);
return false;
}else{
//比较用户名和密码
if(strcmp(temp.name,pUser->name) == 0){
//存在 保存类型
pUser->type = temp.type;
//比较密码
if(strcmp(temp.pwd,pUser->pwd) == 0){
//登陆成功
strcpy(pUser->details,temp.details);
fclose(fp);
return true;
}else{
//用户名正确,密码不正确
fclose(fp);
return false;
}
}
}
}
}
//保存学生,老师,管理员信息
void save_Detail(void *pUser,UserType type){
//拼接用户对应的详细信息的文件名
char file_name[20];
//不能使用char *file_name; 会出现诡异的错误,使用的话,必须打印 上一次 sprintf拼接的结果
//不然这一次拼接会出错
//记录类型大小
size_t size;
//泛型->强制转化
if(type == UserTypeStudent){
Student *stu = (Student *)pUser;
sprintf(file_name,"%s.txt",stu->s_name);
//printf("%s",stu->s_name);
//printf("%s",file_name);
size = sizeof(Student);
}else if(type == UserTypeTeacher){
Teacher *tea = (Teacher *)pUser;
sprintf(file_name,"%s.txt",tea->t_name);
size = sizeof(Teacher);
}else{
}
//printf("%s",file_name);
//打开文件
FILE *fp = open(file_name,"w");
//写入数据
fwrite(pUser,size,1,fp);
//关闭文件,释放占用的文件指针
fclose(fp);
}
//读取数据(学生,老师)
void loadDetail(void *pUser,User user){
//打开文件
FILE *fp = open(user.details,"r");
//泛型->强制转化
if(user.type == UserTypeStudent){
Student *stu = (Student *)pUser;
fread(stu,sizeof(Student),1,fp);
}else if(user.type == UserTypeTeacher){
Teacher *tea = (Teacher *)pUser;
fread(tea,sizeof(Teacher),1,fp);
}else{
}
fclose(fp);
}
-
"fileoperation.h"头文件之一。
#pragma once
#include "Constants.h"
#include
//保存数据
void save(User user);
//保存学生,老师,管理员信息
void saveDetail(void *pUser,UserType type);
//读取数据
User load();
//查询用户
bool select(User *pUser);
//读取数据(学生,老师)
void loadDetail(void *pUser,User user);
这已经是我第二遍写了,上一遍写完不知是怎么回事,就是全部的内容都不见了,我的心态当时瞬间爆炸,所以这一遍的内容有一点水,就凑合着看吧,谢谢!