实验三:图书管理系统


实验目的

编写一个跨越三个文件的代码,包括 Library.cppLibrary.hMain.cpp。它应该包含与指定类相关的适当放置的声明和实现,并包含一个 main() 函数,以此满足在接受实验书籍和借阅者两个输入数据的基础上,模拟图书馆借书过程。此外,为梳理实验中各类的关系,需要进行类图的绘制。


实验过程

  • 编写一个书籍类

详细功能介绍: bookID 是书籍的 ID;title 是书籍的标题,接着是作者的名字authorFirstName和姓氏authorLastName,然后是书籍的出版年份(yearPublished),最后是一开始图书馆中持有的副本数量(totalCopies),还有当前可借阅的书籍副本数字段availableCopiesavailableCopies。

该类提供了一些列成员函数实现对应的功能,如返回书籍ID,获取当前书籍余量,获取书籍总数量,显示书籍信息,并模拟书籍借出的过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//图书类的声明
class BookRecord
{
private:
std::string bookID; // 书籍 ID 字段
std::string title; // 书籍标题字段
std::string authorFirstName; // 作者的名字字段
std::string authorLastName; // 作者的姓氏字段
int yearPublished; // 出版年份字段
int totalCopies; // 书籍总数字段
int availableCopies; // 仍可借阅的书籍副本数字段

public:
// 构造函数
BookRecord();
//有参构造函数
BookRecord(const std::string& bookID, const std::string& title, const std::string& authorFirstName,
const std::string& authorLastName, int yearPublished, int totalCopies);
// 析构函数
~BookRecord();
// 返回书籍 ID
std::string getBookID() const;
//获取当前书籍余量
int getavailableCopies()const;
//获取当前书籍总共数量
int gettotalCopies()const;
// 显示书籍信息
void display() const;
//书籍被借出,减去一本
void borrow();
};
  • 编写借阅者类

具体功能介绍:

其中,ID 是借阅者的ID号,必须是五位数字;first name last name 是借阅者的名字和姓氏,用空格分隔。numBooksLoaned 表示借阅者当前借阅的书籍数量,最后bookIDs[]数组表示当前借阅的书籍ID数组。

该类提供了2个成员函数,显示借阅者信息,并模拟借书过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//借阅者类的声明
class Borrower
{
private:
std::string ID; // ID 字段
std::string firstName; // 名字字段
std::string lastName; // 姓氏字段
int numBooksLoaned; // 借阅的书籍数量字段
std::string bookIDs[6]; // 当前借阅的书籍ID数组

public:
// 构造函数
Borrower();
//有参构造函数
Borrower(const std::string& ID, const std::string& firstName, const std::string& lastName);
// 析构函数
~Borrower();
// 显示借阅者信息
void display() const;
//表示借阅者又借了一本书,存进书籍ID数组
void add(int cnt, std::string bookis);
};

编写书籍记录总数类(反映图书馆所有书籍)

具体功能介绍:

其中,定义了书籍记录总数totalBookRecords和上述书籍类的指针* bookRecords。

同时,该类提供了返回书籍记录总数和显示书籍记录两个成员函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//图书馆书籍总记录
class Catalogue
{
private:
// 书籍记录总数字段
int totalBookRecords;
public:
// BookRecords 数组,就是记录仪书籍使用的
BookRecord* bookRecords;
// 构造函数
Catalogue();
//有参构造函数
Catalogue(int numBookRecords);
// 析构函数
~Catalogue();
// 返回书籍记录总数
int getTotalBookRecords() const;
// 显示书籍记录
void displayBookRecords() const;
};
  • 编写一个 Library 类

