#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)

图书登记管理程序

问题描述:

请设计一个图书登记管理程序,以方便图书管理员管理图书馆内的图书,该程序应该具有以下功能:
(1)从键盘输入某本图书的信息
(2)给定书号(ISBN),显示该图书的信息。
(3)给定图书的作者,显示所有该作者所著的图书。
(4)给定书号(ISBN),修改该图书的信息。
(5)给定书号(ISBN),删除该图书的信息。

题目要求:

(1)按照分析、设计、编码、调试、测试的软件过程完成这个应用程序。
(2)图书信息应该包含 书号、图书名称、图书出版社、图书作者(假设一个作者)、图书价格、出版时间。
(3)为各项操作功能设计一个菜单,应用程序运行后,先显示这个菜单,然后用户通过菜单项选择希望进行的操作项目。
输入要求:
(1)应用程序运行后在屏幕上显示一个菜单。用户可以根据需求,选定相应的操作项目。进入每个操作后,根据应用程序的提示信息,从键盘输入相应的信息。程序根据用户输入的信息完成相应的处理,实现要求的功能。
(2)能对输入的数据进行简单的校验,例如,出版时间必须是一个合法的日期格式,国际标准书号是唯一的(一个国际标准书号对应一种图书信息)。

输出要求:

(1)应用程序运行后,要在屏幕上显示一个菜单。
(2)要求用户输入数据时,给出清晰、明确的提示信息,包括输入的数据内容、格式以及结束方式等。
(3)在程序完成处理后,要清楚地给出程序的处理结果。例如,在给定国际标准书号删除图书信息时,如果该图书不存在,要提示没能删除,如果删除成功要提示删除成功。
实现要求:
(1)在程序中使用链表存储图书信息。
(2)采用模块化程序设计的方法,将程序中的各项功能用函数实现。
提示:
(1)使用结构体表示图书信息,一个结点保存一条图书信息。

扩展功能:

(1)提供一些统计功能。例如统计每个出版社的图书种类数,统计每个作者的图书种类数。
(2)图书信息从文件读入。
(3)将图书信息保存到文件中。

系统主要包括功能:

  1. 显示功能界面
  2. 添加书本信息
  3. 查看指定书本信息
  4. 修改指定书本的信息
  5. 删除指定书本的信息
  6. 统计按(出版社)分类计数
  7. 统计按(作者)分类计数
  8. 从文件读入信息
  9. 将信息输出到文件

程序测试与结果

1. 添加书本信息

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第1张图片

1) 正常输入时

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第2张图片

2) 多次输入错误时,自动退出

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第3张图片
#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第4张图片

3) 输入ISBN号不唯一,提示有误

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第5张图片

4) 输入的日期有误时,提示重新输入

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第6张图片

2. 查看书本信息(通过ISBN号指定)
1) 正常情况

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第7张图片

2) 当程序中还未保存信息时,提示暂未存储数据

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第8张图片

3) 当输入的ISBN号不存在时,提示没有找到

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第9张图片

3. 查看指定作者的所有书本信息
1) 正常情况

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第10张图片

2) 输入的作者名不存在时,提示找不到

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第11张图片

4. 修改指定书本信息
1) 正常情况

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第12张图片
#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第13张图片

2) 当输入指定的ISBN号有误时,提示找不到书本

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第14张图片

3) 当输入更新的ISBN号有误时,重新输入;多次输入有误时,不更新数据,重新选择

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第15张图片

4) 当输入更新的日期有误是,重新输入;多次输入有误时,不更新数据,重新选择(此图片未更新,以代码运行效果为准)

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第16张图片

5. 删除指定书本信息
1) 正常情况

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第17张图片

2) 输入的ISBN号不存在时,提示找不到

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第18张图片

3) 当程序中还未保存信息时,提示暂未存储数据

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第19张图片

6. 按出版社分类,统计书的数量
1) 正常情况

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第20张图片

2) 当程序中还未保存信息时,提示暂未存储数据

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第21张图片

7. 按作者分类,统计书的数量
1) 正常情况

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第22张图片

2) 当程序中还未保存信息时,提示暂未存储数据

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第23张图片

8. 从指定文件中读取数据
1) 正常情况

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第24张图片
#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第25张图片

2) 当输入的路径有误时,提示读取文件失败

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第26张图片

3) 当指定的文件中读取的数据有错误时,提示已添加的数据量及碰见的错误

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第27张图片
#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第28张图片

