5、简单文件数据库-模拟图书馆管理系统
涉及知识点:文件读写、内存管理、结构体定义、基本数据结构、高级格式化输入输出
要求:
编写一个程序模拟图书管理系统。用户分为管理员和读者两类,分别显示不同文本格式菜单,通过菜单项对应数字进行选择。读者菜单包括借书、还书、查询等功能。管理员菜单包括图书和读者信息录入、修改和删除。图书信息至少应包括:编号、书名、数量,读者信息至少应包括:编号、姓名、所借图书。可根据图书名称或编号进行图书信息查询,可查询某本书现在被哪些读者借走。
命令行参数如下:
Libsim –a(-u) xxxx
第一个参数为可执行程序名称;第二个参数为用户身份,-a表示管理员,-u表示读者;第三个参数为用户名
都是一些基本的逻辑,但是实现的时候其实挺繁琐的,事实上,我们需要先搞清楚给定需求。
主要就是要实现图书馆书籍的增删改查。读者所拥有的书籍的增删查。
对于书籍:需要书籍的名称,ID
不难想到,会存在很多书籍名称相同,ID不同,所以,在每本书的节点,应当在定义一个ID链表,这样每个ID才是实实在在的一本书,而不是叫做当前书名的一类书。
到了这里,仔细考虑,对于每个ID节点,我们还可以储存借出了当前书籍的人。
所以就会有以下定义。
typedef struct Node {
int data; //编号
char readerName[MAX];//当前借阅读者的名称
struct Node* next;
}Node;
typedef struct Book {
int inNum; //馆存数量
int outNum; //外借数量
char name[MAX]; //名称
Node* id; //编号
struct Book* next;
}Book;
而对于读者,只需要读者名字,所借的一系列书籍这些即可
typedef struct Readers{
Book* allBooks;
char name[MAX];
struct Readers* next;
}Readers;
具体实现代码如下:
#include
#include
#include
#define MAX 256
//Node和 Book用于记录 图书馆中的书,Book储存名称,Node储存ID和读者信息
typedef struct Node {
int data; //编号
char readerName[MAX];//当前借阅读者的名称
struct Node* next;
}Node;
typedef struct Book {
int inNum; //馆存数量
int outNum; //外借数量
char name[MAX]; //名称
Node* id; //编号
struct Book* next;
}Book;
//Readers: name储存读者名字,
//allBooks链表:对于每个Book节点,inNum,outNum为无用信息,
//只需要书名和改书包含的一系列ID
typedef struct Readers{
Book* allBooks;
char name[MAX];
struct Readers* next;
}Readers;
char BUF[1024];
Book* libary = NULL;
Readers* reader = NULL;
char s[25];//记录当前模式
int inintReaders(); //将读者件读取到程序中
int inintLibrary(); //将图书馆文件读取到程序中
void showBook(Book* bk); //输出bk中的所有信息
void showAdmin(); //展示管理员操作台
void showReader(); //展示读者操作台
Readers* findReader(char* name); //在reader链表中寻找 name 的节点
int searchBookByName(char* name); //通过name寻找书籍并打印信息
Book* searchBookByNameHelper(Book* allBooks, char* name); //在allBook链表中通过name寻找书书籍节点
int searchBookByID(int id); //通过 id寻找书籍并打印信息
int deleteBookByName(char *name); // 在libary中删除name的书籍
int deleteBookByID(int id); //在libary中删除id的书籍
void addBook(Book* allBooks,char* name , int id); // 在allBooks链表中添加新书
int changeBook(char* name,int id,char* newname, int newid); // 在libary中改变书籍
/*若改变书名,则添加一本新书籍,否则改变ID*/
int borrowBook(char* bkname , char* rdname); // 读者借书操作
int returnBook(char* bkname , char* rdname); //读者还书操作
void ForAdmin(); //管理员模式
void ForReader(char* rdname); //读者模式
/*结束程序,并将当前状态写入到文件中保存起来*/
void endReader();
void endLib();
void end();
//----------------可爱的分割线 ---------------------------------
int main(int argc, char *argv[]) {
if(inintLibrary() == 0)
return 0;
if(inintReaders() == 0)
return 0;
if(strcmp(argv[1],"-u")==0){
ForReader(argv[2]);
}else{
ForAdmin();
}
end();
return 0;
}
//----------------无情的分割线 ---------------------------------
void endReader(){
Readers* rd = reader->next;
FILE* fp = fopen("myreaders.readers","w");
while(rd != NULL){
fprintf(fp,"%s#",rd->name);
Book* bk = rd->allBooks->next;
while(bk != NULL){
fprintf(fp,"%s",bk->name);
Node* p = bk->id->next;
while(p != NULL){
fprintf(fp,",%d",p->data);
p = p->next;
}
fprintf(fp,"#");
bk = bk->next;
}
fprintf(fp,"\n");
rd = rd->next;
}
}
void endLib(){
FILE* fp = fopen("mylibary.libary","w");
Book* bk = libary->next;
while(bk != NULL){
printf("sa\n");
fprintf(fp,"%s#",bk->name);
fprintf(fp,"%d#",bk->inNum);
fprintf(fp,"%d#",bk->outNum);
Node* p = bk->id->next;
while(p != NULL){
fprintf(fp,"%d#%s#",p->data,strlen(p->readerName)>0?p->readerName:".");
p = p->next;
}
fprintf(fp,"\n");
bk = bk->next;
}
}
void end(){
endReader();
endLib();
printf("欢迎使用!再见!\n");
}
void ForReader(char* rdname){
//不存在当前读者的话
Readers* r = findReader(rdname);
if(r == NULL){
Readers* rp = reader;
r = (Readers*)malloc(sizeof(Readers));
strcpy(r->name,rdname);
r->allBooks = (Book*)malloc(sizeof(Book));
r->allBooks->id = (Node*)malloc(sizeof(Node));
r->allBooks->id->next = NULL;
r->allBooks->next = NULL;
r->next = rp->next;
rp->next = r;
}
while(1){
showReader();
int choice = 0;
scanf("%d",&choice);
if(choice == 0){
return ;
}else if(choice == 1){
char bkname[MAX]="";
printf("请输入借阅书籍:\n");
scanf("%s",bkname);getchar();
borrowBook(bkname , rdname);
}else if(choice == 2){
char bkname[MAX]="";
printf("请输入归还书籍:\n");
scanf("%s",bkname);getchar();
returnBook(bkname , rdname);
}else{
printf("Error!\n");
}
}
}
int inintReaders(){
FILE* fp = fopen("myreaders.readers", "r");
if (fp == NULL) {
printf("ERROR!");
return 0;
}
reader = (Readers*)malloc(sizeof(Readers));
reader->next = NULL;
reader->allBooks = NULL;
Readers* cur = reader;
while (!feof(fp)) {
//重置BUF区域后读取一行到BUF中并建立一本书
memset(BUF,'\0',sizeof(BUF));
fgets(BUF, 1024, fp);
if(BUF[0]=='\0'||BUF[0]=='\n'||BUF[0]=='\r')
break;
int n = strlen(BUF);
//建立用户
Readers* p = (Readers*)malloc(sizeof(Readers));
p->next = NULL;
p->allBooks = (Book*)malloc(sizeof(Book));
p->allBooks->next = NULL;
//书籍的哑节点
Book* curbk = p->allBooks;
int index = 0;
char name[MAX] = "";
int t = 0;
//读者名字
while(index<n && BUF[index]!='#'){
name[t] = BUF[index];
t++;
index ++;
}
strcpy(p->name,name);
//剩下的信息全部是书籍的
while(index<n&& BUF[index]!='\n'&&BUF[index]!='\0'&&BUF[index]!='\r'){
if(BUF[index] == '#'){
if(index == n-1 || BUF[index]=='\n'||BUF[index]=='\0'||BUF[index]=='\r')
break;
index ++;
if(BUF[index]=='\n'||BUF[index]=='\0'||BUF[index]=='\r')
break;
memset(name,'\0',sizeof(name));
t = 0;
//建立一本新书
Book* bk = (Book*)malloc(sizeof(Book));
bk->id = (Node*)malloc(sizeof(Node));
bk->id->next = NULL;
bk->id->data = -1;
bk->next = NULL;
Node* sd = bk->id;
//书名
while(index<n && BUF[index]!=','){
name[t] = BUF[index];
t++;
index++;
}
strcpy(bk->name,name);
index ++;
//记录下所有的ID
while(index<n && BUF[index]!='\n'&&BUF[index]!='\0'&&BUF[index]!='\r' && BUF[index]!='#'){
if(BUF[index]==','){
index ++;
}else{
int id = 0;
Node* s = (Node*)malloc(sizeof(Node));
s->next = NULL;
while(index<n && BUF[index]!='\n'&&BUF[index]!='\0'&&BUF[index]!='\r' && BUF[index]!='#' && BUF[index]!=','){
id = id*10 + BUF[index]-'0';
index ++;
}
s->data = id;
sd->next = s;
sd = sd->next;
}
}
//下一本
curbk->next = bk;
curbk = curbk->next;
}else{
index ++;
}
}
//下一个读者
cur->next = p;
cur = cur->next;
}
return 1;
}
int inintLibrary() {
FILE* fp = fopen("mylibary.libary", "r+");
if (fp == NULL) {
printf("ERROR!");
return 0;
}
libary = (Book*)malloc(sizeof(Book));//头节点
libary->next = NULL;
Book* cur = libary;
while (!feof(fp)) {
//重置BUF区域后读取一行到BUF中并建立一本书
memset(BUF,0,sizeof(BUF));
fgets(BUF, 1024, fp);
if(BUF[0]=='\0'||BUF[0]=='\n'||BUF[0]=='\r')
break;
Book* p = (Book*)malloc(sizeof(Book));
p->next = NULL;
int index = 0;
int n = strlen(BUF);
//读取书名
while (index < n && BUF[index] != '#') {
p->name[index] = BUF[index];
index++;
}
p->name[index] = '\0';
index++;
//读取数量
p->inNum = 0;
p->outNum = 0;
int num = 0;
//当前图书馆存在的数量
while (index < n && BUF[index] != '#') {
num = num * 10 + BUF[index] - '0';
index++;
}
p->inNum = num;
index++;
//当前图书馆外借的数量
num = 0;
while (index < n && BUF[index] != '#') {
num = num * 10 + BUF[index] - '0';
index++;
}
p->outNum = num;
index++;
//读取编号并制成Node链表
p->id = (Node*)malloc(sizeof(Node));
p->id->data = -1;
strcpy(p->id->readerName ,"");
Node* tmp = p->id;
while (index<n && BUF[index]!='\0' && BUF[index]!='\n') {
if (BUF[index] == '#') {
index++;
}
else {
int d = 0;
//获取ID
while (index < n && isdigit(BUF[index])) {
d = d * 10 + (BUF[index] - '0');
index++;
}
if(BUF[index] == '#'){
index ++;
}
char nameBuf[MAX]="";
int t = 0;
while(index<n && BUF[index]!='\n'&&BUF[index]!='#'&&BUF[index]!='\0'&&BUF[index]!='\r'){
nameBuf[t] = BUF[index];
index++;
t++;
}
Node* s = (Node*)malloc(sizeof(Node));
s->data = d;
if(strcmp(nameBuf,".") == 0)
strcpy(s->readerName,"\0");
else
strcpy(s->readerName,nameBuf);
s->next = NULL;
tmp->next = s;
tmp = tmp->next;
}
}
//下一本
cur->next = p;
cur = cur->next;
}
return 1;
}
void addBook(Book* allBooks,char* name , int id) {
Book* cur = searchBookByNameHelper(allBooks,name);
if(cur == NULL){
Book* bk = (Book*)malloc(sizeof(Book));
strcpy(bk->name,name);
bk->outNum = 0;
bk->inNum = 1;
bk->id = (Node*)malloc(sizeof(Node));
Node* tmp = bk->id;
tmp->data = -1;
Node* s = (Node*)malloc(sizeof(Node));
s->data = id;
s->next = NULL;
tmp->next = s;
Book* cur = allBooks;
bk->next = cur->next;
cur->next = bk;
printf("OK!\n");
}else{
cur->inNum++;
Node* tmp = (Node*)malloc(sizeof(Node));
tmp->data = id;
strcpy(tmp->readerName,"");
Node* p = cur->id;
tmp->next = p->next;
p->next = tmp;
}
printf("添加成功!\n");
}
Book* searchBookByNameHelper(Book* allBooks, char* name){
Book* cur = allBooks->next;
while(cur != NULL){
if(strcmp(cur->name , name)==0){
return cur;
}
cur = cur->next;
}
return NULL;
}
int searchBookByName(char* name) {
Book* bk = searchBookByNameHelper(libary,name);
if(bk == NULL){
printf("抱歉!不存在这本书!\n");
return 0;
}
printf("这是寻找到的书的信息:\n");
showBook(bk);
return 1;
}
int searchBookByID(int id) {
Book* bk = libary->next;
while(bk != NULL){
Node* p = bk->id->next;
while(p != NULL){
if(p->data == id){
printf("这是寻找到的书的信息:\n");
showBook(bk);
return 1;
}
}
}
printf("抱歉!不存在这本书!\n");
return 0;
}
void showAdmin() {
printf("\n--------图书馆管理系(administrators)-----------\n");
printf("| 你可以选择以下操作(按下相应数字键): |\n");
printf("| 0.退出程序 |\n");
printf("| 1.录入图书信息 |\n");
printf("| 2.删除图书信息 |\n");
printf("| 3.修改图书信息 |\n");
printf("| 4.查询图书信息 |\n");
printf("| 5.录入读者信息 |\n");
printf("| 6.删除读者信息 |\n");
printf("| 7.修改读者信息 |\n");
printf("| 8.查询读者信息 |\n");
printf("----------------------------------------------\n");
}
void showReader() {
printf("\n--------图书馆管理系(reader)------------------\n");
printf("| 你可以选择以下操作(按下相应数字键): |\n");
printf("| 0.退出程序 |\n");
printf("| 1.借书 |\n");
printf("| 2.还书 |\n");
printf("----------------------------------------------\n");
}
int deleteBookByName(char *name) {
Book* bk = libary;
while(bk->next!=NULL){
if(strcmp(bk->next->name,name) == 0){
Book* p = bk->next;
bk->next = p->next;
free(p);
printf("删除成功!\n");
return 1;
}
bk = bk->next;
}
printf("删除失败!不存在!\n");
return 0;
}
int deleteBookByID(int id){
Book* bk = libary->next;
while(bk != NULL){
Node* p = bk->id;
while(p->next != NULL){
if(p->next->data == id){
Node* s = p->next;
p->next = s->next;
free(s);
bk->inNum--;
printf("删除成功!\n");
return 1;
}
p = p->next;
}
}
printf("删除失败!不存在!\n");
return 0;
}
void showBook(Book* bk){
if(bk==NULL)
return ;
printf("书名: %s\n",bk->name);
printf("馆存数量: %d\n",bk->inNum);
printf("外借数量: %d\n",bk->outNum);
Node* cur = bk->id->next;
printf("编号列表: \n");
while(cur!=NULL){
printf("ID:%d 外借情况:%s\n",cur->data,strlen(cur->readerName)>0?cur->readerName:"未借出");
cur = cur->next;
}
printf("\n");
}
int changeBook(char* name,int id,char* newname, int newid){
Book* bk = searchBookByNameHelper(libary,name);
if(bk == NULL){
printf("修改失败!不存在!\n");
return 0;
}
Node* tmp = bk->id;
while(tmp->next != NULL){
if(tmp->next->data == id){
if(name == newname){ //名称未变
tmp->next->data = newid;
printf("修改成功!\n");
return 1;
}else{
Node* s = tmp->next;
tmp->next = s->next;
bk->inNum--;
free(s);
addBook(libary,newname , newid);//名称已变,新建书本
return 1;
}
}
tmp = tmp->next;
}
printf("修改失败!不存在!\n");
return 0;
}
Readers* findReader(char* name){
Readers* cur = reader->next;
while(cur != NULL){
if(strcmp(cur->name,name)==0){
return cur;
}
cur = cur->next;
}
return NULL;
}
int borrowBook(char* bkname , char* rdname) {
Book* bk = searchBookByNameHelper(libary,bkname);
if(bk==NULL){
printf("借阅失败!不存在!\n");
return 0;
}else if(bk->inNum == 0){
printf("借阅失败!不存在!\n");
return 0;
}
Node* p = bk->id->next;
while(p != NULL && strlen(p->readerName)>0){
p = p->next;
}
if(p == NULL){
printf("借阅失败!不存在!\n");
return 0;
}
int id = p->data;
Readers* rd = findReader(rdname);
if(rd == NULL){
printf("未查询到读者!\n");
return 0;
}else{
strcpy(p->readerName , rdname);
//在读者已有的书籍中寻找
Book* rk = searchBookByNameHelper(rd->allBooks,bkname);
//不存在
if(rk == NULL){
Book* book = rd->allBooks;
Book* tmp = (Book*)malloc(sizeof(Book));
strcpy(tmp->name,bkname);
tmp->next = NULL;
//ID的记录
tmp->id = (Node*)malloc(sizeof(Node));
tmp->id->data = -1;
//新ID加入
Node* t = (Node*)malloc(sizeof(Node));
t->data = id;
t->next = NULL;
tmp->id->next = t;
//将书籍加入
tmp->next = book->next;
book->next = tmp;
}else{
Node* tp = rk->id;
Node* sp = (Node*)malloc(sizeof(Node));
sp->data = id;
sp->next = tp->next;
tp->next = sp;
}
}
bk->inNum--;
bk->outNum++;
printf("借阅成功!\n");
return 1;
}
int returnBook(char* bkname , char* rdname) {
Readers* rd = findReader(rdname);
if(rd == NULL){
printf("归还失败,未查询到读者!\n");
return 0;
}
Book* bk = searchBookByNameHelper(rd->allBooks,bkname);
if(bk == NULL){
printf("归还失败,读者未借阅此书!\n");
return 0;
}
Node* t = bk->id;
if(t->next == NULL){
printf("归还失败,读者未借阅此书!\n");
return 0;
}
Node* st = t->next;
t->next = st->next;
bk = searchBookByNameHelper(libary,bkname);
if(bk == NULL) //不存在
addBook(libary,bkname,st->data);
else{
Node* p = bk->id->next;
while(p != NULL){
if(p->data == st->data){
strcpy(p->readerName,"");
break;
}
p = p->next;
}
//不存在此ID
if(p == NULL){
p = bk->id;
Node* tp = (Node*)malloc(sizeof(Node));
tp->data = st->data;
strcpy(tp->readerName , "");
tp->next = p->next;
p->next = tp;
}
}
free(st);
bk->inNum++;
bk->outNum--;
printf("归还成功!\n");
return 1;
}
void ForAdmin(){
while(1){
showAdmin();
int choice = 0;
scanf("%d",&choice);
if(choice == 0){
return;
}
else if(choice == 1){
char name[MAX] = "";
printf("输入新书的名称: \n");
scanf("%s",name);getchar();
int id = 0;
printf("输入新书的ID: \n");
scanf("%d",&id);
addBook(libary, name , id);
}
else if(choice == 2){
int ch = 0;
printf("按书名删除请按0,按ID删除请按1: \n");
scanf("%d",&ch);
if(ch == 0){
printf("请输入书名:\n");
char name[MAX] = "";
scanf("%s",name);getchar();
deleteBookByName(name);
}else if(ch == 1){
int id = 0;
scanf("%d",&id);
deleteBookByID(id);
}else{
printf("Error!\n");
}
}
else if(choice == 3){
char name[MAX] = "";
char newname[MAX] = "";
int id = 0;
int newid = 0;
printf("请输入被修改书籍的名称: \n");
scanf("%s",name);getchar();
printf("请输入被修改书籍的ID: \n");
scanf("%d",&id);
printf("请输入新书籍的名称: \n");
scanf("%s",newname);getchar();
printf("请输入新书籍的ID: \n");
scanf("%d",&newid);
changeBook(name,id,newname,newid);
}
else if(choice == 4){
int ch = 0;
printf("按书名查询请按0,按ID查询请按1: \n");
scanf("%d",&ch);
if(ch == 0){
printf("请输入书名:\n");
char name[MAX] = "";
scanf("%s",name);getchar();
searchBookByName(name);
}else if(ch == 1){
int id = 0;
scanf("%d",&id);
searchBookByID(id);
}else{
printf("Error!\n");
}
}
else if(choice == 5){
printf("请输入读者的名字\n");
char name[MAX] = "";
scanf("%s",name);getchar();
Readers* rd = reader;
Readers* p = (Readers*)malloc(sizeof(Readers));
strcpy(p->name,name);
p->allBooks = (Book*)malloc(sizeof(Book));
p->allBooks->id = (Node*)malloc(sizeof(Node));
p->allBooks->id->next = NULL;
p->allBooks->next = NULL;
p->next = rd->next;
rd->next = p;
printf("添加成功!\n");
}
else if(choice == 6){
printf("输入删除的读者的名字: \n");
char name[MAX] = "";
scanf("%s",name);getchar();
Readers* rd = reader;
int flag = 1;
while(rd->next != NULL){
if(strcmp(rd->next->name,name) == 0){
Readers* tp = rd->next;
rd->next = tp->next;
free(tp);
flag = 0;
printf("删除成功!\n");
break;
}
rd = rd->next;
}
if(flag == 1){
printf("不存在该读者!\n");
}
}
else if(choice == 7){
char name[MAX] = "";
char newname[MAX] = "";
printf("输入被修改的读者的名字: \n");
printf("输入被修改的读者的新名字: \n");
Readers* rd = findReader(name);
if(rd == NULL){
printf("不存在该读者!\n");
}else{
strcpy(rd->name,newname);
printf("修改成功!\n");
}
}
else if(choice == 8){
printf("请输入读者名字: \n");
char name[MAX]= "";
scanf("%s",name);getchar();
Readers* rd = findReader(name);
if(rd == NULL){
printf("未查询到!");
}else{
printf("读者名字: %s",name);
Book* bk = rd->allBooks->next;
printf("持有书籍: \n");
while(bk != NULL){
printf("%s: ",bk->name);
Node* tp = bk->id->next;
while(tp != NULL){
printf("%d",tp->data);
if(tp->next!=NULL)
printf(",");
tp = tp->next;
}
bk = bk->next;
}
}
}
else {
printf("Error!\n");
}
}
}