具体功能介绍:

  1. 一个表示借出书籍总数的字段:totalBooksOnLoan
  2. 一个表示借阅者总数的字段:totalBorrowers
  3. 一个 Catalogue 对象。
  4. 一个借阅者对象数组,* borrowers。
  5. 一个成员函数displayBookRecords,显示借出书籍总数、书籍记录总数并显示各个书籍记录。
  6. 一个成员函数displayBorrowerRecords,显示借阅者总数和各个借阅者记录。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Library
{
private:
// 总借出的书籍数量字段
int totalBooksOnLoan;
// 总借阅者数量字段
int totalBorrowers;
public:
// Catalogue 对象指针
Catalogue* catalogue;
// Borrower 对象指针
Borrower* borrowers;
// 构造函数
Library(int numBookRecords, int numBorrowers);
// 析构函数
~Library();
// 显示书籍记录
void displayBookRecords();
// 显示借阅者记录
void displayBorrowerRecords();
//图书馆工作函数,也就是程序相对而言的主函数
void work(int booknums, int borrowernums);
};

解决方案一览

Library.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#pragma once

#include<iostream>
#include<string>

// 防止头文件重用
#ifndef LIBRARY_H
#define LIBRARY_H

// 书籍记录类
// 主要是记录书籍
// 其中包含了书籍的基本信息以及用于获取和显示这些信息的函数。

// 图书类的声明
class BookRecord
{
private:
std::string bookID; // 书籍 ID 字段
std::string title; // 书籍标题字段
std::string authorFirstName; // 作者的名字字段
std::string authorLastName; // 作者的姓氏字段
int yearPublished; // 出版年份字段
int totalCopies; // 书籍总数字段
int availableCopies; // 仍可借阅的书籍副本数字段

public:
// 构造函数
BookRecord();

// 有参构造函数
BookRecord(const std::string& bookID, const std::string& title, const std::string& authorFirstName,
const std::string& authorLastName, int yearPublished, int totalCopies);

// 析构函数
~BookRecord();

// 返回书籍 ID
std::string getBookID() const;

// 获取当前书籍余量
int getAvailableCopies() const;

// 获取当前书籍总共数量
int getTotalCopies() const;

// 显示书籍信息
void display() const;

// 书籍被借出,去一本
void borrow();

//重载赋值运算符
//BookRecord& operator=(BookRecord bookRecord);
};

// 借阅者类的声明
class Borrower
{
private:
std::string ID; // ID 字段
std::string firstName; // 名字字段
std::string lastName; // 姓氏字段
int numBooksLoaned; // 借阅的书籍数量字段
std::string bookIDs[6]; // 当前借阅的书籍ID数组

public:
// 构造函数
Borrower();

// 有参构造函数
Borrower(const std::string& ID, const std::string& firstName, const std::string& lastName);

// 析构函数
~Borrower();

// 显示借阅者信息
void display() const;

// 表示借阅者又借了一本书,存进书籍ID数组
void add(int cnt, std::string bookis);

//重载赋值运算符有
// Borrower& operator=(Borrower borrower);
};

// 图书馆书籍总记录
class Catalogue
{
private:
// 书籍记录总数字段
int totalBookRecords;

public:
// BookRecords 数组,就是记录仪书籍使用的
BookRecord* bookRecords;

// 构造函数
Catalogue();

// 有参构造函数
Catalogue(int numBookRecords);

// 析构函数
~Catalogue();

// 返回书籍记录总数
int getTotalBookRecords() const;

// 显示书籍记录
void displayBookRecords() const;
};

class Library
{
private:
// 总借出的书籍数量字段
int totalBooksOnLoan;

// 总借阅者数量字段
int totalBorrowers;

public:
// Catalogue 对象指针
Catalogue *catalogue;

// Borrower 对象指针
Borrower* borrowers;

//默认构造函数
Library();

// 构造函数
Library(int numBookRecords, int numBorrowers);

// 析构函数
~Library();

// 显示书籍记录
void displayBookRecords();

// 显示借阅者记录
void displayBorrowerRecords();

// 图书馆工作函数,也就是程序相对而言的主函数
void work();

//展示总共借出书籍总数
int showtotalBooksOnLoan()const;

//展示借书人数
int showtotalBoorrowers()const;
};

#endif // LIBRARY_H

//图书馆要有一个工作函数,有一个初始化函数,初始化究竟有谁借书
//同时里面要记录书名
//还有减去总数和还可以借的要减去
//如果书籍不够了,就要提醒这个人不能借书了
//差不多就这样