9. 将数据写入指定文件中
1) 正常情况

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第29张图片
#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第30张图片

2) 输入的文件不存在时,会新建文件

#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第31张图片
#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第32张图片
#c语言 #课程设计 #链表 #结构体 #文件 #函数 #描述(图书登记管理程序)_第33张图片

源代码(可直接运行)

#include 
#include 
#include 
#include 

typedef struct books
{
    char isbn[18];
    char name[20];
    char author[9];
    char publisher[30];
    float price;
    char date[9]; // 时间格式20201212
    struct books *nextBooks;
} BOOKS, *PBOOKS;

/**
 * 声明所需函数:
 * 1 界面
 * 2 创建一个链表,初始化头结点
 * 3 添加信息 函数,生成一个结点,写入信息
 * 4 修改信息 函数,遍历链表,找到指定条件,修改结点中信息
 * 5 删除信息 函数,遍历链表,判断指定条件,删除结点
 * 扩展:
 * 6 统计 按(出版社)分类-->计数,创一个链表保存出版社的名称与书的数量,遍历输出
 * 7 统计 按(作者)分类-->计数,创一个链表保存作者的名称与书的数量,遍历输出
 * 8 从文件读入信息
 * 9 将信息 输出 到文件
 *
 * */

// 前置声明
void Interface();                   // 显示界面
void createLinked();                // 初始化链表
void add();                         // 添加书的信息
void findIsbn();                    // 通过isbn查找书的信息
int isbnEqual(char *, char *, int); // 判断两个isbn号是不是相等,参数3为长度,可以用作其它判断
void findName();                    // 通过作者名查找其所有书的信息
void isbnUpdate();                  // 通过isbn号修改指定书的信息
void isbnDelete();                  // 通过isbn号删除指定书的信息
void inputFile();                   // 通过文件读入书的记录
void outputFile();                  // 向指定文件中输出信息
void copy(char *, char *, int);     // 将参数2中的数据复制到参数1中,参数3为长度
int proofreadIbsn(char *);          // 判断isbn号的合法性
int sole(char *);                   // 判断指定isbn的唯一性,比较链表中的结点中存的值
int proofreadDate(char *);          // 判断日期的合法性
void countsAuthors();               // 统计 作者:书的数量
void conntsPublishers();            // 统计 出版社:书的数量

// 全局
PBOOKS pHead = NULL; // 链表头节点
PBOOKS pTail = NULL; // 尾结点

// 主函数
int main(int argc, char const *argv[])
{
    int option = 10;

    createLinked(); // 初始化链表

    while (option)
    {
        Interface();          // 打印菜单
        scanf("%d", &option); // 输入选项 ,输入0退出
        fflush(stdin);
        switch (option)
        {
        case 1:
            system("CLS");
            add();
            option = 10;
            break;
        case 2:
            system("CLS");
            findIsbn();
            option = 10;
            break;
        case 3:
            system("CLS");
            findName();
            option = 10;
            break;
        case 4:
            system("CLS");
            isbnUpdate();
            option = 10;
            break;
        case 5:
            system("CLS");
            isbnDelete();
            option = 10;
            break;
        case 6:
            system("CLS");
            conntsPublishers();
            option = 10;
            break;
        case 7:
            system("CLS");
            countsAuthors();
            option = 10;
            break;
        case 8:
            system("CLS");
            inputFile();
            option = 10;
            break;
        case 9:
            system("CLS");
            outputFile();
            option = 10;
            break;
        case 0:
            system("CLS");
            exit(-1);
            break;
        default:
            system("CLS");
            printf("输入不能识别,请输入正确的选项!\n");
            option = 10;
            break;
        }
    }
    return 0;
}

void Interface()
{
    printf("====================图书登记管理程序====================\n");
    printf("    -->(1) 添加书本信息\n");
    printf("    -->(2) 通过书号(ISBN),查看书本信息\n");
    printf("    -->(3) 通过作者名,查看其所有书本信息\n");
    printf("    -->(4) 通过书号(ISBN),修改书本信息\n");
    printf("    -->(5) 通过书号(ISBN),删除书本信息\n");
    printf("    扩展:\n");
    printf("    -->(6) 统计 按(出版社)分类-->计数\n");
    printf("    -->(7) 统计 按(作者)分类-->计数\n");
    printf("    -->(8) 从文件读入书本信息\n");
    printf("    -->(9) 将信息输出到文件\n");
    printf("    -->(0) 退出此程序\n");
    printf("\n请输入你的选择:");
}
void createLinked()
{
    pHead = (PBOOKS)malloc(sizeof(BOOKS)); // 生成1个结点,做头节点
    if (pHead == NULL)
    {
        printf("分配失败,程序终止\n");
        exit(-1);
    }

    pTail = pHead; // Tail中的地址是头节点
    pTail->nextBooks = NULL;

    return;
}

