图书信息管理系统
如何做一个图书管理系统
首先做一个图书管理系统,你要知道它有什么功能,比如
它有3个登录的方式:
- 超级管理员登录
- 普通管理员登录
- 读者登录
有自己各自的登录方式
然后分别有自己的登录界面的功能选项 供不同的使用者使用
磨刀不误砍柴工,你先在脑海中或者在纸上构思一下有什么功能要实现,
实现大概需要一个什么样的过程,大概需要一个什么样子的结构、变量
比如:
- 每一次程序的启动 退出都要用文件操作来实现读取和保存功能。
- 每个登录界面至少都要有返回的功能。
- 一般数据都是要保存在动态内存之中的。
- 每个用户都要有一些人性化的功能 比如修改自己用户密码、名称等等。
- 借阅 预约可以多本书,要提醒读者及时借阅
- 写函数的时候要严谨,一些基本的问题要考虑周到 比如书的数量要足够、归还余额要足够等等
然后写完功能记得要试验一下是否成功 不然可能最后运行的时候错误行数比代码行数还多。
1.基础_变量的声明,基本框架
构思完大概要怎么写之后先来写一点需要的变量和结构 取名字要注意 不要随便取!
- 先写3个登录者和图书的可能要用到的变量;
basicInfo_.h中先写入
//图书信息结构体
typedef struct Book
{
int id; //书号
char name[NAME_LEN]; //书名
double price; //价格
int bortimes; //借阅次数
int have; //现在拥有数量
int appnum; //已经被预约的数量
int appoint[APPBK]; //预约图书 记录读者编号
}Bk;
//读者信息结构体
typedef struct Readers
{
int id; //读者编号
char user[LOLEN]; //读者用户
char pass[LOLEN]; //读者密码
char name[NAME_LEN];//读者姓名
int bornum; //已经借阅的数量
int borbook[BORBK]; //正在借阅的书籍 记录书号
int time[BORBK]; //记录借书的时间
double money; //余额
int appoin_num; //记录预约的书号
}Red;
//管理员信息结构体
typedef struct Admin
{
int id; //管理员编号
char user[LOLEN]; //管理员用户
char pass[LOLEN]; //管理员密码
char name[NAME_LEN];//管理员姓名
}Admin;
//超级管理员信息结构体
typedef struct Superadmin
{
char user[LOLEN]; //超级管理员用户
char pass[LOLEN]; //超级管理员密码
}Suadmin;
- 然后需要一个界面文件和一个进行动态内存操作的文件(把数据存储到动态内存之中)
创建一个view.h view.c通过run()函数 使main.c运行。
run()函数中进行各种界面显示逻辑的处理。
main.c:
#include"view.h"
int main()
{
run();
}
- 文件操作需要一个文件来进行开始和最后的读取保存(超级管理员可以先设置一个账号密码 保存之后,注释掉超级管理员账号密码的那段代码)
文件操作的时候想到一些问题
加载的时候 图书编号需要读取一下 因为增加图书 要++ 不设置的话就是一开始设置好的值比如(id=0)
启动一次 图书编号就会从0开始。
所以fread(&Bk_id,4,1,fp);记得加上
然后要在
basicInfo.h中声明 extern int Bk_id;//图书编号 自动增加
main.c文件中中定义 int Bk_id= 0;
#include"file.h"
#include<unistd.h>
//从图书文件加载到内存中
int load_Bk(const char *path)
{
if(path == NULL)
{
return PATH_ERR;
}
if(access(path,F_OK)!=0)
{
return FILE_NOT_EXISTS;
}
FILE *fp = fopen(path,"r");
if(fp == NULL)
{
return OPEN_ERR;
}
fread(&Bk_id,4,1,fp);
Bk s = {
};
while(fread(&s,SIZE_BK,1,fp)>0)
{
int ret = addBk(&s);
if(ret != SUCCESS)
{
fclose(fp);
return ret;
}
// printf("ret:%d\n",ret);
}
fclose(fp);
return SUCCESS;
}
//把内存中的数据储存到图书文件中
int save_Bk(const char *path)
{
if(path == NULL)
{
return ARG_ERR;
}
FILE *fp = fopen(path,"w");
if(fp == NULL)
{
return OPEN_ERR;
}
fwrite(&Bk_id,4,1,fp);
if(fwrite(pbk,SIZE_BK,Bcnt,fp)<Bcnt)
{
fclose(fp);
return WRITE_ERR;
}
fclose(fp);
return SUCCESS;
}
- 然后是动态内存的问题,动态内存就是要讲数据添加、删除、和找到这个整个结构体的地址
所以在oper.c文件中需要增加以下代码:
basicInfo.h中声明:
extern Bk *pbk;//用于记录储存书籍信息的指针 需要申请动态内存
extern size_t Bsize;//申请动态内存能够存储书籍信息的数量
extern size_t Bcnt;//当前动态内存中书籍信息的数量
#define SIZE_BK sizeof(Bk) //记录Bk的长度
main.c中定义:
Bk *pbk = NULL; //用于记录储存书籍信息的指针 需要申请动态内存
size_t Bsize = 10; //申请动态内存能够存储书籍信息的数量
size_t Bcnt = 0; //当前动态内存中书籍信息的数量
为了能够快速正确的知道输出错误的地点 可以选择在basicInfo.h中增加一个枚举来快速查看错误的位置
enum CODE_STATE //如果出现异常 返回异常结果的 枚举
{
SUCCESS = 0,
PATH_ERR,
ARG_ERR,
ALLOC_ERR,
OPEN_ERR,
FILE_NOT_EXISTS,
WRITE_ERR,
FAIL,
NOT_CHAR,
};
#include"oper.h"
//申请动态内存 把获取到的图书结构体存储到动态内存中
int addBk(Bk *Bps)
{
if(Bps == NULL)
{
return ARG_ERR;
}
if(pbk == NULL)
{
pbk = malloc(SIZE_BK*Bsize);
}
if(pbk != NULL && Bsize == Bcnt)
{
Bsize = 2*Bsize;
pbk = realloc(pbk,SIZE_BK*Bsize);
}
if(pbk == NULL)
{
return ALLOC_ERR;
}
pbk[Bcnt] = *Bps;
++Bcnt;
return SUCCESS;
}
//通过获取到图书的id号 删除动态内存中相应的结构体
int delBk(int id)
{
size_t i;
for(i=0;i<Bcnt;i++)
{
if(pbk[i].id == id)
{
pbk[i] = pbk[Bcnt-1];
--Bcnt;
// printf("Bcnt:123");
return SUCCESS;
}
}
return FAIL;
}
//通过获取到的图书的id号 读取动态内存中的结构体
Bk* findBk(int id)
{
size_t i;
for(i=0;i<Bcnt;i++)
{
if(pbk[i].id == id)
{
return pbk + i;
}
}
return NULL;
}
2.各种功能的实现
进行好头文件的添加,头文件要记得添加头文件卫士 要在外部使用的函数记得声明
然后在main.c中随便创建一个结构体例子进行试验 可以就进行下一步。
好了各种基本的东西都已经完成了,现在开始进行界面的设计 和 实现
在view.c文件中需要什么功能就写什么功能 然后在basicInfo.h中补上各种声明
在main.c文件中补上各种定义
接下来就是逻辑问题了如:
写上菜单显示的各种功能(只是一部分 全代码在下面)
把各种登录类型上实现的功能写在其他的文件中 加上头文件
写的时候记得加上注释!
这个程序还不够严谨 应该多加一些判断!
view.c:
#include"view.h"
#include"file.h"
#include"Suadmin_oper.h"
#include"Admin_oper.h"
#include"Read_oper.h"
enum login_{
Su_=1,Admin_,Reader_};//登陆用户的枚举
//开始 选择用户登陆界面
void startMenu()
{
printf("\n欢迎使用图书信息管理系统!\n");
printf("请选择你想要登陆的用户类型!\n");
printf("1.超级管理员\n");
printf("2.普通管理员\n");
printf("3.读者\n");
}
//超级管理员 帐号密码登陆
void SuadminLogin()
{
printf("\n请输入你的帐号和密码!\n");
char user_[10] = {
};
char pass_[10] = {
};
int i ;
for(i=0;i<3;i++)
{
scanf("%s%s",user_,pass_);
if(strcmp(user_,Sucheck.user)==0 && strcmp(pass_,Sucheck.pass)==0)
{
printf("恭喜你登陆成功\n\n");
logintype =1;
break;
}
printf("\n帐号密码错误,请重新输入!\n");
}
}
//运行
void run()
{
load_Bk(Bk_info_file);
load_Admin(Admin_info_file);
load_Red(Red_info_file);
while(1)
{
startMenu();
// int isreturn = 0;
int oper = 0;
scanf("%d",&oper);
switch(oper)
{
case Su_ :
SuadminLogin();
break;
case Admin_ :
AdminLogin();
break;
case Reader_ :
RedLogin();
break;
}
//超级管理员菜单进入
while(logintype==1)
{
// logintype=0;
SuadminMenu();
int choose = -1;
scanf("%d",&choose);
switch(choose)
{
case 1:
add_Admin();
break;
case 2:
del_Admin();
break;
case 3:
mod_Admin();
break;//........
}
}
}
}
3.文件中全代码及注释
basicInfo.h://各种结构体 和变量的声明
#ifndef BASIC_INFO_H__
#define BASIC_INFO_H__
#define NAME_LEN 40 //书名长度
#define LOLEN 10 //登陆帐号密码长度
#define BORBK 5 //读者借阅书籍的数量
#define APPBK 5 //被预约图书的数量
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<time.h>
//图书信息结构体
typedef struct Book
{
int id; //书号
char name[NAME_LEN]; //书名
double price; //价格
int bortimes; //借阅次数
int have; //现在拥有数量
int appnum; //已经被预约的数量
int appoint[APPBK]; //预约图书 记录读者编号
}Bk;
#define SIZE_BK sizeof(Bk) //记录Bk的长度
//读者信息结构体
typedef struct Readers
{
int id; //读者编号
char user[LOLEN]; //读者用户
char pass[LOLEN]; //读者密码
char name[NAME_LEN];//读者姓名
int bornum; //已经借阅的数量
int borbook[BORBK]; //正在借阅的书籍 记录书号
int time[BORBK]; //记录借书的时间
double money; //余额
int appoin_num; //记录预约的书号
}Red;
#define SIZE_RED sizeof(Red) //记录Red的长度
//管理员信息结构体
typedef struct Admin
{
int id; //管理员编号
char user[LOLEN]; //管理员用户
char pass[LOLEN]; //管理员密码
char name[NAME_LEN];//管理员姓名
}Admin;
#define SIZE_ADMIN sizeof(Admin) //记录Admin的长度
//超级管理员信息结构体
typedef struct Superadmin
{
char user[LOLEN]; //超级管理员用户
char pass[LOLEN]; //超级管理员密码
}Suadmin;
extern Bk *pbk;//用于记录储存书籍信息的指针 需要申请动态内存
extern size_t Bsize;//申请动态内存能够存储书籍信息的数量
extern size_t Bcnt;//当前动态内存中书籍信息的数量
extern int Bk_id;//图书编号 自动增加
extern Red *pred;//用于记录储存读者信息的指针 需要申请动态内存
extern size_t Rsize;//申请动态内存能够存储读者信息的数量
extern size_t Rcnt;//当前动态内存中读者信息的数量
extern int Red_id;//读者编号 自动增加
extern Admin *padmin;//用于记录储存管理员信息的指针 需要申请动态内存
extern size_t Asize;//申请动态内存能够存储管理员信息的数量
extern size_t Acnt;//当前动态内存中管理员信息的数量
extern int Admin_id;//管理员编号 自动增加
extern Suadmin Sucheck;//超级管理员数组 单独保存
extern int logintype;//登陆类型 分支变量
extern Red *p; //读者登陆时 在动态内存找出这个读者的结构体
//extern int book_borid;
//extern int red_borid;
enum CODE_STATE //如果出现异常 返回异常结果的 枚举
{
SUCCESS = 0,
PATH_ERR,
ARG_ERR,
ALLOC_ERR,
OPEN_ERR,
FILE_NOT_EXISTS,
WRITE_ERR,
FAIL,
NOT_CHAR,
};
#endif
file.h://文件操作 读取保存
#ifndef _FILE_H__
#define _FILE_H__
#include "basicInfo.h"
//加载图书文件到内存中
int load_Bk(const char *path);
//把内存中的数据储存到图书文件中
int save_Bk(const char *path);
//加载管理员文件到内存中
int load_Bk(const char *path);
//把内存中的数据储存到管理员文件中
int save_Bk(const char *path);
//加载读者文件到内存中
int load_Bk(const char *path);
//把内存中的数据储存到读者文件中
int save_Bk(const char *path);
#endif
file.c:
#include"file.h"
#include<unistd.h>
//从图书文件加载到内存中
int load_Bk(const char *path)
{
if(path == NULL)
{
return PATH_ERR;
}
if(access(path,F_OK)!=0)
{
return FILE_NOT_EXISTS;
}
FILE *fp = fopen(path,"r");
if(fp == NULL)
{
return OPEN_ERR;
}
fread(&Bk_id,4,1,fp);
Bk s = {
};
while(fread(&s,SIZE_BK,1,fp)>0)
{
int ret = addBk(&s);
if(ret != SUCCESS)
{
fclose(fp);
return ret;
}
// printf("ret:%d\n",ret);
}
fclose(fp);
return SUCCESS;
}
//把内存中的数据储存到图书文件中
int save_Bk(const char *path)
{
if(path == NULL)
{
return ARG_ERR;
}
FILE *fp = fopen(path,"w");
if(fp == NULL)
{
return OPEN_ERR;
}
fwrite(&Bk_id,4,1,fp);
if(fwrite(pbk,SIZE_BK,Bcnt,fp)<Bcnt)
{
fclose(fp);
return WRITE_ERR;
}
fclose(fp);
return SUCCESS;
}
//从管理员文件加载到内存中
int load_Admin(const char *path)
{
if(path == NULL)
{
return PATH_ERR;
}
if(access(path,F_OK)!=0)
{
return FILE_NOT_EXISTS;
}
FILE *fp = fopen(path,"r");
if(fp == NULL)
{
return OPEN_ERR;
}
fread(&Admin_id,4,1,fp);
Admin s = {
};
while(fread(&s,SIZE_ADMIN,1,fp)>0)
<