Library.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
#include"Library.h"
#include<iostream>

// 默认构造函数
BookRecord::BookRecord()
{
this->bookID = "";
this->title = "";
this->authorFirstName = "";
this->authorLastName = "";
this->totalCopies = 0;
this->availableCopies = 0;
this->yearPublished = 2020;
}
//有参构造函数
BookRecord::BookRecord(const std::string& bookID, const std::string& title, const std::string& authorFirstName, const std::string& authorLastName, int yearPublished, int totalCopies)
: bookID(bookID), title(title), authorFirstName(authorFirstName), authorLastName(authorLastName), totalCopies(totalCopies), availableCopies(totalCopies)
{
//出版年份的特别判断
//不为1也不为2就直接提示用户并且退出程序
if (yearPublished / 1000 != 1 && yearPublished / 1000 != 2)
{
std::cout << "出版年份不符合现实" << std::endl;
exit(0);
}
else
{
this->yearPublished = yearPublished;
//赋值年份
}
}
//析构函数
//不需要管理动态内存
BookRecord::~BookRecord() {}

// 返回书籍 ID
std::string BookRecord::getBookID() const
{
return this->bookID;
}

//返回书籍可供借阅数
int BookRecord::getAvailableCopies()const
{
return this->availableCopies;
}

//返回书籍总数
int BookRecord::getTotalCopies()const
{
return this->totalCopies;
}

//书籍个数减去一,代表该书已经被借出
void BookRecord::borrow()
{
this->availableCopies--;
}

// 显示书籍信息
void BookRecord::display() const
{
std::cout << "Information:" << std::endl;
std::cout << "Book ID: " << bookID << std::endl;
std::cout << "Title: " << title << std::endl;
std::cout << "Author: " << authorFirstName << " " << authorLastName << std::endl;
std::cout << "Year published: " << yearPublished << std::endl;
std::cout << "Total number of copies: " << totalCopies << std::endl;
std::cout << "Number available for loan: " << availableCopies << std::endl;
}
/*
BookRecord& BookRecord::operator=(BookRecord bookRecord)
{
//bookID, title, authorFirstname, authorLastname, yearname, totalcopies
this->bookID = bookRecord.bookID;
this->title = bookRecord.title;
this->authorFirstName = bookRecord.authorFirstName;
this->authorLastName = bookRecord.authorLastName;
this->yearPublished = bookRecord.yearPublished;
this->totalCopies = bookRecord.totalCopies;
this->availableCopies = bookRecord.availableCopies;
return *this;
}
*/
// 构造函数进行初始化
Borrower::Borrower()
{
this->ID = "";
this->firstName = "";
this->lastName = "";
for (int i = 1; i <= 5; i++)
{
this->bookIDs[i] = "";
}
this->numBooksLoaned = 0;
}
Borrower::Borrower(const std::string& ID, const std::string& firstName, const std::string& lastName)
: firstName(firstName), lastName(lastName), numBooksLoaned(0)
{
if (ID.length() != 4)
{
std::cout << "用户ID不符合规范,程序终止" << std::endl;
exit(0);
}
else
{
this->ID = ID;
}
for (int i = 1; i <= 5; i++)
{
this->bookIDs[i] = "";
}
}
// 析构函数
Borrower::~Borrower()
{
if (bookIDs != nullptr)
{
delete[] bookIDs;
}
//需要释放 bookIDs 数组的内存
//防止内存泄漏
//注意需要防止内存二次释放
}