void add()
{
    printf("====================图书登记管理程序====================");
    printf("\n已进入添加书本信息选项中:\n");
    int i = 0;
    char input = 'y';
    while (input == 'y')
    {
        PBOOKS pNew = (PBOOKS)malloc(sizeof(BOOKS)); // PBOOKS pNew  表示 struct Node * ; pNew 每次循环生成一个结点,将地址赋给pNew,进行处理
        if (pNew == NULL)
        {
            printf("分配失败,程序终止\n");
            exit(-1);
        }
        printf("请输入ISBN(例:978-962-215-001-0):");
        fflush(stdin);
        scanf("%s", &(pNew->isbn));

        int flag = 3;

        if (proofreadIbsn(pNew->isbn) && sole(pNew->isbn)) // 判断isbn的正确性
        {
            printf("校验成功\n"); // 合法,不做处理
        }
        else
        {
            while ((!(proofreadIbsn(pNew->isbn) && sole(pNew->isbn))) && --flag) // 合法返回1,取反,循环结束
            {

                memset(pNew->isbn, '\0', sizeof(pNew->isbn)); // 初始化 内存中的值
                // printf("\n多次输入错误%d\n",flag);
                printf("\n输入的ISBN有误,请重新输入\n");
                printf("请输入ISBN(例:978-962-215-001-0):");
                fflush(stdin);
                scanf("%s", &(pNew->isbn));
            }
            if (flag == 0)
            {
                printf("\n多次输入错误,自动退出\n");
                return;
            }
            printf("校验成功\n");
        }
        printf("请输入书名:");
        fflush(stdin);
        scanf("%s", &(pNew->name));

        printf("请输入作者:");
        fflush(stdin);
        memset(pNew->author, '\0', sizeof(pNew->author)); // 初始化 内存中的值
        scanf("%s", &(pNew->author));

        printf("请输入价格:");
        fflush(stdin);
        scanf("%f", &(pNew->price));

        printf("请输入出版社:");
        fflush(stdin);
        memset(pNew->publisher, '\0', sizeof(pNew->publisher)); // 初始化 内存中的值
        scanf("%s", &(pNew->publisher));

        printf("请输入出版日期(例:20201212):");
        fflush(stdin);
        scanf("%s", &(pNew->date));

        if (proofreadDate(pNew->date)) // 判断日期的正确性
        {
            printf("校验成功\n"); // 合法,不做处理
        }
        else
        {
            flag = 3;
            while (!proofreadDate(pNew->date) && --flag) // 合法返回1,取反,循环结束,多次输入错误,退出
            {
                memset(pNew->date, '\0', sizeof(pNew->date)); // 初始化 内存中的值
                printf("\n输入的日期有误,请重新输入\n");
                printf("请输入出版日期(例:20201212):");
                fflush(stdin);
                scanf("%s", &(pNew->date));
            }
            if (flag == 0)
            {
                printf("\n多次输入错误,自动退出\n");
                return;
            }
            printf("校验成功\n");
        }

        pNew->nextBooks = NULL;
        pTail->nextBooks = pNew; // 第一次循环时,pTail中的地址是头节点,第二次循环时pTail中的地址是 第一次循环时生成的pNew中的地址
        pTail = pNew;            // 最新的结点充当尾结点
        printf("\n继续输入信息,请输入y,结束输入任意字符:");
        fflush(stdin);
        scanf("%c", &input);
        i++;
    }
    printf("添加%d条数据\n", i);
    return;
}
void findIsbn()
{
    printf("====================图书登记管理程序====================");
    printf("\n已进入通过书号(ISBN),查看书本信息选项中:\n");

    char isbnN[18];

    PBOOKS p = pHead->nextBooks; // 头指针->next(头节点的指针域),首结点

    if (p == NULL) // 没有首结点
    {
        printf("\n程序中暂未存储数据\n");
    }
    else
    {
        printf("请输入你要查找的ISBN:");
        memset(isbnN, '\0', sizeof(isbnN));
        fflush(stdin);
        scanf("%s", &isbnN);
        while (p != NULL) // 遍历
        {
            if (isbnEqual(p->isbn, isbnN, 18)) // 比较字符数组中的内容
            {
                printf("\nISBN\t\t\t书名\t作者\t出版社\t\t价格\t出版日期\n");
                printf("%s\t%s\t%s\t%s\t%.2f\t%s\n\n", p->isbn, p->name, p->author, p->publisher, p->price, p->date);
                return;
            }
            else
            {
                p = p->nextBooks;
            }
        }
        printf("\n程序中没有找到书本\n");
    }
    return;
}

