前言
这是我花了3天时间写的一个基于C语言的图书管理系统,里面包含了超级管理员,普通管理员,图书,读者4个模块。该管理系统使用了多文件的方式进行设计编写的,具有保存存储功能,也可以批量导入,批量导出,使用了动态内存分配,对于初学者入门,该文章是最好的选择了!!
下面展示一下流程图
展示一下我的文件分类
一些结构体的定义我都是放在一个peopleInfo.h中的
#ifndef _PEOPLEINFO_H__
2 #define _PEOPLEINFO_H__
3
4 #include<stdio.h>
5 #include<string.h>
6 #include<stdlib.h>
7 #define FILE_MNAME "mana.bin"
8 #define FILE_RNAME "reader.bin"
9 #define FILE_BNAME "book.bin"
10 #define NAME_LEN 40
11 #define PASS_LEN 40
12 #define USER_LEN 40
13 #define BOOK_LEN 150
enum SEX{MAN,WOMAN};
16 enum RET_CODE{
17 SUCCESS = 0,
18 ARG_ERR,
19 ALLOC_ERR,
20 FAIL,
21 OPEN_ERR,
22 FILE_NOT_EXISTS,
23 WRITE_ERR
24 };
25 typedef struct SuperInfo{//超级管理员
26 int id;//工号
27 char name[NAME_LEN];//名字
28 int age;//年龄
29 enum SEX sex;//性别
30 }Super;
31
32 typedef struct ManaInfo{//普通管理员
33 int id;//工号
34 char name[NAME_LEN];//名字
35 int age;//年龄
36 enum SEX sex;//性别
37 char user[USER_LEN];//用户名
38 char pass[PASS_LEN];//密码
39 }Mana;
40
41 typedef struct BookInfo{//图书结构体
42 int id;//书号
43 char name[NAME_LEN];//书名
44 char author[NAME_LEN];//作者
45 double price;//价格
46 int state;//状态,可借or不可借or被预约
47 int lender;//借这本书的人
48 }Book;
typedef struct ReaderInfo{//读者
51 int id;//读者号
52 char name[NAME_LEN];//名字
53 int age;//年龄
54 enum SEX sex;//性别
55 double balance;//余额
56 char borrowBook[10][BOOK_LEN];//所借的书
57 char orderBook[10][BOOK_LEN];//预约书
58 char user[USER_LEN];//用户名
59 char pass[PASS_LEN];//密码
60 }Reader;
61
62
63 extern Mana *pmana;//记录普通管理员信息 需要申请动态内存
64 extern size_t msize;//申请动态内存能够存储管理员信息的数量
65 extern size_t mcnt;//当前动态内存中管理员信息数量
66 extern int makeId;//自动生成管理员工号
67
68 extern Book *pbook;//记录图书信息 要申请动态内存
69 extern size_t bsize;//申请动态内存能够存储图书信息的数量
70 extern size_t bcnt;//当前动态内存中图书信息数量
71 extern int bookId;//自动生成书号
72
73 extern Reader *preader;//记录读者信息 需要申请动态内存
74 extern size_t rsize;//申请动态内存能够存储读者信息的数量
75 extern size_t rcnt;//当前动态内存中读者信息数量
76 extern int readerId;//自动生成读者号
77
78
79 #endif //_PEOPLEINFO_H__
主界面的3个登录界面
多文件的好处就是可以使代码更好的分类,做项目的时候它不可能把所有的东西都写在一个文件中,我一个view.c文件中要编写功能代码,那么我要在view.h文件中去声明好这些函数,做好一一对应,那么在调用的时候只要调用view.h文件就行了
1 #include "view.h"
2 #include "oper.h"
3 #include "viewMana.h"
4 #include "viewSuper.h"
5 #include "viewReader.h"
6
7 void showPeopleType(){//第一个界面,显示人员的类型
8 printf("指针图书信息管理\n");
9 printf("1 超级管理员\n");
10 printf("2 普通管理员\n");
11 printf("3 普通会员\n");
12 printf("0 退出\n");
13 }
14
15 void run(){//
16 showPeopleType();
17 int oper = 0;
18 scanf("%d",&oper);
19 switch(oper){
20 case 0:
21 manaSave(FILE_MNAME);
22 readerSave(FILE_RNAME);
23 bookSave(FILE_BNAME);
24 exit(0);
25 case 1:
26 superLogin();//调用超级管理员
27 break;
28 case 2:
29 manaLogin(pmana);//调用普通管理员,这里的指针传全局的指针pmana
30 break;
31 case 3:
32 readerLogin(preader);
33 break;
34 }
35 }
增删改查的功能在oper.c中,这里是他们函数的逻辑功能实现代码
1 #include "oper.h"
2
3 int addMana(Mana *pm){//添加一个管理员
4 if(pm == NULL){//指针为空
5 return ARG_ERR;
6 }
7 if(pmana == NULL){//第一次申请
8 pmana = malloc(sizeof(Mana)*msize);
9 }
10 if(pmana != NULL && msize == mcnt){//满了
11 msize *= 2;//扩容
12 pmana = realloc(pmana,sizeof(Mana)*msize);
13 }
14 if(pmana == NULL){//如果申请动态内存失败了
15 return ALLOC_ERR;
16 }
17 pmana[mcnt] = *pm;//把该管理员放进去
18 ++mcnt;
19 return SUCCESS;
20 }
21
22 int delMana(int id){//删除管理员
23 int i;
24 for(i = 0; i < mcnt; i++){
25 if(pmana[i].id == id){
26 pmana[i] = pmana[mcnt-1];
27 mcnt--;
28 return SUCCESS;
29 }
30 }
31 return;
32 }
Mana* findMana(int id){//查找管理员
35 int i;
36 for(i = 0; i < mcnt; i++){
37 if(pmana[i].id == id){
38 return &pmana[i];
39 }
40 }
41 return NULL;
42 }
43
44 int addBook(Book *pb){//增加一本书
45 if(pb == NULL){//指针为空
46 return ARG_ERR;
47 }
48 if(pbook == NULL){//第一次申请
49 pbook = malloc(sizeof(Book)*bsize);
50 }
51 if(pbook != NULL && bsize == bcnt){//满了
52 bsize *= 2;//扩容
53 pbook = realloc(pbook,sizeof(Book)*bsize);
54 }
55 if(pbook == NULL){//如果申请动态内存失败了
56 return ALLOC_ERR;
57 }
58 pbook[bcnt] = *pb;//把该书放进去
59 ++bcnt;
60 return SUCCESS;
61 }
63 int delBook(int id){//删除一本书
64 int i;
65 for(i = 0; i < bcnt; i++){
66 if(pbook[i].id == id){
67 pbook[i] = pbook[bcnt-1];
68 --bcnt;
69 return SUCCESS;
70 }
71 }
72 return;
73 }
74
75 Book *findBook(int id){//查找一本书
76 int i;
77 for(i = 0; i < bcnt; i++){
78 if(pbook[i].id == id){
79 return &pbook[i];
80 }
81 }
82 return NULL;
83 }
85 int addReader(Reader *pr){//增加一个读者
86 if(pr == NULL){
87 return ARG_ERR;
88 }
89 if(preader == NULL){
90 preader = malloc(sizeof(Reader)*rsize);
91 }
92 if(pr != NULL && rcnt == rsize){
93 rsize *= 2;
94 preader = realloc(preader,sizeof(Reader)*rsize);
95 }
96 if(preader == NULL){//申请失败
97 return ALLOC_ERR;
98 }
99 preader[rcnt] = *pr;
100 ++rcnt;
101 return SUCCESS;
102 }
103
104 int delReader(int id){
105 int i;
106 for(i = 0; i < rcnt; i++){
107 if(preader[i].id == id){
108 preader[i] = preader[rcnt-1];
109 --rcnt;
110 return SUCCESS;
111 }
112 }
113 return;
114 }
116 Reader *findReader(int id){
117 int i;
118 for(i = 0; i < rcnt; i++){
119 if(preader[i].id == id){
120 return &preader[i];
121 }
122 }
123 return NULL;
124 }
以图书模块的增删改为例
1 #include "viewMana.h"
2 #include "oper.h"
3
4 void showBook(Book *pb){//显示图书
5 printf("书号:%d\n",pb->id);
6 printf("书名:%s\n",pb->name);
7 printf("作者:%s\n",pb->author);
8 printf("价格:%.2lf\n",pb->price);
9 printf("状态:%s\n",pb->state == 0 ? "可借":(pb->state == 1 ?"借阅":(pb->state==2?"预约":"借阅预约")));//0 空闲可借 1 被借走 2 被预约 3借阅中,被> 预约
10 printf("借阅者:%d\n",pb->lender);
11 }
12
13 void addBooks(){//增加图书
14 Book b = {};
15 b.id = bookId++;
16 printf("增加图书\n");
17 printf("请输入书名\n");
18 scanf("%s",b.name);
19 printf("请输入作者\n");
20 scanf("%s",b.author);
21 printf("请输入价格\n");
22 scanf("%lf",&b.price);
23 printf("请输入状态 0-可借 1-借阅 2-预约 3-借阅预约\n");
24 scanf("%d",&b.state);
25 //printf("借这本书的人\n");
26 //scanf("%d",&b.lender);
27 addBook(&b);
28 showBook(&b);
29 }
31 void delBooks(){//删除图书
32 printf("请输入要删除的书号\n");
33 int id = 0;
34 scanf("%d",&id);
35 if(delBook(id) == SUCCESS){
36 printf("删除成功\n");
37 }else{
38 printf("没有该书\n");
39 }
40
41 }
42
43 void altBooks(){//修改图书
44 printf("请输入要修改的书号\n");
45 int id;
46 scanf("%d",&id);
47 Book *pb = findBook(id);
48 if(pb == NULL){
49 printf("没有该书\n");
50 return;
51 }
52 showBook(pb);
53 printf("请输入书名\n");
54 scanf("%s",pb->name);
55 printf("请输入作者\n");
56 scanf("%s",pb->author);
57 printf("请输入价格\n");
58 scanf("%lf",&pb->price);
59 printf("借阅情况 0-可借 1-借阅 2-预约 3-借阅预约\n");
60 scanf("%d",&pb->state);
61 }
63 void findBooks(){//查找图书
64 printf("请输入要查找的书号\n");
65 int id = 0;
66 scanf("%d",&id);
67 Book *pb = findBook(id);
68 if(pb == NULL){
69 printf("没有这本书\n");
70 return;
71 }
72 showBook(pb);
73 }
74
75 void listBooks(){//列出图书
76 if(bcnt == 0){
77 return;
78 }
79 printf("-----------------------------------------------------------------------\n");
80 printf("书号\t书名\t作者\t价格\t借阅情况\t借阅者id\n");
81 int i;
82 for(i = 0; i < bcnt; i++){
83 printf("%d\t%s\t%s\t%.2lf\t%s\t\t%d\n",pbook[i].id,pbook[i].name,pbook[i].author,pbook[i].price,pbook[i].state==0?"可借":(pbook[i].state==1?"借阅" :(pbook[i].state==2?"预约":"借阅预约")),pbook[i].lender);
84 }
85 printf("-----------------------------------------------------------------------\n");
86 }
文件的导入导出同样以图书为例
88 void importBooks(){
89 char path[NAME_LEN];
90 Book im = {};
91 int ret;
92 printf("请输入你要导入的源文件\n");
93 scanf("%s",path);
94 FILE *frp = fopen(path,"r");
95 if(frp != NULL){
96 while(1){
97 char imState[NAME_LEN];
98 ret = fscanf(frp,"%d%s%s%lf%s%d",&im.id,im.name,im.author,&im.price,imState,&im.lender);
99 if(ret > 0){
100 if(strcmp(imState,"可借") == 0){
101 im.state = 0;
102 }else if(strcmp(imState,"借阅") == 0){
103 im.state = 1;
104 }else if(strcmp(imState,"预约") == 0){
105 im.state = 2;
106 }else{
107 im.state = 3;
108 }
109 addBook(&im);
110 }else{
111 printf("导入完成\n");
112 break;
113 }
114 }
115 }
116
117 }
118 void exportBooks(){
119 char path[NAME_LEN];
120 printf("请输入你要导出的文件名\n");
121 scanf("%s",path);
122 FILE *fwp = fopen(path,"w");
123 int i;
124 if(fwp != NULL){
125 for(i = 0; i < bcnt; i++){
126 fprintf(fwp,"%d\t%s\t%s\t%.2lf\t%s\t%d\n",pbook[i].id,pbook[i].name,pbook[i].author,pbook[i].price,pbook[i].state==0?"可借":(pbook[i].stat e==1?"借阅":(pbook[i].state==2?"预约":"借阅预约")),pbook[i].lender);
127 }
128 }
129 fclose(fwp);
130 }
借书还书部分的设计还不够完善,只写了借一本还一本预约也只能一本,定义结构体时候可以把变量定义为数组,后序 完善了会补充
1 #include "viewReader.h"
2 #include "oper.h"
3 #include<assert.h>
4
5
6 void readerAdmin(){//读者目录
7 printf("指针图书信息管理系统 -- 读者\n");
8 printf("1 查找图书(借阅.还书.预约)\n");//模糊查询 借阅 还书 预约图书
9 printf("2 充值余额\n");
10 printf("3 修改密码\n");
11 printf("4 返回\n");
12 printf("0 退出\n");
13 }
14
15 void fuzzy(const char *dady,const char *baby){
16 assert(dady!=NULL&& baby!=NULL );
17 int i=0;
18 size_t len = strlen(baby);
19 while(dady[i] != '\0'){
20 if(dady[i] == baby[0]){
21 if(strncmp(baby,dady+i,len)==0){
22 printf("%s ",dady);
23 }
24 }
25 i++;
26 }
27 } 29 Book *fuzzyBooks(Reader *pr){ //查找书籍
30 if(pbook == NULL){
31 printf("the list is empty!\n");
32 return pbook;
33 }
34 Book *pb = pbook;
35 char seekName[NAME_LEN];
36 printf("请输入您要查找的书籍名(模糊匹配):");
37 scanf("%*c");
38 scanf("%[^\n]",seekName);
39 int i=0;
40 int len = strlen(seekName);
41 printf("您可能想要查找的书籍如下:\n");
42 for(i=0;i<bcnt;i++){
43 fuzzy(pb[i].name,seekName);
44 }
45 printf("请您选择输入具体书名:");
46 scanf("%*c");
47 scanf("%[^\n]",seekName);
48 i=0;
49 while(strcmp(pb->name,seekName)!=0 && i<bcnt){
50 pb++;
51 i++;
52 }
53 if(strcmp(pb->name,seekName) == 0){
54 printf("编号为%d 的书籍的信息如下:\n",pb->id);
55 printf("书号:%d\t书名:%s\t作者:%s\t价格:%.2lf\t状态:%s\t借阅者%d\n",pb->id,pb->name,pb->author,pb->price,pb->state==0?"可借":(pb->state==1?"借
阅":(pb->state ==2?"预约":"借阅预约")),pb->lender);
56 printf("请操作:1-借阅书籍 2-预约书籍 3-归还书籍 4-返回");
57 int opt;
58 scanf("%d",&opt);
59 switch(opt){
60 case 1:
61 borrowBooks(pb,pr);
62 break;
63 case 2:
64 appBooks(pb,pr);
65 break;
66 case 3:
67 returnBooks(pb,pr);
68 case 4:
69 return pbook;
70 break;
71 default:
72 printf("illegal input!\n");
73 break;
74 }
75 }else{
76 printf("查无此书籍!\n");
77 }
78 return pbook;
79 }
80 void borrowBooks(Book *pb,Reader *pr){
81 if(pb->state == 1){//被借走
82 printf("这本书被借走了\n");
83 return;
84 }else if(pb->state == 2){//被预约
85 if(strcmp(pr->orderBook[0],pb->name) == 0 && pb->lender == 0){//1预约者与被预约的书一样才能借2这本书别人已经还了
86 printf("成功借走这本书\n");
87 pb->state = 1;//状态变为借走
88 pb->lender = pr->id;//把读者的id赋值给书的借阅者
89 strcpy(pr->borrowBook[0],pb->name);//把书名赋值给读者所借的书
90 pr->balance -= 10;//读者的金额减少10
91 strcpy(pr->orderBook[0],NULL);
92 }else{
93 printf("这本书被预约了,不能借走\n");
94 }
95 }else{
96 printf("成功借走\n");
97 pb->state = 1;//状态变成借走
98 pb->lender = pr->id;//把读者的id赋值给书的借阅者
99 strcpy(pr->borrowBook[0],pb->name);//把书名赋值给读者所借的书
100 pr->balance -= 10;//读者的金额减少10
101 return;
102 }
103 }
104
105 void returnBooks(Book *pb,Reader *pr){
106 printf("请输入要归还的书号\n");
107 int id = 0;
108 scanf("%d",&id);
109 int i = 0;
110 while(i < bcnt && pb->id != id){
111 i++;
112 pb++;
113 }
114 if(pb->id == id){
115 if(strcmp(pb->name,pr->borrowBook[0]) == 0){//借的书和书名一样
116 pb->state = 0;
117 pb->lender = 0;//书的使用者变为空
118 strcmp(pr->borrowBook[0],"NULL");//读者所借的书变为空
119 printf("还书成功\n");
120 }else{
121 printf("这本书你没有借,无法归还\n");
122 }
123 }else{
124 printf("没有这本书\n");
125 }
126 }
127 void appBooks(Book *pb,Reader *pr){//预约书籍
128 if(strcmp(pr->orderBook[0],"NULL") != 0){
129 printf("你已经有预约的书了,预约失败\n");
130 return;
131 }
132 if(pb->state == 0){//可借
133 pb->state = 2;
134 strcpy(pr->orderBook[0],pb->name);
135 pr->balance -= 2;
136 printf("你成功预约了这本书\n");
137 return;
138 }else if(pb->state == 1){//被借走
139 pb->state = 3;//被借走的书,被预约了
140 pr->balance -= 2;
141 printf("你成功预约了这本书,等别人还了你就能借啦\n");
142 return;
143 }else{//被预约了
144 printf("这本书别人预约了,预约失败\n");
145 return;
146 }
147 }
148
149 void balanceAdd(Reader *pr){
150 double money = 0;
151 printf("你当前的余额为%.2lf\n",pr->balance);
152 printf("请输入要充值的金额\n");
153 scanf("%lf",&money);
154 pr->balance += money;
155 printf("你充值后的余额为%.2lf\n",pr->balance);
156 }
157
158 void changePass(Reader *pr){
159 printf("请输入原来的密码\n");
160 char oldPass[NAME_LEN];
161 scanf("%s",oldPass);
162 if(strcmp(pr->pass,oldPass) == 0){
163 printf("请输入新密码");
164 scanf("%s",pr->pass);
165 }else{
166 printf("你输入的旧密码有错\n");
167 }
168 }
登录差点给忘了,看看读者登录
170 void readerLogin(Reader *pr){//读者登陆
171 size_t i,j;
172 char in_user[20];
173 char in_pass[20];
174 int flag = 0;
175 printf("你有3次输入的机会\n");
176 for(j = 0; j < 3; j++){
177 printf("请输入用户名\n");
178 scanf("%s",in_user);
179 for(i = 0; i < rcnt; i++){
180 if(strcmp(pr[i].user,in_user) == 0){
181 printf("请输入密码\n");
182 scanf("%s",in_pass);
183 if(strcmp(pr[i].pass,in_pass) == 0){
184 flag = 1;
185 break;
186 }
187 }
188 }
189 if(flag == 1){
190 break;
191 }
192 }
193 if(j < 3){
194 printf("登陆成功\n");
195 while(1){
196 readerAdmin();
197 int opt = 0;
198 scanf("%d",&opt);
199 switch(opt){
200 case 1:
201 fuzzyBooks(pr+i);//模糊查询
202 break;
203 case 2:
204 balanceAdd(pr+i);//余额充值
205 break;
206 case 3:
207 changePass(pr+i);//修改密码
208 break;
209 case 4:
210 run();//返回
211 case 0:
212 manaSave(FILE_MNAME);
213 readerSave(FILE_RNAME);
214 bookSave(FILE_BNAME);
215 exit(0);
216 break;
217 }
218 }
219 }else{
220 printf("登陆失败\n");
221 run();
222 }
223 }