用Qt搭建图书管理系统(一)

第一章 使用的数据结构

https://gitee.com/mayonaka/LibraryManageSystem

百度云:https://pan.baidu.com/s/1G95yPyGG080b6yXcjc8B0g

提取码:4q8b

程序无非就是数据结构+算法。而数据结构就是程序中用来组织数据的方法。本次编写的图书管理系统用的是一个比较简单的数据结构:链表。

首先,先确定图书管理系统中需要存储的数据。

1.     书,书的属性有:书名,作者,类型,介绍,还有为了唯一标记一本书,给他一个id。

2.     用户:姓名,密码,还有id。

3.     用户借阅的书:人的id,书的id,借阅时间。

因为要用链表要储存这些数据,所以要从这些数据中抽象一个父类出来作为链表中的节点(总不能为它们每一个都建立一个链表吧,那样维护起来太难),我们发现,每一个数据都有一个共同的属性,那就是id,因此,建立一个只有id属性的类作为它们的基类,在链表中使用这个基类作为节点

//基类
class NodeType
{
public:
    // 通过id来判断是否是要找的节点
    virtual bool Compare(int id);

    int GetId();
    void SetId(int id);
    NodeType* GetNext();
    void SetNext(NodeType* node);

protected:
    int id;
    NodeType* next = NULL;
};

//用户类
class UserType : public NodeType
{
public:
    QString GetName();
    void SetName(QString name);
    QString GetPassword();
    void SetPassword(QString password);

protected:
    QString name;
    QString password;
};

//书类
class BookType : public NodeType
{
public:
    QString GetName();
    void SetName(QString name);
    QString GetAuthor();
    void SetAuthor(QString author);
    QString GetCategory();
    void SetCategory(QString category);
    QString GetIntroduction();
    void SetIntroduction(QString introduction);

protected:
    QString name;
    QString author;
    QString category;
    QString introduction;
};

// 用户的书类
class UserBookType : public NodeType
{
public:
    // 不是通过id来判断,而是bookId
    virtual bool Compare(int id);

    int GetBookId();
    void SetBookId(int id);
    int GetYear();
    void SetYear(int year);
    int GetMonth();
    void SetMonth(int month);
    int GetDay();
    void SetDay(int day);

protected:
    int bookId;
    int year;
    int month;
    int day;
};

 

 

 

关于这几个类的实现,都是一些比较简单的操作。除了Compare方法需要讲一下。Compare方法是用来比较的函数,在本项目中的作用就是判断当前节点是否为想要找的节点。BookType类,UserType类通过id属性来判断,UserBookType类通过bookId属性来判断,因此需要重写Compare函数。

 

bool NodeType::Compare(int id)
{
    if (this->id == id)
    {
        return true;
    }
    else
    {
        return false;
    }
}

bool UserBookType::Compare(int id)
{
    if (this->bookId == id)
    {
        return true;
    }
    else
    {
        return false;
    }
}

 

下面开始建立链表,链表中储存的节点是NoteType类型,也就是BookType,UserType,UserBookType的父类,在使用到具体子类的时候可以强转到具体的子类。

LinerList的方法:

1.    Init函数:从外存中(本项目是数据库)中读取数据来初始化链表。

2.    Save函数:用来保存在程序中被修改的数据,通过链表头节点的id值来判断是添加还是删除:1表示添加,调用SaveAdd函数;-1表示删除,调用SaveDelete函数,

3.    SaveAdd函数:把链表中的数据添加到数据库中。

4.    SaveDelete函数:把链表中的数据从数据库中删掉。

5.    AddNode函数:把node节点添加到链表中。

6.    DeleteNode函数:把链表中节点属性id的值为id的节点删掉

LinerList的属性:

1.    List:该属性是链表的头节点。

2.    Length:用来记录链表长度

3.    db:这是一个QSqlDatabase类型的静态变量,本项目中所有的数据都存储在同一个数据库中,为了方便之后的读入读出操作,就设置了一个静态变量来保存数据库对象,这样在初始化一次之后,就不用再重复进行初始化操作了。注:注意类中静态变量的初始化方法。要在类体外进行初始化。

 

