为了账号安全,请及时绑定邮箱和手机立即绑定

C++实现简单图书馆

标签:
C++

用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];
char
ptr2 = 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、报错都曾搞得我焦头烂额。最后做完时感到的是如释重负而不是大功告成的开心。
点击查看更多内容
6人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消