图书管理系统的制作

本文介绍了如何使用C语言制作图书管理系统,包括系统功能规划、变量声明、基础框架搭建、文件操作、动态内存管理以及功能实现。系统具备超级管理员、普通管理员和读者三种登录方式,涉及界面设计、用户权限和数据存储等多个方面。
摘要由CSDN通过智能技术生成

如何做一个图书管理系统

首先做一个图书管理系统,你要知道它有什么功能,比如
它有3个登录的方式:

  1. 超级管理员登录
  2. 普通管理员登录
  3. 读者登录

有自己各自的登录方式
然后分别有自己的登录界面的功能选项 供不同的使用者使用

磨刀不误砍柴工,你先在脑海中或者在纸上构思一下有什么功能要实现,
实现大概需要一个什么样的过程,大概需要一个什么样子的结构、变量

比如:

  1. 每一次程序的启动 退出都要用文件操作来实现读取保存功能。
  2. 每个登录界面至少都要有返回的功能。
  3. 一般数据都是要保存在动态内存之中的。
  4. 每个用户都要有一些人性化的功能 比如修改自己用户密码、名称等等。
  5. 借阅 预约可以多本书,要提醒读者及时借阅
  6. 写函数的时候要严谨,一些基本的问题要考虑周到 比如书的数量要足够、归还余额要足够等等

然后写完功能记得要试验一下是否成功 不然可能最后运行的时候错误行数比代码行数还多。

1.基础_变量的声明,基本框架

构思完大概要怎么写之后先来写一点需要的变量和结构 取名字要注意 不要随便取!

  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;
  1. 然后需要一个界面文件和一个进行动态内存操作的文件(把数据存储到动态内存之中)
    创建一个view.h view.c通过run()函数 使main.c运行。
    run()函数中进行各种界面显示逻辑的处理。
    main.c:
#include"view.h"
int main()
{
   
	run();
}
  1. 文件操作需要一个文件来进行开始和最后的读取保存(超级管理员可以先设置一个账号密码 保存之后,注释掉超级管理员账号密码的那段代码)
    文件操作的时候想到一些问题
    加载的时候 图书编号需要读取一下 因为增加图书 要++ 不设置的话就是一开始设置好的值比如(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;
}

  1. 然后是动态内存的问题,动态内存就是要讲数据添加、删除、和找到这个整个结构体的地址
    所以在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)
	<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值