C++ 无法打印链表的指针数据

C++ Unable to Print Pointer Data of a Linked List

我正在处理双向链表。它由 类 组成,并以当前节点为中心(而不是列表开头或结尾的节点)。现在我的打印函数将抛出一个错误,但前提是我完全遍历了列表。我的打印函数只打印当前节点中的数据(前提是它不为空)。这是我的打印功能:(在底部对我的文件层次结构和代码进行了更详细的描述)

void queue::print(){
    if (current){
        std::cout << std::endl << std::endl << "+++++++++++++++++++ Webpage +++++++++++++++++++" << std::endl
            << "URL: " << current->data.getURL() << std::endl
            << "-----------------------------------------------" << std::endl 
            << "Title: " << current->data.getTitle() << std::endl
            << "-----------------------------------------------" << std::endl
            << "Content: " << current->data.getContent() << std::endl
            << "+++++++++++++++++++++++++++++++++++++++++++++++" << std::endl << std::endl;
    }
    else{
        std::cout << std::endl << "Your not on a page. Please navigate to a page first." << std::endl;
    }

现在,如果我用两个数据节点填充列表,并执行我的打印函数,它会很好地打印节点中的数据。但是,如果我使用 goBack() 函数遍历到前一个节点:

void queue::goBack(){
    if (!current->previous){
        std::cout << "No previous page to go to!" << std::endl;
    }
    else{
        temp2 = current;
        current = current->previous;
    }
}

这会执行得很好,但是当我尝试打印节点中的数据时(使用相同的打印功能)我收到此错误:

Web 中 0x003E7926 处的未处理异常 Browser.exe:0xC0000005:访问冲突读取位置 0xCDCDCE19。

和visual studio打开一个没有扩展类型的文件,里面有看起来像C代码的东西,叫做xstring,它有一个指向第1754行的中断箭头。

现在让我更详细地解释一下我的代码。我有五个文件:webQueue.h、webQueue.cpp、webPage.h、webPage.cpp、&main.cpp。我列出的所有函数都在我的 webQueue.cpp 文件中。

这是webQueue.h:

#include "webPage.h"
class queue{
public:
    queue();
    void newPage(std::string u, std::string t, std::string c);
    void goForward();
    void goBack();
    void print();
private:
    struct Node{
        webPage data;
        Node* next;
        Node* previous;
    };
    Node* temp;
    Node* current;
    Node* temp2;
};

这里是 webPage.h:

#include <string>
class webPage{
public:
    webPage();
    webPage(std::string u, std::string t, std::string c);
    std::string getURL();
    void setURL(std::string u);
    std::string getTitle();
    void setTitle(std::string t);
    std::string getContent();
    void setContent(std::string c);
private:
    std::string URL;
    std::string title;
    std::string content;
};

我的 webQueue.cpp 文件包括:

#include <iostream>
#include "webQueue.h"

我的 webPage.cpp 文件只包含 webPage.h 而我的 main.cpp 文件(包含我的执行函数)包括:

#include <iostream>
#include <string>
#include "webQueue.h"

虽然这些关系看起来有点绕,但应该都是成立的。 cpp 文件被 link 编辑到它们具有完全相同名称的头文件(假设头文件存在),连同 main.cpp 被 link 编辑到 webQueue.h 和 webQueue.h 被 link 编辑为 webPage.h。我看不出我的代码有什么问题——尽管那可能只是因为我很难理解指针的工作原理。我想错误出在我的 print()、goBack() 和 goForward() 函数的代码中(尽管在修复 goBack() 函数之前我无法测试我的 goForward() 函数)但我不能告诉我哪里出了问题。

非常感谢你们能提供的任何帮助,因为我很困惑。这是所有文件的保管箱 link,这样您就可以自己测试这个程序,看看我是否有任何其他功能有错误:https://www.dropbox.com/s/yekrz6dln1v9npk/webQueue.zip?dl=0

你的Node管理有误

一个小问题是 queue::goBack()queue::goForward() 在访问其字段之前不检查 current 是否为 null,因此如果用户选择 [=61],您的代码将崩溃=] 或 "go forward",然后再选择 "go to webpage"(至少 print() 正在检查 null)。所以添加这些检查,甚至可能更新 printMenu() 以在队列没有可用的当前页面时甚至不输出这些选项。