int isbnEqual(char *a, char *b, int len)
{
    int result = 0;
    int i;
    for (i = 0; i < len - 1; i++)
    {
        if (*(a + i) == *(b + i))
        {
            result++;
            // printf("\n比对下标%d位%c^%c\n",i,*(a + i),*(b + i));
        }
        else
        {
            return 0;
        }
    }
    return result;
}

void copy(char *a, char *b, int len)
{
    int i;
    for (i = 0; i < len - 1; i++)
    {
        *(a + i) = *(b + i);
    }
    return;
}

int proofreadDate(char *a)
{
	// 下面只是简单的判断一下,没有考虑年、月份里的准确天数  (合理的应该是判断闰年,月份准确的有多少天)
    // 20201201 长度8,每位都是数字,以1、2开头,第5位为0、1,第6位0~9(当第5位为1时,第6位取1、2),第7位 0、1、2、3,第8位0~9(当第7位为3时,第8位取1、0)
    if (strlen(&(*a)) != 8)
    {
        return 0;
    }

    int i;
    for (i = 0; i < 8; i++) // 下标0~7
    {
        if (*(a + i) >= '0' && *(a + i) <= '9') // 每位都是数字
        {
            ;
        }
        else
        {
            return 0;
        }
    }

    if (*(a) == '1' || *(a) == '2') // 下面判断 具体情况  1,2
    {
        if (*(a + 4) == '0' || (*(a + 4) == '1' && (*(a + 5) == '0' || *(a + 5) == '1' || *(a + 5) == '2'))) // 5,6
        {
            if (*(a + 6) >= '0' && *(a + 6) < '3' || *(a + 6) == '3' && ( *(a + 7) == '1'|| *(a + 7) == '0') )
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }
        else
        {
            return 0;
        }
    }
    else
    {
        return 0;
    }
}

int proofreadIbsn(char *a)
{
    // printf("调用过"); // 测试时用
	// 只简单的判断一下,不准确
    // ISBN 978-962-215-001-0 , 数字开头与结尾,13位,4个分隔符
    if (strlen(&(*a)) != 17)
    {
        // printf("\n长度为%d",strlen(a));
        return 0;
    }
    int s = 0, f = 0;
    int i;
    for (i = 0; i < 17; i++) // 下标0~16
    {
        if (*(a + i) >= '0' && *(a + i) <= '9')
        {

            s++;
            // printf("\n%d,\n",s);
        }
        else
        {
            if (*(a + i) == '-' && i != 0 && i != 16)
            {
                f++;
                // printf("\n,%d\n",f);

                if (*(a + i) == '-' && *(a + i + 1) == '-') // 两位连续是'-'时,错误
                {
                    // printf("连续");
                    return 0;
                }
            }
            else
            {
                return 0;
            }
        }
    }
    if (s == 13 && f == 4)
    {
        // printf("proofreadIbsn\n");
        return 1;
    }
}

int sole(char *a) // 唯一性
{
    // 遍历,对比
    PBOOKS p = pHead->nextBooks; // 首结点
    if (p == NULL)
    {
        // printf("sole\n");
        return 1;
    }
    while (p != NULL) // 遍历
    {

        if (isbnEqual(p->isbn, a, 18)) // 为真时,表示相等,重复了
        {
            // printf("noSole\n");
            return 0;
        }
        else
        {
            p = p->nextBooks;
        }
    }
    // printf("sole\n");
    return 1;
}

