无法让我的代码的一部分工作。建立一个基本的链表来学习指针。我想我的大部分内容已经失效,但是任何尝试使用我创建的函数(push_back)都会在设置指针值时抛出内存访问错误。
不确定是什么问题,因为它可以正常使用push_front,它几乎完全相同。
有什么想法吗? = /
CODE:
driver.cpp
#include <string>
#include <iostream>
#include "linklist.h"
#include "node.h"
using namespace std;
// printList function
// Purpose: Prints each node in a list
// Returns: None.
// Pre-Conditions: List must have member nodes.
// Post-Conditions: None.
void printList(linklist);
int main()
{
linklist grocery;
grocery.push_front(new node("milk", "1 gallon"));
grocery.push_front(new node("bread","2 loaves"));
grocery.push_front(new node("eggs","1 dozen"));
grocery.push_front(new node("bacon","1 package"));
cout << "First iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
grocery.push_front(new node("hamburger","2 pounds"));
grocery.push_front(new node("hamburger buns", "1 dozen"));
cout << "Second iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
node* deleteMe = grocery.pop_front();
delete deleteMe;
cout << "Third iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
grocery.push_back(new node("orange juice","2 cans"));
grocery.push_back(new node("swiss cheeese","1 pound"));
cout << "Fourth iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
deleteMe = grocery.pop_back();
delete deleteMe;
cout << "Fifth iteration:" << endl;
printList(grocery);
cout << "----------------------" << endl << endl;
while (grocery.getNodeCount() != 0)
{
deleteMe = grocery.pop_front();
cout << "Cleaning: " << deleteMe->getDescription() << endl;
delete deleteMe;
}
system("PAUSE");
return 0;
}
void printList(linklist input)
{
node* temp = input.getFirst();
for (int i = 0; i < (input.getNodeCount()); i++)
{
cout << temp->getQuantity() << " " << temp->getDescription() << endl;
temp = temp->getNextNode();
}
}
node.h
#pragma once
#include <string>
using namespace std;
class node
{
public:
// Default Constructor
// Values, "none", "none", NULL.
node();
// Parameterized Constructor
// nextNode initialized NULL and must be explicitly set.
node(string descriptionInput, string quantityInput);
// getDescription function
// Purpose: Returns node description.
// Returns: string
// Pre-Conditions: None.
// Post-Conditions: None.
string getDescription();
// setDescription function
// Purpose: Sets node description
// Returns: Void
// Pre-Conditions: None
// Post-Conditions: None
void setDescription(string);
// getQuantity function
// Purpose: Returns node quantity.
// Returns: string
// Pre-Conditions: None.
// Post-Conditions: None.
string getQuantity();
// setQuantity function
// Purpose: Sets node quantity
// Returns: Void
// Pre-Conditions: None
// Post-Conditions: None
void setQuantity(string);
// getNextNode function
// Purpose: Returns pointer to next node in list sequence.
// Returns: node pointer
// Pre-Conditions: None.
// Post-Conditions: None.
// Note: Not set during initialization. Must be explicitly done.
node* getNextNode();
// setNextNode function
// Purpose: Sets pointer to next node in list sequence.
// Returns: None.
// Pre-Conditions: None.
// Post-Conditions: None.
// Note: Not set during initialization. Must be explicitly done.
void setNextNode(node*);
private:
string description;
string quantity;
node* nextNode;
};
node.cpp
#include "node.h"
node::node()
:description("none"),
quantity("none"),
nextNode(NULL)
{}
node::node(string descriptionInput, string quantityInput)
:description(descriptionInput),
quantity(quantityInput),
nextNode(NULL)
{}
string node::getDescription()
{
return description;
}
void node::setDescription(string descriptionInput)
{
description = descriptionInput;
}
string node::getQuantity()
{
return quantity;
}
void node::setQuantity(string quantityInput)
{
quantity = quantityInput;
}
node* node::getNextNode()
{
return nextNode;
}
void node::setNextNode(node* input)
{
nextNode = input;
}
linklist.h
#pragma once
#include "node.h"
class linklist
{
public:
// Constructor
// Builds an empty list
linklist();
// push_front function
// Purpose: Takes node pointer. Places that node at beginning of list.
// Returns: None
// Pre-Conditions: None
// Post-Conditions: None
void push_front(node*);
// pop_front function
// Purpose: Removes first node from list.
// Returns: Node pointer. NODE IS NOT DESTROYED.
// Pre-Conditions: List must have a node to remove.
// Post-Conditions: Node is not destroyed.
node* pop_front();
// getFirst function
// Purpose: Returns node pointer to first node in list
// Returns: node pointer
// Pre-Conditions: List must have a node added.
// Post-Conditions: None.
node* getFirst();
// push_back function
// Purpose: Takes node pointer. Places that node at end of list.
// Returns: None
// Pre-Conditions: None
// Post-Conditions: None
void push_back(node*);
// pop_back function
// Purpose: Removes last node from list.
// Returns: Node pointer. NODE IS NOT DESTROYED.
// Pre-Conditions: List must have a node to remove.
// Post-Conditions: Node is not destroyed.
node* pop_back();
// getNodeCount function
// Purpose: Returns nodeCount
// Returns: int
// Pre-Conditions: None.
// Post-Conditions: None.
int getNodeCount();
private:
node* firstNode;
node* lastNode;
int nodeCount;
};
linklist.cpp
#include "linklist.h"
linklist::linklist()
:firstNode(NULL),
lastNode(NULL),
nodeCount(0)
{}
void linklist::push_front(node* input)
{
node* temp = getFirst();
input->setNextNode(temp);
firstNode = input;
nodeCount++;
}
node* linklist::pop_front()
{
node* temp = getFirst();
firstNode = temp->getNextNode();
nodeCount--;
return temp;
}
node* linklist::getFirst()
{
return firstNode;
}
void linklist::push_back(node* input)
{
node* temp = lastNode;
temp->setNextNode(input);
lastNode = temp;
nodeCount++;
}
node* linklist::pop_back()
{
node* oldLast = lastNode;
node* temp = firstNode;
// find second to last node, remove it's pointer
for (int i = 0; i < (nodeCount - 1); i++)
{
temp = temp->getNextNode();
}
temp->setNextNode(NULL);
lastNode = temp;
nodeCount--;
return oldLast;
}
int linklist::getNodeCount()
{
return nodeCount;
}
答案 0 :(得分:2)
你在推送方法上有错误,因为当你在前面推动时,你不能控制这个元素是否也是最后一个,并且当你在最后推动时是相似的。它导致你没有连接整个列表,因为开始部分不知道结束部分。我希望这是可以理解的。
同样流行的方法是错误的 - 同样的问题。您无法控制列表是否为空
答案 1 :(得分:1)
好吧,当列表为空时,push_back
temp
为NULL。因此temp->setNextNode(input)
失败。您需要区分空列表的特殊情况。
顺便说一下,如果你允许后面和前面的操作,也许你需要一个双向链表?否则,您需要遍历整个(可能很大的)列表以弹出最后一个元素,因为您没有到其前一个元素的“直接”链接。
顺便说一句,你的操作是deque的操作,而不是列表。
答案 2 :(得分:1)
看起来你的push_back中有一个简单的错误:
void linklist::push_back(node* input)
{
node* temp = lastNode;
temp->setNextNode(input);
lastNode = temp; //this looks wrong
nodeCount++;
}
如上所述,我认为你的意思是lastNode = input
;
P.S。以"exception safety" carefully into account为准。 pop例程不返回任何内容,而是与peek()例程配对,以支持异常中立性/安全性并不罕见。
答案 3 :(得分:1)
根据node
的定义,它是一个单链表。 (否则你还必须包含prevNode
)。
因此 - 操纵列表的“后退”并非易事。要弹出列表的“后退”,您需要横切整个列表并识别新的“最后”元素。
你确定你这样做了吗?包括处理所有“极端”情况(如删除最后一个元素等)?
发布push_back
和pop_back
的代码非常好。
P.S。也许您没有在lastNode
和push_front
中正确设置pop_front
。你可能不会注意到这一点,除非你试图操纵你的“后退”。
也发布push_front
和pop_front
的代码。
修改强>:
好的,我看到了代码。而且有很多错误。
void linklist::push_front(node* input)
{
node* temp = getFirst();
input->setNextNode(temp);
firstNode = input;
nodeCount++;
// Missing:
if (!temp)
lastNode = firstNode;
}
node* linklist::pop_front()
{
node* temp = getFirst();
firstNode = temp->getNextNode();
// Missing:
if (!firstNode)
lastNode = 0;
nodeCount--;
return temp;
}
void linklist::push_back(node* input)
{
node* temp = lastNode;
// instead of
// temp->setNextNode(input);
// lastNode = temp;
// should be:
if (temp)
temp->setNextNode(input);
else
firstNode = input;
lastNode = input;
nodeCount++;
}
node* linklist::pop_back()
{
node* oldLast = lastNode;
if (firstNode == lastNode)
{
firstNode = 0;
lastNode = 0;
} else
{
node* temp = firstNode;
// find second to last node, remove it's pointer
for (int i = 0; i < (nodeCount - 1); i++)
{
temp = temp->getNextNode();
}
temp->setNextNode(NULL);
lastNode = temp;
}
nodeCount--;
return oldLast;
}