但更重要的是,您的 queue::newPage() 实现 完全损坏 。当 current 不为空时,您将该节点的 next 成员设置为指向 自身 而不是 新节点 您已经创建,并且您根本没有设置新节点的 previous 字段 ,更不用说指向它之后插入的现有节点了。

您还应该删除 queue class 的 temptemp2 成员。他们本来就不属于那里。它们只在queue::newPage()内部有用(queue::goBack()根本不需要使用temp,就像goForward()一样),所以应该在queue::newPage() 而已。更好的是,它们可以完全删除,因为 queue::newPage() 可以在根本不使用它们的情况下实现。

您的 queue 实现应该看起来更像这样(而且这甚至不包括 copy/move 语义 - 参见 rule of three/five/zero):

#include "webPage.h"

class queue {
public:
    queue();
    void newPage(std::string u, std::string t, std::string c);
    void goForward();
    void goBack();
    void print();
private:
    struct Node {
        webPage data;
        Node* next;
        Node* previous;
    };
    Node* current;
};

#include <iostream>
#include "webQueue.h"

queue::queue() {
    current = nullptr;
}

void queue::newPage(std::string u, std::string t, std::string c) {
    Node* n = new Node;
    n->data = webPage(u, t, c);
    n->next = nullptr;
    n->previous = nullptr;

    if (current) {
        if (current->next) {
            n->next = current->next;
            current->next->previous = n;
        }
        n->previous = current;
        current->next = n;
    }

    current = n;
}

void queue::goBack() {
    if ((current) && (current->previous)) {
        current = current->previous;
    }
    else {
        std::cout << "No previous page to go to!" << std::endl;
    }
}

void queue::goForward() {
    if ((current) && (current->next)) {
        current = current->next;
    }
    else {
        std::cout << "No next page to go to!" << std::endl;
    }
}

void queue::print() {
    if (current) {
        std::cout << std::endl << std::endl
            << "+++++++++++++++++++ Webpage +++++++++++++++++++" << std::endl
            << "URL: " << current->data.getURL() << std::endl
            << "-----------------------------------------------" << std::endl 
            << "Title: " << current->data.getTitle() << std::endl
            << "-----------------------------------------------" << std::endl
            << "Content: " << current->data.getContent() << std::endl
            << "+++++++++++++++++++++++++++++++++++++++++++++++" << std::endl << std::endl;
    }
    else {
        std::cout << std::endl << "You are not on a page. Please navigate to a page first." << std::endl;
    }
}

然后,当你在做的时候,你应该重写 queue 以完全停止使用手动节点管理并使用标准 std::list class 代替:

#include "webPage.h"
#include <list>

class queue {
public:
    void newPage(std::string u, std::string t, std::string c);
    void goForward();
    void goBack();
    void print();
private:
    std::list<webPage> data;
    std::list<webPage>::iterator current;
};

#include "webQueue.h"
#include <iostream>
#include <iterator>

void queue::newPage(std::string u, std::string t, std::string c) {
    webPage p(u, t, c);
    if (data.empty()) {
        data.push_back(p);
        current = data.begin();
    }
    else {
        current = data.insert(std::next(current), p);
    }
}

void queue::goBack() {
    if ((!data.empty()) && (current != data.begin()))
        current = std::prev(current);
    else
        std::cout << "No previous page to go to!" << std::endl;
}

void queue::goForward() {
    if (!data.empty()) {
        std::list<webPage>::iterator iter = std::next(current);
        if (iter != data.end()) {
            current = iter;
            return;
        }
    }
    std::cout << "No next page to go to!" << std::endl;
}

void queue::print() {
    if (!data.empty()) {
        std::cout << std::endl << std::endl
            << "+++++++++++++++++++ Webpage +++++++++++++++++++" << std::endl
            << "URL: " << current->data.getURL() << std::endl
            << "-----------------------------------------------" << std::endl 
            << "Title: " << current->data.getTitle() << std::endl
            << "-----------------------------------------------" << std::endl
            << "Content: " << current->data.getContent() << std::endl
            << "+++++++++++++++++++++++++++++++++++++++++++++++" << std::endl << std::endl;
    }
    else {
        std::cout << std::endl << "You are not on a page. Please navigate to a page first." << std::endl;
    }
}