void findName()
{
    printf("====================图书登记管理程序====================");
    printf("\n已进入通过作者名,查看其所有书本信息选项中:\n");

    char authorN[20];
    int count = 0;
    PBOOKS p = pHead->nextBooks; // 头指针->next(头节点的指针域)

    if (p == NULL) // 没有首结点
    {
        printf("\n程序中暂未存储数据\n");
    }
    else
    {
        printf("请输入你要查找的作者:");
        fflush(stdin);
        scanf("%s", &authorN);
        while (p != NULL) // 遍历
        {
            if (strcmp(p->author, authorN) == 0) // 比较数组中的内容
            {
                count++;
                printf("\nISBN\t\t\t书名\t作者\t出版社\t\t价格\t出版日期\n");
                printf("%s\t%s\t%s\t%s\t%.2f\t%s\n", p->isbn, p->name, p->author, p->publisher, p->price, p->date);
                p = p->nextBooks;
            }
            else
            {
                p = p->nextBooks;
            }
        }
        if (!count)
        {
            printf("\n程序中没有找到与此作者相关书本\n");
        }
    }
    return;
}
void isbnUpdate()
{
    printf("====================图书登记管理程序====================");
    printf("\n通过书号(ISBN),修改书本信息选项中:\n");

    char isbnN[18];
    char temp_isbn[18];
    char temp_date[9];

    PBOOKS p = pHead->nextBooks; // 头指针->next(头节点的指针域)

    if (p == NULL) // 没有首结点
    {
        printf("\n程序中暂未存储数据\n");
    }
    else
    {
        printf("请输入你要查找的ISBN:");
        memset(isbnN, '\0', sizeof(isbnN));
        fflush(stdin);
        scanf("%s", &isbnN);
        while (p != NULL) // 遍历
        {
            if (isbnEqual(p->isbn, isbnN, 18)) // 输入的isbn与链表中的isbn 遍历比较
            {
                int flag = 10;
                int sign = 3;
                while (flag)
                {
                 	printf("\nISBN\t\t\t书名\t作者\t出版社\t\t价格\t出版日期\n");
                	printf("%s\t%s\t%s\t%s\t%.2f\t%s\n", p->isbn, p->name, p->author, p->publisher, p->price, p->date);
                	
                    memset(temp_isbn, '\0', sizeof(temp_isbn)); // 初始化 内存中的值
                    memset(temp_date, '\0', sizeof(temp_date));
                    copy(temp_isbn, p->isbn, 18);
                    copy(temp_date, p->date, 9);

                    printf("\n需要修改哪一项内容?(1.ISBN 2.书名 3.作者 4.出版社 5.价格 6.出版日期\n或输入其它任意字符退出,请输入:");
                    fflush(stdin);
                    scanf("%d", &flag);

                    switch (flag)
                    {
                    case 1:
                        flag = 10;
                        printf("请输入ISBN:");
                        fflush(stdin);
                        scanf("%s", isbnN);

                        // 合法性校验
                        sign = 3;

                        while (((proofreadIbsn(isbnN) == 0) || (sole(isbnN) == 0)) && --sign) // 满足所有条件,多次输入错误,退出
                        {
                            memset(isbnN, '\0', sizeof(isbnN)); // 初始化 内存中的值
                            printf("\n输入的ISBN有误,请重新输入\n");
                            printf("请输入ISBN(例:978-962-215-001-0):");
                            fflush(stdin);
                            scanf("%s", &(isbnN));
                        }

                        copy(p->isbn, isbnN, 18);

                        if (sign == 0)
                        {
                            memset(p->isbn, '\0', sizeof(p->isbn)); // 初始化 内存中的值
                            copy(p->isbn, temp_isbn, 18);
                            printf("\n多次输入有误,数据未更改\n");
                            break;
                        }
                        printf("\n修改成功\n");
                        break;
                    case 2:
                        flag = 10;
                        printf("\n请输入书名:");
                        fflush(stdin);
                        scanf("%s", p->name);
                        printf("\n修改成功\n");
                        break;
                    case 3:
                        flag = 10;
                        printf("\n请输入作者:");
                        fflush(stdin);
                        scanf("%s", p->author);
                        printf("\n修改成功\n");
                        break;
                    case 4:
                        flag = 10;
                        printf("\n请输入出版社:");
                        fflush(stdin);
                        scanf("%s", p->publisher);
                        printf("\n修改成功\n");
                        break;
                    case 5:
                        flag = 10;
                        printf("\n请输入价格:");
                        fflush(stdin);
                        scanf("%f", &p->price);
                        printf("\n修改成功\n");
                        break;
                    case 6:
                        flag = 10;
                        printf("\n请输入出版日期:");
                        fflush(stdin);
                        scanf("%s", p->date);
                        // 合法性校验
                        sign = 3;

                        while (!proofreadDate(p->date) && --sign) // 合法返回1,取反,循环结束
                        {
                            memset(p->date, '\0', sizeof(p->date)); // 初始化 内存中的值
                            printf("\n输入的日期有误,请重新输入\n");
                            printf("请输入出版日期(例:20201212):");
                            fflush(stdin);
                            scanf("%s", &(p->date));
                        }

                        if (sign == 0)
                        {
                            memset(p->date, '\0', sizeof(p->date)); // 初始化 内存中的值
                            copy(p->date, temp_date, 9);
                            printf("\n多次输入有误,数据未更改\n");
                            break;
                        }
                        printf("\n修改成功\n");
                        break;
                    default:
                        return;
                    }
                }
            }
            else
            {
                p = p->nextBooks;
            }
        }
        printf("\n程序中没有找到书本\n");
    }
    return;
}
void isbnDelete()
{
    printf("====================图书登记管理程序====================");
    printf("\n已进入通过书号(ISBN),删除书本信息选项中:\n");

    char isbnN[18];

    PBOOKS p = pHead->nextBooks; // 首结点

    if (p == NULL) // 没有首结点
    {
        printf("\n程序中暂未存储数据\n");
    }
    else
    {
        PBOOKS temp = pHead; // 头节点
        printf("请输入你要删除的ISBN:");
        scanf("%s", &isbnN);
        fflush(stdin);
        while (p != NULL) // 遍历
        {
            if (isbnEqual(p->isbn, isbnN, 18)) // 比较字符数组中的内容
            {
                temp->nextBooks = p->nextBooks; // temp结点 比 p结点慢一步
                free(p);                        // 释放被删除的结点内存
                printf("\n删除成功\n");
                if (temp->nextBooks == NULL)
                {
                    pTail = temp;
                }
                return;
            }
            else
            {
                p = p->nextBooks;
                temp = temp->nextBooks;
            }
        }
        printf("\n程序中没有找到书本\n");
    }
    return;
}
void inputFile()
{
    printf("====================图书登记管理程序====================");
    printf("\n已进从文件读入书本信息选项中:\n");

    FILE *fp = NULL;
    // char *a = "D:\\E_disk\\tes.txt";
    char path[50];
    // 1. 输入读取路径
    fflush(stdin);
    printf("\n请输入读取文件路径,可参考(D:\\A\\b.txt):");
    scanf("%s", path);
    printf("指定的路径为:%s", path);

    // 2. 读取文件
    fp = fopen(path, "r"); // r 只读,文件不存在就出错

    if (fp == NULL)
    {
        printf("\n读取文件失败\n");
        return;
    }
    else
    {
        printf("\n成功读入文件...正在处理\n");

        // 临时变量
        char isbn[18];
        char name[20];
        char author[9];
        char publisher[30];
        float price;
        char date[9]; // 时间格式20201221

        // 4. 从文件里依次取值 , 循环读取全部数据
        int count = 0;
        printf("\nISBN\t\t\t书名\t作者\t出版社\t\t价格\t出版日期\n");

        while (!feof(fp)) // 文件结束:返回非0值;文件未结束:返回0值
        {
            // 	3. 读取数据前,先创建一个结点
            PBOOKS pNew = (PBOOKS)malloc(sizeof(BOOKS));
            if (pNew == NULL)
            {
                printf("\n分配失败,程序终止\n");
                printf("\n已添加%d条数据\n", count);
                return;
            }

            memset(isbn, '\0', sizeof(isbn)); // 初始化 内存中的值
            memset(name, '\0', sizeof(name));
            memset(author, '\0', sizeof(author));
            memset(publisher, '\0', sizeof(publisher));
            memset(&price, '\0', sizeof(price));
            memset(date, '\0', sizeof(date));

            memset(pNew->isbn, '\0', sizeof(pNew->isbn)); // 初始化 内存中的值
            memset(pNew->name, '\0', sizeof(pNew->name));
            memset(pNew->author, '\0', sizeof(pNew->author));
            memset(pNew->publisher, '\0', sizeof(pNew->publisher));
            memset(&(pNew->price), '\0', sizeof(pNew->price));
            memset(pNew->date, '\0', sizeof(pNew->date));

            // 读取数据
            fscanf(fp, "%s %s %s %s %f %s\n", isbn, name, author, publisher, &price, date);

            // 赋值前,进行数据的检验
            if ((proofreadIbsn(isbn) && sole(isbn)) == 0) // 判断isbn的正确性
            {
                system("CLS");
                printf("\n本次操作添加了%d条数据\n", count);
                printf("\n从文件中读入的数据(ISBN)有误,禁止写入数据\n\n");
                return;
            }

            if (proofreadDate(date) == 0) // 判断日期的正确性
            {
                system("CLS");
                printf("\n本次操作添加了%d条数据\n", count);
                printf("\n从文件中读入的数据(日期)有误,禁止写入数据\n\n");
                return;
            }

            // 临时值读取成功后赋值给结点,c语言中 两个数组之间不能直接赋值
            copy(pNew->isbn, isbn, 18);
            copy(pNew->name, name, 20);
            copy(pNew->author, author, 9);
            copy(pNew->publisher, publisher, 30);
            pNew->price = price;
            copy(pNew->date, date, 9);

            printf("%s\t%s\t%s\t%s\t%.2f\t%s\n", pNew->isbn, pNew->name, pNew->author, pNew->publisher, pNew->price, pNew->date);

            // 结点插入到链表后面
            pNew->nextBooks = NULL;
            pTail->nextBooks = pNew;
            pTail = pNew;

            count++;
        }
        printf("\n本次操作添加了%d条数据\n", count);
        // 关闭文件
        fclose(fp);
    }
    return;
}

