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

时间:2015-06-09 00:11:23

标签: c++ linked-list nodes

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

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 Browser.exe中0x003E7926处的未处理异常:0xC0000005:访问冲突读取位置0xCDCDCE19。

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

现在让我更详细地解释一下我的代码。我有五个文件:webQueue.h,webQueue.cpp,webPage.h,webPage.cpp,&amp; 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文件链接到它们的头文件,它们具有完全相同的名称(提供头文件存在),以及链接到webQueue.h的main.cpp和链接到webPage.h的webQueue.h。我无法看到我的代码出错了 - 尽管这可能仅仅是因为我很难理解指针是如何工作的。我想错误是在我的print(),goBack()和goForward()函数的代码中(虽然我不能测试我的goForward()功能,直到我修复我的goBack()函数)但我可以& #39;告诉我的错误。

我们非常感激你们给予的任何帮助,因为我很难过。这是一个指向所有文件的保管箱链接,以便您可以自己测试此程序,看看我是否还有其他任何错误的功能:https://www.dropbox.com/s/yekrz6dln1v9npk/webQueue.zip?dl=0

1 个答案:

答案 0 :(得分:1)

您的Node管理错误。

一个小问题是queue::goBack()queue::goForward()在访问其字段之前未检查current是否为空,因此如果用户选择“返回”或在选择“转到网页”之前“前进”(至少print()检查为空)。所以添加这些检查,甚至更新printMenu()甚至在队列没有当前页面时甚至不输出这些选项。

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

您还应该摆脱temp班级的temp2queue成员。他们首先不属于那里。它们仅在queue::newPage()内有用(queue::goBack()根本不需要使用temp,就像goForward())一样,因此应将它们更改为queue::newPage()内的局部变量仅限{1}}。更好的是,它们可以完全删除,因为queue::newPage()可以在不使用它们的情况下实现。

您的queue实现应该看起来更像这样(这甚至不计算复制/移动语义,请参阅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类:

#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;
    }
}