链表的实现比较简单,这里大家看一下代码就行。

需要注意的一点是,在Qt中使用MySql时,要在配置文件(.pro文件)中加一句QT += sql。

#include <QtSql/QSqlDatabase>
#include "nodetype.h"

class LinerList
{
public:
    LinerList();
    virtual ~LinerList();

    // 从文件中读取信息来初始化链表
    virtual void Init();
    // 清空整个链表
    virtual void Clear();
    // 把链表中的信息保存下来,使用第一个节点,也就是头节点的id来标记是删除还是添加
    // id为1时,向文件中添加链表中的节点信息
    // id为-1时,把链表中的节点信息从文件中删除
    virtual void Save();
    // 向文件中添加链表中的节点信息
    virtual void SaveAdd();
    // 从文件中把链表中的节点信息删除
    virtual void SaveDelete();
    // 向链表中添加一个节点,node为空时无操作
    virtual void AddNode(NodeType* node);
    // 从链表中删除属性为id的节点
    virtual void DeleteNode(int id);
    // 获得属性为id的节点,id为-1时,获得头节点,其它返回空
    virtual NodeType* GetNode(int id);

protected:
    static QSqlDatabase db;
    NodeType* list = NULL;
    int length = 0;
};

 

#include "linerlist.h"

//初始化数据库对象
QSqlDatabase LinerList::db = QSqlDatabase::addDatabase("QMYSQL");

LinerList::LinerList()
{
    //头节点
    this->list = new NodeType();
    this->list->SetNext(NULL);

    //初始化数据库信息
    this->db.setDatabaseName("LibraryManageSystem");
    this->db.setHostName("localhost");
    this->db.setUserName("user");
    this->db.setPort(3306);
    this->db.setPassword("123456");
}

LinerList::~LinerList()
{
    NodeType* preNode = this->list;
    NodeType* nextNode = this->list;

    while (nextNode != NULL)
    {
        preNode = nextNode;
        nextNode = nextNode->GetNext();

        delete preNode;
    }

    this->list = NULL;
}

void LinerList::Clear()
{
    NodeType* preNode = this->list->GetNext();
    NodeType* nextNode = this->list->GetNext();

    while (nextNode != NULL)
    {
        preNode = nextNode;
        nextNode = nextNode->GetNext();

        delete preNode;
    }

    this->length = 0;
    this->list->SetNext(NULL);
}

NodeType* LinerList::GetNode(int id)
{
    // 当id为-1时,返回头节点
    if (id == -1)
    {
        return this->list;
    }

    NodeType* node = this->list->GetNext();
    while (node != NULL)
    {
        if (node->GetId() == id)
        {
            return node;
        }

        node = node->GetNext();
    }

    return NULL;
}

void LinerList::AddNode(NodeType *node)
{
    if (node == NULL)
    {
        return;
    }

    node->SetNext(this->list->GetNext());
    this->list->SetNext(node);
    this->length++;
}

void LinerList::DeleteNode(int id)
{
    NodeType* preNode = this->list;
    NodeType* nextNode = this->list->GetNext();

    while (nextNode != NULL)
    {
        if (nextNode->Compare(id))
        {
            preNode->SetNext(nextNode->GetNext());
            delete nextNode;
            this->length--;
            break;
        }
        else
        {
            preNode = nextNode;
            nextNode = nextNode->GetNext();
        }

    }
}

// LinerList只是基类,没有要初始化的信息
// 初始化的具体实现在每一个子类中实现
void LinerList::Init()
{

}

void LinerList::Save()
{
    NodeType* node = this->GetNode(-1);
    // 当头节点id为1时,表示把链表中的信息添加到数据库中
    // 当有节点id为-1时,表示把链表中的信息从数据库中删掉
    if (node->GetId() == 1)
    {
        this->SaveAdd();
    }
    else if (node->GetId() == -1)
    {
        this->SaveDelete();
    }
}

// 在子类中具体实现
void LinerList::SaveAdd()
{

}

// 在子类中具体实现
void LinerList::SaveDelete()
{

}


 

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值