BGI 应用程序:已删除的节点未完全删除,打印时出现错误

问题描述 投票:0回答:1

向大家问好。我正在为我的 DSA 课程开发一个图书馆管理应用程序。我们使用 Borland Graphics.h 库来绘制用户界面(从这张图片here可以看出)。如图所示,左列包含书名结构列表,又名

DauSach
,代码如下:

struct DauSach {
    char ISBN[MAX_ISBN + 1];
    char tensach[MAX_TENSACH + 1];
    int sotrang;
    char tacgia[MAX_TACGIA + 1];
    int nxb;
    char theloai[MAX_THELOAI + 1];
    PtrSach* First = nullptr;

    int soluotmuon;
    int soluong;

    DauSach() {
    }
    DauSach(char* isbn, char* ten, int st, char* tg, int xb, char* tl) {
        strcpy(ISBN, isbn);
        strcpy(tensach, ten);
        sotrang = st;
        strcpy(tacgia, tg);
        nxb = xb;
        strcpy(theloai, tl);
        First = nullptr;

        soluong = 0;
        soluotmuon = 0;
    }

};

struct DS_DauSach {
    int n;
    DauSach* nodes[MAX_SIZE_DAUSACH];

    DS_DauSach() {
        n = 0;
    }
    ~DS_DauSach() {
        while (n) {
            DeleteAllPtrSach(nodes[n - 1]->First);
            delete nodes[--n];
        }
    }
};

内部

DauSach
是书的单链接列表,又名
Sach
,其结构如下:

struct Sach {
    char MASACH[MAX_MASACH + 1];
    int trangthai;
    char vitri[MAX_VITRI + 1];

    Sach() {
    }
    Sach(char ms[MAX_MASACH + 1], int tt, char vt[MAX_VITRI + 1]) {
        strcpy(MASACH, ms);
        trangthai = tt;
        strcpy(vitri, vt);
    }

};

// NODE Sach - DSLK don
struct PtrSach {
    Sach sach;
    PtrSach* next;
};

从上图中可以看到,右栏是显示

Sach
列表的位置。每本书都有删除功能,假设你有一本名为“TEST”的书,“TEST”书的列表是
TEST-0
TEST-1
TEST-2
。我想删除这本书
TEST-1
,应该只有
TEST-0
TEST-1
。删除书籍的步骤如下。

首先,我用这段代码获取当前书籍的节点。

PtrSach* nodeSelect = GetPtrSach(DSDS.nodes[curDauSach]->First, 10 * (curPageSach - 1) + curSach);
PtrSach* GetPtrSach(PtrSach* First, int position) {
    PtrSach* node = First;
    for (int i = 0; node != nullptr; node = node->next) {
        if (i == position) {
            return node;
        }
        ++i;
    }
    return nullptr; // Return nullptr if position is out of bounds
}

然后,在我有了节点之后,我通过选择结构体的当前名称

Sach
来删除这本书,假设它当前是
TEST-1

XoaPtrSachTheoMaSach(nodeSelect, sach.MASACH);

void XoaPtrSachTheoMaSach(PtrSach*& head, char* targetMASACH) {
    if (head == nullptr) return; // Empty list
    while (head != nullptr && strcmp(head->sach.MASACH, targetMASACH) == 0) {
        PtrSach* tmp = head;
        head = head->next;
        delete tmp;
    }
    if (head == nullptr) return;
    PtrSach* current = head;
    while (current->next != nullptr) {
        if (strcmp(current->next->sach.MASACH, targetMASACH) == 0) {
            PtrSach* tmp = current->next;
            current->next = current->next->next;
            delete tmp;
        }
        else {
            current = current->next;
        }
    }
}

删除后,我只是用此代码再次将当前书籍列表打印到右侧列。

void DrawDanhMucSach() {
    ... // these previous part can be ignored
    PtrSach* node = GetPtrSach(DSDS.nodes[curDauSach]->First, 10 * (curPageSach - 1));

    for (int i = 0; node != nullptr && i < 10; node = node->next) {
        DrawItemSach(node->sach, i++);  
    }
}

我遇到的问题是,在外部测试时(我可以保证)函数

XoaPtrSachTheoMaSach
按预期工作,但是在程序中包含代码后,它无法正确打印。相反,
TEST-1
的节点似乎没有完全删除,因为其中仍然留有垃圾值(怀疑是 nullptr 或其他东西?我不知道)。 这是我的意思的图片。问题是,如果删除函数起作用,则应删除该节点,并打印下一个节点,或者如果删除的节点已经是最后一个节点,则应将其分配给 nullptr 并停止打印。有谁知道或解决这种情况首先是如何发生的?

注意:我们不允许使用标准库,但是内部有

string
库,只能与
strcpy
函数一起使用或在
char[]
之间进行比较。

c++ linked-list singly-linked-list bgi borland-c++
1个回答
0
投票

这个循环不正确

PtrSach* current = head;
while (current->next != nullptr) {
    if (strcmp(current->next->sach.MASACH, targetMASACH) == 0) {
        PtrSach* tmp = current->next;
        current->next = current->next->next;
        delete tmp;
    }
    else {
        current = current->next;
    }
}

删除

current->next
时,必须使
current
指向
current->next
之后的节点。换句话说,代码应该是

PtrSach* current = head;
while (current->next != nullptr) {
    if (strcmp(current->next->sach.MASACH, targetMASACH) == 0) {
        PtrSach* tmp = current->next;
        current = current->next->next; // CHANGE HERE
        delete tmp;
    }
    else {
        current = current->next;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.