// 显示借阅者信息
void Borrower::display() const
{
std::cout << "Information" << ":" << std::endl;
std::cout << "Borrower ID: " << ID << std::endl;
std::cout << "Name: " << firstName << " " << lastName << std::endl;
std::cout << "Number of loaned books: " << numBooksLoaned << std::endl;
if (numBooksLoaned == 0)
{
std::cout << "Not borrow any books" << std::endl;
}
else if (numBooksLoaned > 0)
{
std::cout << "IDs of books on loan: ";
for (int i = 1; i <= numBooksLoaned; ++i)
{
std::cout << "No." << i << ":" << bookIDs[i] << " "<<std::endl;
}
std::cout << std::endl;
}
}
//添加借阅的书籍
void Borrower::add(int cnt, std::string bookid)
{
if (cnt > 5)
{
std::cout << "You have borrowed 5 books." << std::endl;
std::cout << "Please return the borrowed books before borrowing more from the Library of Souls" << std::endl;
}
else
{
this->bookIDs[cnt] = bookid;
this->numBooksLoaned++;
}
}
/*
Borrower& Borrower::operator=(Borrower borrower)
{
//ID, firstname, lastname
this->ID = borrower.ID;
this->firstName = borrower.firstName;
this->lastName = borrower.lastName;
for (int i = 1; i <= 5; i++)
{
this->bookIDs[i] = "";
}
this->numBooksLoaned = 0;
return *this;
}
*/

// 构造函数
Catalogue::Catalogue() {}

//有参构造函数
Catalogue::Catalogue(int numBookRecords) : totalBookRecords(numBookRecords)
{
// 分配存储空间
bookRecords = new BookRecord[numBookRecords+1];
}

// 析构函数
Catalogue::~Catalogue()
{
//防止重复释放
// 注意释放存储空间
if (bookRecords != nullptr)
{
delete[] bookRecords;
bookRecords = nullptr;
}
}

// 返回书籍记录总数
int Catalogue::getTotalBookRecords() const
{
return this->totalBookRecords;
}

//显示书籍记录
void Catalogue::displayBookRecords() const
{
for (int i = 1; i <= totalBookRecords; ++i)
{
std::cout << "Book Record " << i << std::endl;
std::cout << "=============" << std::endl;
bookRecords[i].display();
std::cout << std::endl;
}
}

//默认构造函数

Library::Library(){}

// 构造函数
Library::Library(int numBookRecords, int numBorrowers)
: totalBooksOnLoan(numBookRecords), totalBorrowers(numBorrowers)
{
// 初始化 Catalogue 对象指针
catalogue = new Catalogue(numBookRecords + 1);
// 初始化 Borrower 对象指针数组
borrowers = new Borrower[numBorrowers + 1];
}

// 析构函数
Library::~Library()
{
// 释放 Catalogue 对象指针的内存
if (catalogue!=nullptr)
{
delete catalogue;
catalogue = nullptr;
}
// 释放 Borrower 对象指针数组的内存
if (borrowers != nullptr)
{
delete[] borrowers;
borrowers = nullptr;
}
}

// 显示书籍记录
void Library::displayBookRecords()
{
this->catalogue->displayBookRecords();
}

// 显示借阅者记录
void Library::displayBorrowerRecords()
{
for (int i = 1; i <= totalBorrowers; ++i)
{
std::cout << "Borrower " << i << ":" << std::endl;
borrowers[i].display();
std::cout << std::endl;
}
}

//展示借书总数
int Library::showtotalBooksOnLoan()const
{
return this->totalBooksOnLoan;
}

//展示借阅者总数
int Library::showtotalBoorrowers()const
{
return this->totalBorrowers;
}

