用C++写一个小型图书馆系统,要求功能:
1.在控制台打印现有书单。
2.录入新书。
3.删除书籍。
4.将现有书单写入TXT文件。
5.从TXT文件读入书单。
6.按不同要求排序书籍。
7.找到书名最长的书。
由于这是大一上学期的期末作业,并没有学到链表,甚至连类都没有学,只能用结构体数组实现书单。
#define MAXLENAUTHOR 40//作者名长度限制
#define MAXLENBOOK 50//书名长度限制
enum Categbook { Science_Fiction, Fiction, Classic };//书籍的类型
int capacity = 6;//数组大小
int numbook = 5;//书籍数量
struct BOOK { bool tag = false;
char author[MAXLENAUTHOR] = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
char title[MAXLENBOOK]="zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
int year = 2019; double price = 99999999.0; Categbook category=Science_Fiction; };
上面是一些基础的变量和书籍结构体。
在这里我用tag标记书籍,tag为true代表书存在。为的就是删除书籍的时候不用重新new一个动态数组,但这样偷懒的举动给我带来了很多的麻烦。所有变量初始化时为了方便排序。还有就是我在数组大小和书本数量上用了全局变量,其实可以把他们写进一个新结构体中,比如:
struct BOOKLIST {int capacity;int numbook;BOOK *booklist;};
然后,我们建立一个BOOK类型的动态数组,并写一个switch函数
BOOK *booklist = new BOOK[capacity];
char in;
while(1)
{
mainjiemian();
cin >> in;
switch (in) {
case'1':
bookinfo(booklist);
system("cls");
break;
case'2':
addbook(booklist);
system("cls");
break;
case'3':
delbook(booklist);
system("cls");
break;
case'4':
write(booklist);
system("cls");
break;
case'5':
read(booklist);
system("cls");
break;
case'6':
system("cls");
sortbook(booklist);
system("cls");
break;
case'7':
findbook(booklist);
system("cls");
break;
case'8':
delete[]booklist;//退出程序前一定要delete掉动态数组
exit(0);
case'9':
system("cls");
inibook(*&booklist);
system("cls");
break;
default:cout << "Illegal input" << endl;
}
}
然后就开始按照switch来一步步写函数了:
- 检查数组是否满容
void examination(BOOK *&booklist)
{
if (capacity == numbook)
{
printf("Began to expand the array.\n");
BOOK *newbooklist = new BOOK[capacity + addsize];
for (int i = capacity; i < (capacity+addsize); i++) {
newbooklist[i].tag = false;
numbook = 0;
}
for (int i = 0; i < capacity; i++) {
if (booklist[i].tag == true) {
newbooklist[i] = booklist[i];
numbook++;
}
}
delete[]booklist;//删除旧指针指向的空间
capacity = capacity + addsize;
booklist = newbooklist;//将指针指向新分配的空间
newbooklist = nullptr;
}
}
- 初始化书单
void inibook(BOOK *&booklist)
{
for (int i = 0; i < (capacity); i++) {
booklist[i].tag = false;//所有书籍的标记为false
numbook = 0;
}
}
- 打印书单
void bookinfo(BOOK *&booklist)
{
printf("\nnumbook: %d\ncapacity: %d\n",numbook,capacity);
for (int i = 0; i < capacity; i++) {
if (booklist[i].tag == true) {
printf("\nThe number of the book is: %d", i);
printf("\nTitle: %s\nAuthor: %s\nCategory: %s\nYear of release: %d\nPrice: %.2f YUAN\n", booklist[i].title, booklist[i].author, categoryStrings[booklist[i].category], booklist[i].year, booklist[i].price);
}
}
system("pause");
}
- 删除书籍
void delbook(BOOK *&booklist)
{
if (numbook < 1) {
printf("There is no book in the booklist!\n");
}
else {
int i;
printf("\nPlease input the number of book you want to delete:");
scanf("%d", &i);
if (i > capacity) {
printf("This book does not exist!\n");
}
else {
booklist[i].tag = false;
numbook--;
}
}
system("pause");
}
此处应当做两个判断:书柜中是否有书和要删除的书是否存在。
- 录入新书
void addbook(BOOK *&booklist)
{
int i;
for ( i = 0; i < capacity; i++) {
if (booklist[i].tag == false) {
break;
}
}
printf("\nINFORMATIONS FOR THE BOOK\n\n");
printf("The number of the book you are about to add is: %d\n", i);
booklist[i].tag = true;
char bookname[MAXLENBOOK];
printf("Please input the name of the book:");
scanf("%s", bookname);
getchar();
sprintf_s(booklist[i].title, MAXLENBOOK, "%s", bookname);
char authorname[MAXLENAUTHOR];
printf("Please input the name of the author:");
scanf("%s", authorname);
getchar();
sprintf_s(booklist[i].author, MAXLENAUTHOR, "%s", authorname);
int year = 0;
while (1)
{
printf("Please input the year of release:");
scanf("%d", &year);
getchar();
if (year < -5000 || year>2018)
{
printf("\nYour input is illegal.Try again.\n");
}
else
{
booklist[i].year = year;
break;
}
}
float price = 0.0;
while (1)
{
printf("Please input the price of the book:");
scanf("%f", &price);
getchar();
if (price < 0)
{printf("\nYour input is illegal.Try again.");}
else
{booklist[i].price = price;
break;}
}
int categ;
while (1)
{
printf("\n");
for (int i = 0; i < sizeof(categoryStrings) / sizeof(categoryStrings[0]); i++)
{
printf("\n%d.%s", i + 1, categoryStrings[i]);
}
printf("\nPlease input the number of category of the book:");
scanf("%d", &categ);
getchar();
if (categ<1 || categ> sizeof(categoryStrings) / sizeof(categoryStrings[0]))
{
printf("\nYour input is illegal.Try again.");
}
else
{
booklist[i].category = (Categbook)(categ - 1);
break;
}
}
numbook++;
printf("\n\nEND\n");
examination(booklist);
system("pause");
}
- 排序函数
void sortbook(BOOK *&booklist) { if (numbook < 2) { printf("No need to sort!\n"); system("pause"); } else { char ins; while (1) { sortjiemian(); cin >> ins; switch (ins) { case'1': for (int i = 0; i < capacity; i++) { int m = i; for (int j = i + 1; j < capacity; j++) { if (CmpStr(booklist[m].author, booklist[j].author) > 0) { m = j; } } if (i != m) { Swapbook(booklist[i], booklist[m]); } } printf("Sorted booklist is:"); bookinfo(booklist); break; case'2': for (int i = 0; i < capacity; i++) { int m = i; for (int j = i + 1; j < capacity; j++) { if (CmpStr(booklist[m].title, booklist[j].title) > 0) { m = j; } } if (i != m) { Swapbook(booklist[i], booklist[m]); } } printf("Sorted booklist is:"); bookinfo(booklist); break; case'3': for (int i = 0; i < capacity; i++) { int m = i; for (int j = i + 1; j < capacity; j++) { if (CmpInt(booklist[m].year, booklist[j].year) > 0) { m = j; } } if (i != m) { Swapbook(booklist[i], booklist[m]); } } printf("Sorted booklist is:"); bookinfo(booklist); break; case'4': for (int i = 0; i < capacity; i++) { int m = i; for (int j = i + 1; j < capacity; j++) { if (CmpFloat(booklist[m].price, booklist[j].price) > 0) { m = j; } } if (i != m) { Swapbook(booklist[i], booklist[m]); } } printf("Sorted booklist is:"); bookinfo(booklist); break; case'5': for (int i = 0; i < capacity; i++) { int m = i; for (int j = i + 1; j < capacity; j++) { if (CmpInt(booklist[m].category, booklist[j].category) < 0) { m = j; } } if (i != m) { Swapbook(booklist[i], booklist[m]); } } printf("Sorted booklist is:"); bookinfo(booklist); break; case'6': mainjiemian(); break; default:cout << "Illegal input" << endl; } break; } } mainjiemian();
}
int CmpStr(char pp1, char pp2)//比较两个字符串长度
{
int nResult;
char pa, pb, a, b;
pa = pp1;
pb = pp2;
do
{
a = pa;
b = pb;
pa++;
pb++;
} while ((a == b) && (a != 0) && (b != 0));
nResult = a - b;
return nResult;
}
void Swapbook(BOOK& book1, BOOK& book2)//交换函数
{
BOOK temp = book1;
book1 = book2;
book2 = temp;
}
int CmpInt(int a, int b)//比较两个int类型变量
{
return a - b;
}
int CmpFloat(float a, float b)//比较两个float类型变量
{
int nResult;
if (a - b > 0)
{ nResult = 1;}
if ( a - b < 0)
{ nResult = -1;}
if ( a - b == 0.0)
{ nResult = 0;}
return nResult;
}
老师希望我们把排序函数写成一个,只需要传递不同的参数就可以对所有项目排序,但是那样要多写好几个函数,而且实现起来效果差不多,所以我只写了比较函数和交换函数(其实是嫌麻烦不想写)。
这里还要加一个判断,如果书柜中书记数量小于1,那么就不需要排序。
- 找出书名最长的书
void findbook(BOOK *booklist)
{
int j = 0;
int n = 0;
char*a = new char[capacity];
for (int q = 0; q < capacity; q++) {
a[q] = new char[MAXLENBOOK];
}
for (int i = 0; i < capacity; i++) {
if (booklist[i].tag == 1) {
sprintf_s(a[j], MAXLENBOOK, "%s", booklist[i].title);
j++;
}
}
for (int z = 0; z < j; z++) {
charptr1 = a[z];
charptr2 = a[n];
if (strlen(ptr1) > strlen(ptr2)) {
n = z;
}
}
for (int i = 0; i < j; i++) {
char*ptr1 = a[n];
char*ptr2 = a[i];
if (strlen(ptr1) == strlen(ptr2)) {
printf("The book with the longest name is:%s.\n", a[i]);
}
}
for (int p = 0; p < capacity; p++)
delete[] a[p];
delete[] a;
system("pause");
}
我将所有书名写入一个新数组再比较他们的长度,找到最长的那一个。我觉得这是个效率很低的方法,但想不出其他方法了。
我考虑到可能会有同名书籍的存在,于是加了一个循环。
- 将书单写入TXT文件和从TXT中读取
void write(BOOK &booklist)
{
FILE fp = NULL;
if (NULL == (fp = fopen("lab6.txt", "w")))
{
printf("error");
}
else {
for (int i = 0; i < capacity; i++) {
if (booklist[i].tag == true) {
BOOK book = booklist[i];
fprintf(fp, "Title: %s\nAuthor: %s\nCategory: %d\nYear of release: %d\nPrice: %lf YUAN\n", book.title, book.author, book.category, book.year, book.price);
}
}
}
fclose(fp);
printf("Succeed!\n");
system("pause");
}
void read(BOOK *&booklist)
{
inibook(booklist);
FILE *fp = NULL;
if (NULL == (fp = fopen("lab6.txt", "r")))
{
printf("Error");
}
else {
int i = 0;
numbook = 0;
while (!feof(fp))
{
fscanf(fp, "Title: \n%[^\n]\nAuthor: \n%[^\n]\nCategory: %d\nYear of release: %d\nPrice: %lf YUAN\n", &booklist[i].title, &booklist[i].author, &booklist[i].category, &booklist[i].year, &booklist[i].price);
booklist[i].tag = true;
numbook++;
i++;
examination(booklist);
}
}
fclose(fp);
printf("Succeed!\n");
system("pause");
}
讲道理这两个都是按格式写就会没问题的函数,但是,write函数很好很ok,但read函数各种不合作,根本不工作。在我苦思冥想之后,终于发现问题是出在“%s”上。“%s”在读取时遇到空格或者空行就会停止读取,导致整个函数无法按照正确的预设的格式读取。情况就是:文件也正常打开了,指针也没问题,就是一直读啊读,没个完。
最后我用了“\n%[^\n]”这个指令来读取整行字符。网上推荐的"%[^\n]%*c"指令好像在我的程序不起作用
- 界面函数
void mainjiemian()
{
cout << "" << endl;
cout << " library " << endl;
cout << " " << endl;
cout << " (1) Show existing books " << endl;
cout << " " << endl;
cout << " (2) Add a new book " << endl;
cout << " " << endl;
cout << " (3) Delete book(s) " << endl;
cout << " " << endl;
cout << " (4) Write the books to the file " << endl;
cout << " " << endl;
cout << " (5) Read the books from the file " << endl;
cout << " " << endl;
cout << " (6) Sort books " << endl;
cout << " " << endl;
cout << " (7) Find the book with the longest name " << endl;
cout << " " << endl;
cout << " (8) Exit " << endl;
cout << "" << endl;
cout << "Please select an option:" << endl;
}
void sortjiemian()
{
cout << "**" << endl;
cout << " Sort options " << endl;
cout << " " << endl;
cout << " (1) Sort by author " << endl;
cout << " " << endl;
cout << " (2) Sort by name " << endl;
cout << " " << endl;
cout << " (3) Sort by year " << endl;
cout << " " << endl;
cout << " (4) Sort by price " << endl;
cout << " " << endl;
cout << " (5) Sort by category " << endl;
cout << " " << endl;
cout << " (6) exit " << endl;
cout << "**" << endl;
cout << "Please select an option:" << endl;
}
最后就是和switch配套的两个界面函数了。
现在想想这个程序也不是很难,但在做的过程中各种层出不穷奇奇怪怪的BUG、报错都曾搞得我焦头烂额。最后做完时感到的是如释重负而不是大功告成的开心。