void outputFile()
{
    printf("====================图书登记管理程序====================");
    printf("\n已进将信息输出到文件选项中:\n");

    FILE *fp = NULL;
    // char *path = "D:\\E_disk\\output.txt";
    char path[50];
    // 1. 输入读取路径
    fflush(stdin);
    printf("\n请输入要输出文件路径,可参考(D:\\A\\c.txt):");
    scanf("%s", path);
    printf("指定的路径为:%s", path);

    // 2. 读取文件
    fp = fopen(path, "a"); // a 追加,文件不存会自己创建
    // setbuf(fp, NULL);

    if (fp == NULL)
    {
        printf("\n路径读取出现问题\n");
        return;
    }
    else
    {
        printf("\n成功读取路径..正在处理\n");
    }

    // 2. 遍历输出链表结点
    PBOOKS p = pHead->nextBooks; // 首结点

    if (p == NULL)
    {
        printf("\n程序中没有数据\n");
    }
    else
    {

        printf("\n正在输出数据...\n");
        int count = 0;
        fprintf(fp, "ISBN\t\t\t书名\t作者\t出版社\t\t价格\t出版日期\n");
        fflush(fp);
        while (p != NULL) // 遍历
        {
            count++;
            // 把输出结果保存到文件
            fprintf(fp, "%s\t%s\t%s\t%s \t%.2f\t%s\n", p->isbn, p->name, p->author, p->publisher, p->price, p->date);
            fflush(fp);
            p = p->nextBooks;
        }
        printf("\n共%d条数据写入到文件\n", count);
    }
    fclose(fp);
    return;
}
void countsAuthors()
{
    printf("====================图书登记管理程序====================");
    printf("\n已进统计 按(作者)分类-->计数选项中:\n");

    typedef struct authors // 作者名,以链表存储,
    {
        char name[9];
        int n;
        struct authors *nextAutors;
    } AUTHORS, *PAUTHORS;

    PAUTHORS pHead_au = NULL;
    PAUTHORS pTail_au = NULL;

    pHead_au = (PAUTHORS)malloc(sizeof(AUTHORS)); // 头节点
    pTail_au = pHead_au;                          // 最开始 尾结点与头结点指向同一地址
    pTail_au->nextAutors = NULL;

    PAUTHORS pHead_temp = pHead_au->nextAutors;

    PBOOKS p = pHead->nextBooks; // 首结点

    if (p == NULL) // 没有首结点
    {
        printf("\n程序中暂未存储数据\n");
        return;
    }
    else
    {
        while (p != NULL) // 遍历
        {
            // 判断 p->authors 在  p_au 中的 是否存在
            if (pHead_au->nextAutors == NULL) // 不存在直接插入新结点,计数1
            {
                PAUTHORS pNew_au = (PAUTHORS)malloc(sizeof(AUTHORS));
                memset(pNew_au->name, '\0', sizeof(pNew_au->name));
                copy(pNew_au->name, p->author, 9);
                pNew_au->nextAutors = NULL;
                pNew_au->n = 1;
                pTail_au->nextAutors = pNew_au;
                pTail_au = pNew_au;
                // printf("\n情况1\n");
            }
            else
            {
                pHead_temp = pHead_au->nextAutors; // 首结点
                while (pHead_temp != NULL)
                {
                    if (isbnEqual(p->author, pHead_temp->name, 9)) // 存在 计数加1
                    {
                        pHead_temp->n += 1;
                        // printf("\n情况2\n");
                        goto TiaoChu;
                    }
                    pHead_temp = pHead_temp->nextAutors;
                }

                // 不存在,插入新结点,计数1
                PAUTHORS pNew_au = (PAUTHORS)malloc(sizeof(AUTHORS));
                memset(pNew_au->name, '\0', sizeof(pNew_au->name));
                copy(pNew_au->name, p->author, 9);
                pNew_au->nextAutors = NULL;
                pNew_au->n = 1;
                // printf("\n情况3\n");
                pTail_au->nextAutors = pNew_au;
                pTail_au = pNew_au;
            }
        TiaoChu:
            p = p->nextBooks;
        }
    }

    pHead_temp = pHead_au->nextAutors; // 首结点

    printf("\n统计数据(作者名:书本数量):\n");
    while (pHead_temp != NULL) // 遍历
    {
        fflush(stdout);
        printf("\n%s:%d\n", pHead_temp->name, pHead_temp->n);
        pHead_temp = pHead_temp->nextAutors;
    }
    return;
}
void conntsPublishers()
{
    printf("====================图书登记管理程序====================");
    printf("\n已进统计 按(出版社)分类-->计数选项中:\n");

    typedef struct publisher // 出版社名,以链表存储,
    {
        char name[30];
        int n;
        struct publisher *nextPublisher;
    } PUBLISHER, *PPUBLISHER;

    PPUBLISHER pHead_pu = NULL;
    PPUBLISHER pTail_pu = NULL;

    pHead_pu = (PPUBLISHER)malloc(sizeof(PUBLISHER)); // 头节点
    pTail_pu = pHead_pu;                              // 最开始 尾结点与头结点指向同一地址
    pTail_pu->nextPublisher = NULL;

    PPUBLISHER pHead_temp = pHead_pu->nextPublisher; // 首结点

    PBOOKS p = pHead->nextBooks; // 首结点

    if (p == NULL) // 没有首结点
    {
        printf("\n程序中暂未存储数据\n");
        return;
    }
    else
    {
        while (p != NULL) // 遍历
        {
            // 判断 p->publisheers 在  p_pu 中的 是否存在
            if (pHead_pu->nextPublisher == NULL) // 不存在直接插入新结点,计数1
            {
                PPUBLISHER pNew_pu = (PPUBLISHER)malloc(sizeof(PUBLISHER));
                memset(pNew_pu->name, '\0', sizeof(pNew_pu->name));
                copy(pNew_pu->name, p->publisher, 30);
                pNew_pu->nextPublisher = NULL;
                pNew_pu->n = 1;
                pTail_pu->nextPublisher = pNew_pu;
                pTail_pu = pNew_pu;
                // printf("\n情况1\n");
            }
            else
            {
                pHead_temp = pHead_pu->nextPublisher; // 首结点
                while (pHead_temp != NULL)
                {
                    if (isbnEqual(p->publisher, pHead_temp->name, 30)) // 存在 计数加1
                    {
                        pHead_temp->n += 1;
                        // printf("\n情况2\n");
                        goto TiaoChu;
                    }
                    pHead_temp = pHead_temp->nextPublisher;
                }

                // 不存在,插入新结点,计数1
                PPUBLISHER pNew_pu = (PPUBLISHER)malloc(sizeof(PUBLISHER));
                memset(pNew_pu->name, '\0', sizeof(pNew_pu->name));
                copy(pNew_pu->name, p->publisher, 30);
                pNew_pu->nextPublisher = NULL;
                pNew_pu->n = 1;
                // printf("\n情况3\n");
                pTail_pu->nextPublisher = pNew_pu;
                pTail_pu = pNew_pu;
            }
        TiaoChu:
            p = p->nextBooks;
        }
    }

    pHead_temp = pHead_pu->nextPublisher; // 首结点

    printf("\n统计数据(出版社名:书本数量):\n");
    while (pHead_temp != NULL) // 遍历
    {
        fflush(stdout);
        printf("\n%s:%d\n", pHead_temp->name, pHead_temp->n);
        pHead_temp = pHead_temp->nextPublisher;
    }
    return;
}

你可能感兴趣的:(#,c语言,链表,c语言,数据结构)