void Library::work()
{
int booknums;
int borrowernums;
booknums = this->showtotalBooksOnLoan();
borrowernums = this->showtotalBoorrowers();
for (int i = 1; i <= booknums; i++)
{
std::string bookID;
std::string title;
std::string authorFirstname;
std::string authorLastname;
int yearname;
int totalcopies;
int availableCopies;
//输入书籍ID
std::cout << "please input the bookID" << std::endl;
std::cin >> bookID;
//输入title,以;进行分割
std::cout << "please input the title" << std::endl;
std::getline(std::cin, title, ';');
//输入名字
std::cout << "please input the authorFisrtname" << std::endl;
std::cin >> authorFirstname;
//输入姓氏
std::cout << "please input the authorLastname" << std::endl;
std::cin >> authorLastname;
//输入年林
std::cout << "please input the yearname" << std::endl;
std::cin >> yearname;
//输入书籍总数
std::cout << "please input the totalcopies" << std::endl;
std::cin >> totalcopies;
//初始时书籍总数等于书籍空余总数
availableCopies = totalcopies;
//定义BookRecord对象
BookRecord bookRecord(bookID, title, authorFirstname, authorLastname, yearname, totalcopies);
//存进数组
this->catalogue->bookRecords[i] = bookRecord;
this->catalogue->bookRecords[i].display();
}
for (int i = 1; i <= borrowernums; i++)
{
/*
std::string ID; // ID 字段
std::string firstName; // 名字字段
std::string lastName; // 姓氏字段
int numBooksLoaned; // 借阅的书籍数量字段
std::string bookIDs[6]; // 当前借阅的书籍ID数组
*/
std::string ID;
std::string firstname;
std::string lastname;
int numBookloaned = 0;
std::cout << "please input the Id" << std::endl;
std::cin >> ID;
std::cout << "Please input the firstname" << std::endl;
std::cin >> firstname;
std::cout << "Please input the lastname" << std::endl;
std::cin >> lastname;
int nums;
std::cout << "How many books would you like to borrow?" << std::endl;
std::cin >> nums;
Borrower borrower(ID, firstname, lastname);
this->borrowers[i] = borrower;
int cnt = 0;
for (int j = 1; j <= nums; j++)
{
std::string bookid;
std::cout << "Please input the bookid" << std::endl;
std::cin >> bookid;
//要借阅的书籍
for (int k = 1; k <= booknums; k++)
{
if (this->catalogue->bookRecords[k].getBookID() == bookid)
{
if (this->catalogue->bookRecords[k].getAvailableCopies() == 0)
{
std::cout << "很抱歉" << "编号为" << ID << "的这本书已经没有余量了,请继续借阅其他书籍" << std::endl;
break;
}
else
{
this->catalogue->bookRecords[k].borrow();
//直接书籍减去
this->borrowers[i].add(++cnt, bookid);
break;
}

}
}
}
}
std::cout << "what can I say" << std::endl;
std::cout << "Library out!!!" << std::endl;
}

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
#include"Library.h"
int main()
{
//所要求输入信息为二:
//书籍信息
//借阅者信息
//其余一切信息来自于工作区函数
//每次最多借阅数量为5本
std::cout << "Welcome to the library of souls" << std::endl;
std::cout << "In this library system, books have the following attributes:" << std::endl;
std::cout << "- Book ID" << std::endl;
std::cout << "- Book title" << std::endl;
std::cout << " - Author's first and last name" << std::endl;
std::cout << " - Publication date" << std::endl;
std::cout << " - Total quantity of the book" << std::endl;
std::cout << "In this library system, borrowers have the following characteristics: " << std::endl;
std::cout << "ID, last name, summary of borrowed books, and borrowed book IDs." << std::endl;
std::cout << "Now please input the number of books in the library and the number of borrowers in the library" << std::endl;
int booknums;
int borrowernums;
std::cin >> booknums >> borrowernums;
//创建一个图书馆对象,用以初始化不同的信息
//借阅者信息和书籍信息
Library library(booknums, borrowernums);
//该图书馆开始工作
library.work();
return 0;
}

实验结果

经测试,实验结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Welcome to the library of souls
In this library system, books have the following attributes:
- Book ID
- Book title
- Author's first and last name
- Publication date
- Total quantity of the book
In this library system, borrowers have the following characteristics:
ID, last name, summary of borrowed books, and borrowed book IDs.
Now please input the number of books in the library and the number of borrowers in the library
1
1
please input the bookID
0001
please input the title
English
;
please input the authorFisrtname
Simith
please input the authorLastname
Jack
please input the yearname
1991
please input the totalcopies
12
Information:
Book ID: 0001
Title:
English

Author: Simith Jack
Year published: 1991
Total number of copies: 12
Number available for loan: 12
please input the Id
0001
Please input the firstname
Simith
Please input the lastname
Nick
How many books would you like to borrow?
1
Please input the bookid
0001
成功借书

心得体会

通过本次实验,我编写较为冗长,功能较为齐全的代码的能力有所提升,同时,我对设计思想中的类中功能应该避免继承而是应该多用组合,多调用接口有了更深一步的认知。