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 的 temp
和 temp2
成员。他们本来就不属于那里。它们只在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;
}
}
我正在处理双向链表。它由 类 组成,并以当前节点为中心(而不是列表开头或结尾的节点)。现在我的打印函数将抛出一个错误,但前提是我完全遍历了列表。我的打印函数只打印当前节点中的数据(前提是它不为空)。这是我的打印功能:(在底部对我的文件层次结构和代码进行了更详细的描述)
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 的 temp
和 temp2
成员。他们本来就不属于那里。它们只在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;
}
}