我正在处理双重链接列表。它由类组成,并以当前节点为中心(而不是列表开头或结尾的节点)。现在我的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
答案 0 :(得分:1)
您的Node
管理错误。
一个小问题是queue::goBack()
和queue::goForward()
在访问其字段之前未检查current
是否为空,因此如果用户选择“返回”或在选择“转到网页”之前“前进”(至少print()
检查为空)。所以添加这些检查,甚至更新printMenu()
甚至在队列没有当前页面时甚至不输出这些选项。
但更重要的是,您的queue::newPage()
实施已完全破解。当current
不为空时,您将该节点的next
成员设置为指向本身而不是您创建的新节点,并且您没有设置新节点的previous
字段(),更不用说指向现在插入的节点。
您还应该摆脱temp
班级的temp2
和queue
成员。他们首先不属于那里。它们仅在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;
}
}