目录
课设要求
题目:管理信息系统
要求:研究文件型数据库的结构,模拟文件型数据库管理系统,完成部分功能。
技术要求:使用文件操作、链表操作。
功能要求:包含多种形式的增、删、改、查、排序、统计等基本功能。以及简单的菜单控制(1:增、2:查、...)。
至少包含两种不同类型的数据,一种数据存储在一个文件中(即至少2个文件)。主数据文件至少包括100条记录。
程序功能概述
1、直接登录
1)管理员登陆
a增加学生信息
b删除学生信息
c查看全部学生信息
d将学生信息按学号排序
e将学生信息按身份证号排序
f查找学生信息
g更改学生信息
h更改管理员密码
i退出登陆
2)学生登陆
a查询校园卡余额
b查询水卡余额
c校园卡充值
d水卡充值
e查询校园卡历史充值金额
f更改学生密码
g退出登录
3)退出登录
2、注册账号
1)注册管理员账号
2)注册学生账号
3)退出注册
3、注销账号
1)注销管理员账号
2)注销学生账号
3)退出注销
4、退出系统
源代码
预处理
//“文件包含”处理
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
1、包含stdio.h文件主要是为了使用fopen、fclose、scanf、printf等函数;
2、包含stdlib.h文件主要是为了使用malloc等函数;
3、包含string.h文件主要是为了使用strcpy、strcmp等函数;
4、包含windows.h文件主要是为了使用system等函数。
结构体声明
//定义学生信息结构体
typedef struct Student
{
long long id; //学号ID
char ps[20], ID[19]; //密码password,身份证号码ID
int bal[2]; //校园卡余额balance[0],水卡余额balance[1]
int con; //校园卡历史充值金额consumption
struct Student *next, *prior; //分别指向前后两个结点
} stu, *lstu;
//定义管理员信息结构体
typedef struct Administrator
{
long long id; //账号
char ps[20]; //密码
struct Administrator *next, *prior; //分别指向前后两个结点
} adm, *ladm;
1、typedef 不仅方便之后变量的定义,而且对理解代码有一定的帮助。例如:在定义变量方面上,我们可以直接书写stu stud,来定义一个stud变量,而不需要书写struct Student stud,减少了书写量;在理解代码方面上,*stu类型是用来定义一个指向一个结点的指针的,而lstu类型是用来定义一个指向一个链表的指针的。虽然二者实际上做的事情一样,但是对于理解代码有一定的帮助。
2、结构体的声明能够表明我想要创建的链表类型是双链表,因为结构体成员变量中的指针类型变量有两个,一个是指向上一个结点,一个是指向下一个结点。
全局变量定义
//定义两个链表 分别是学生和管理员
lstu ls;
ladm la;
//记录两个链表结点个数
int ns = 0;
int na = 0;
函数声明
//函数的声明
void initial();
void menu1();
void ini1();
stu *search1(long long);
void ini2();
adm *search2(long long);
void menu2();
void admi(adm *);
void del();
void printall();
void sort1();
void sort2();
void cha();
void print();
void menu3(stu *);
void bal1(stu *);
void bal2(stu *);
void rec1(stu *);
void rec2(stu *);
void con1(stu *);
void add1();
void del1();
void save1();
void add0();
void save2();
void chan1(stu *, char *);
void addid();
void delid();
void chan2(adm *, char *);
adm *check1();
stu *check2();
void add2();
void menu4(stu *);
void menu5(adm *);
main函数
//主函数
int main()
{
printf("\t\t\t ZZU\n");
printf("\t\t\t信息初始化中\n\n");
initial();
menu1();
return 0;
}
initial函数
//初始信息的载入函数
void initial()
{
ini1();
ini2();
printf("\t\t\t信息初始化完成!\n");
}
//初始化学生链表
void ini1()
{
FILE *fp;
if ((fp = fopen("student.dat", "r")) == NULL)
{
printf("\t\t\t学生信息初始化失败!\n\n");
exit(0);
}
else
{
//创建一个空链表(带头结点)
ls = (stu *)malloc(sizeof(stu));
if (ls == NULL)
{
printf("\t\t\t学生信息初始化失败!\n\n");
exit(0);
}
else
{
ls->next = NULL;
ls->prior = NULL;
ls->id = -1;
ls->ps[0] = '\0';
}
//初始化学生链表
stu *p0 = ls;
while (1)
{
stu *p;
p = (stu *)malloc(sizeof(stu));
if (p == NULL)
{
printf("\t\t\t学生信息初始化失败!\n\n");
exit(0);
}
else
{
if (EOF == fscanf(fp, "%lld %s %s %d %d %d", &p->id, p->ps, p->ID, &p->bal[0], &p->bal[1], &p->con))
break;
p->next = NULL;
p->prior = NULL;
ns++;
//尾插法
p0->next = p;
p->prior = p0;
p0 = p;
}
}
printf("\t\t\t学生信息初始化成功!\n\n");
}
fclose(fp);
}
//初始化管理员链表
void ini2()
{
FILE *fp;
if ((fp = fopen("admi.dat", "r")) == NULL)
{
printf("\t\t\t管理员信息初始化失败!\n\n");
exit(0);
}
else
{
//创建一个空链表(带头结点)
la = (adm *)malloc(sizeof(adm));
if (la == NULL)
{
printf("\t\t\t管理员信息初始化失败!\n\n");
exit(0);
}
else
{
la->next = NULL;
la->prior = NULL;
la->id = -1;
la->ps[0] = '\0';
}
//初始化管理员链表
adm *p0 = la;
while (1)
{
adm *p;
p = (adm *)malloc(sizeof(adm));
if (p == NULL)
{
printf("\t\t\t管理员信息初始化失败!\n\n");
exit(0);
}
else
{
if (EOF == fscanf(fp, "%lld %s ", &p->id, p->ps))
break;
p->next = NULL;
p->prior = NULL;
na++;
//尾插法
p0->next = p;
p->prior = p0;
p0 = p;
}
}
printf("\t\t\t管理员信息初始化成功!\n\n");
}
fclose(fp);
}
1、因为管理员和学生所包含的信息不同,所以初始化需要两个不同的函数来实现,但是正因为只有所读入的信息个数与格式不同,所以在两个函数中只有读入过程存在差异,其余几乎不变。
2、文件的打开应该以读的方式,并且检验文件是否打开成功;创建并初始化一个空的带有头结点的双链表,并且检验是否创建成功;从相应数据文件中读取数据,并且把数据保存在一个个结点内并插入链表之中;文件读取完毕之后,应该记得关闭文件。
菜单函数
//主目录函数
void menu1()
{
while (1)
{
printf("\n\t\t\t直接登陆请按 1\n");
printf("\t\t\t注册账号请按 2\n");
printf("\t\t\t注销账号请按 3\n");
printf("\t\t\t退出系统请按 0\n\n");
int sign;
scanf("%d", &sign);
switch (sign)
{
case 1:
menu2();
break;
case 2:
addid();
break;
case 3:
delid();
break;
case 0:
system("cls");
break;
default:
printf("\t\t\t请输入0~3!\n\n");
}
if (sign == 0)
break;
system("pause");
system("cls");
}
printf("\n\t\t\t再见!\n\n");
}
//登陆函数目录
void menu2()
{
while (1)
{
printf("\t\t\t管理员登陆请按 1\n");
printf("\t\t\t学生登陆请按 2\n");
printf("\t\t\t退出登陆界面请按 0\n\n");
int sign;
scanf("%d", &sign);
stu *p2;
adm *p1;
switch (sign)
{
case 1:
p1 = check1();
if (p1)
{
printf("\t\t\t登陆成功!\n\n");
admi(p1);
}
else
{
printf("\t\t\t登陆失败!\n\n");
}
break;
case 2:
p2 = check2();
if (p2)
{
printf("\t\t\t登陆成功!\n\n");
menu3(p2);
}
else
{
printf("\t\t\t登陆失败!\n\n");
}
break;
case 0:
system("cls");
break;
default:
printf("\t\t\t请输入0~2!\n\n");
}
if (sign == 0)
break;
system("pause");
system("cls");
}
}
//管理员目录
void admi(adm *p)
{
while (1)
{
printf("\t\t\t增加学生信息请按 1\n");
printf("\t\t\t删除学生信息请按 2\n");
printf("\t\t\t查看全部学生信息请按 3\n");
printf("\t\t\t将学生信息依学号大小排序请按 4\n");
printf("\t\t\t将学生信息依身份证号大小排序请按 5\n");
printf("\t\t\t查找学生信息请按 6\n");
printf("\t\t\t更改学生信息请按 7\n");
printf("\t\t\t更改密码请按 8\n");
printf("\t\t\t退出登陆请按 0\n\n");
int sign;
scanf("%d", &sign);
switch (sign)
{
case 1:
add0();
break;
case 2:
del();
break;
case 3:
printall();
break;
case 4:
sort1();
break;
case 5:
sort2();
break;
case 6:
print();
break;
case 7:
cha();
break;
case 8:
menu5(p);
break;
case 0:
system("cls");
break;
default:
printf("\t\t\t请输入0~6!\n\n");
}
if (sign == 0)
break;
system("pause");
system("cls");
}
}
//学生目录
void menu3(stu *p)
{
while (1)
{
printf("\t\t\t查询校园卡余额请按 1\n");
printf("\t\t\t查询水卡余额请按 2\n");
printf("\t\t\t校园卡充值请按 3\n");
printf("\t\t\t水卡充值请按 4\n");
printf("\t\t\t查询历史校园卡充值金额请按 5\n");
printf("\t\t\t更改密码请按 6\n");
printf("\t\t\t退出登陆请按 0\n\n");
int sign;
scanf("%d", &sign);
switch (sign)
{
case 1:
bal1(p);
break;
case 2:
bal2(p);
break;
case 3:
rec2(p);
break;
case 4:
rec1(p);
break;
case 5:
con1(p);
break;
case 6:
menu4(p);
break;
case 0:
system("cls");
break;
default:
printf("\t\t\t请输入0~5!\n\n");
}
if (sign == 0)
break;
system("pause");
system("cls");
}
}
//注册账号函数
void addid()
{
while (1)
{
printf("\t\t\t注册管理员账号请按 1\n");
printf("\t\t\t注册学生账号请按 2\n");
printf("\t\t\t退出注册请按 0\n\n");
int sign;
scanf("%d", &sign);
switch (sign)
{
case 1:
add1();
break;
case 2:
add2();
break;
case 0:
system("cls");
break;
default:
printf("\t\t\t请输入0~2!\n\n");
}
if (sign == 0)
break;
system("pause");
system("cls");
}
}
//注销账号函数
void delid()
{
while (1)
{
printf("\t\t\t注销管理员账号请按 1\n");
printf("\t\t\t注销学生账号请按 2\n");
printf("\t\t\t退出注销请按 0\n\n");
int sign;
scanf("%d", &sign);
switch (sign)
{
case 1:
del1();
break;
case 2:
del();
break;
case 0:
break;
default:
printf("\t\t\t请输入0~2!\n\n");
}
if (sign == 0)
break;
system("pause");
system("cls");
}
}
1、菜单函数的统一构架:while函数里面加上switch-case
登陆功能
//管理员登陆验证函数
adm *check1()
{
printf("\t\t\t请分别输入账号和密码\n");
printf("\t\t\t(两者以空格分开)\n\n");
long long id;
char ps[20];
scanf("%lld %s", &id, ps);
adm *p = search2(id);
if (p == NULL)
{
printf("\t\t\t该账号还未注册!请先注册账号!\n\n");
return NULL;
}
else
{
int flag = strcmp(p->ps, ps);
if (flag == 0)
return p;
else
{
printf("\t\t\t密码错误!\n\n");
return NULL;
}
}
}
//学生登陆验证函数
stu *check2()
{
printf("\t\t\t请分别输入学号和密码\n");
printf("\t\t\t(两者以空格分开)\n\n");
long long id;
char ps[20];
scanf("%lld %s", &id, ps);
stu *p = search1(id);
if (p == NULL)
{
printf("\t\t\t该账号还未注册!请先注册账号!\n\n");
return NULL;
}
else
{
int flag = strcmp(p->ps, ps);
if (flag == 0)
return p;
else
{
printf("\t\t\t密码错误!\n\n");
return NULL;
}
}
}