我一直在四处寻找,但我找不到解决方案。对于我的数据结构课程,我被要求使用链表创建堆栈。在大多数情况下它运作良好,我的教授甚至给了我一个24/25的任务,但它一直困扰我,它仍然崩溃。我怀疑问题出在复制构造函数或pop操作中。这是头文件:
{
width: auto;
height: auto;
}
这是实施文件:
/*******************************************************************************
*** DESCRIPTION : This file implements a stack ADT using a linked list. ***
*** Besides the standard constructor, copy, and destructor ***
*** functions, the available functions include: ***
*** * push - pushes data onto the stack ***
*** * pop - pops data from the stack ***
*** * peek - view the top element on the stack ***
*** * view - output every element on the stack ***
*******************************************************************************/
#ifndef _KIELASJC2_H
#define _KIELASJC2_H
// User specified element type
typedef char ElementType;
class StackType{
// Exportable definitions
public:
// Constructor
StackType();
// Copy constructor
StackType( StackType& copyStack );
// Destructor
~StackType();
// Push data onto the stack
void push( const ElementType pushElem );
// Pop data from the stack
void pop( ElementType& popElem );
// Peek the top element on the stack without changing the stack
void peek( ElementType& peekElem );
// Look at every element in the stack without changing the stack
void view();
private:
// Non-exportable definitions
struct NodeType;
typedef NodeType* PointerType;
struct NodeType{
ElementType element;
PointerType next;
};
PointerType theTop;
bool isEmpty( PointerType tempNode );
bool isFull( PointerType tempNode );
};
#endif
这是我的测试代码:
/*******************************************************************************
*** DESCRIPTION : This file implements a stack ADT using a linked list. ***
*** Besides the standard constructor, copy, and destructor ***
*** functions, the available functions include: ***
*** * push - pushes data onto the stack ***
*** * pop - pops data from the stack ***
*** * peek - view the top element on the stack ***
*** * view - output every element on the stack ***
*** It also includes two private functions: ***
*** * isEmpty - checks to see if the stack is empty ***
*** * isFull - checks to make sure temp wasn't NULL ***
*******************************************************************************/
#include <iostream> // For using cout
#include <iomanip> // For manipulating output
#include "kielasjc2.h" // Header to this implementation file
// Debug
#define DEBUG 0
// Namespace
using namespace std;
/*******************************************************************************
*** FUNCTION Constructor ***
********************************************************************************
*** DESCRIPTION : Initializes the class by setting theTop and tempNode to ***
*** NULL. ***
*** INPUT ARGS : NONE ***
*** OUTPUT ARGS : NONE ***
*** IN/OUT ARGS : NONE ***
*** RETURN : NONE ***
*******************************************************************************/
StackType::StackType() {
// Initialize both top and temp to NULL
theTop = NULL;
}
/*******************************************************************************
*** FUNCTION Copy Constructor ***
********************************************************************************
*** DESCRIPTION : Creates a copy of the stack linked list by popping all ***
*** elements in the first stack into a temporary stack. All ***
*** elements from the temporary stack are then pushed back ***
*** into the copied stack and original stack. ***
*** INPUT ARGS : NONE ***
*** OUTPUT ARGS : StackType& copyStack - copy of the original stack ***
*** IN/OUT ARGS : NONE ***
*** RETURN : NONE ***
*******************************************************************************/
StackType::StackType( StackType& copyStack ) {
// Point the top to NULL
theTop = NULL;
// Create a temporary stack
StackType tempStack;
// Create a temporary element
ElementType tempElem;
// Create a temporary pointer to the top
//PointerType tempNode = theTop;
// Create a temporary pointer to the the top of the copy stack
//PointerType tempTempNode = tempStack.theTop;
//PointerType copyTempNode = copyStack.theTop;
// Loop through the entire stack and pop each element into the temp stack
while ( !copyStack.isEmpty( copyStack.theTop ) ) {
// Pop the current stack
copyStack.pop( tempElem );
// Push the popped element into the temp stack
tempStack.push( tempElem );
}
// Refill the current and copy stacks with the temp stack
while (!tempStack.isEmpty( tempStack.theTop )){
// Pop the temp stack
tempStack.pop( tempElem );
// Push the popped element onto the current newly copied stack
push( tempElem );
// Push the same popped element back onto the copy stack
copyStack.push( tempElem );
}
}
/*******************************************************************************
*** FUNCTION Destructor ***
********************************************************************************
*** DESCRIPTION : Destroys the current stack by popping every element. ***
*** INPUT ARGS : NONE ***
*** OUTPUT ARGS : NONE ***
*** IN/OUT ARGS : NONE ***
*** RETURN : NONE ***
*******************************************************************************/
StackType::~StackType() {
// Create a temporary element just so we can call pop
ElementType tempElem;
#if DEBUG
cout << "[+] DEBUG: FUNCTION - Destructor" << endl;
cout << "[+] theTop: " << theTop << endl;
#endif
// While the stack is not empty, pop
while (!isEmpty( theTop )) {
// Pop the top node
pop( tempElem );
}
}
/*******************************************************************************
*** FUNCTION push ***
********************************************************************************
*** DESCRIPTION : Pushes the input element onto the current stack. ***
*** INPUT ARGS : const ElementType pushElem - element to be pushed onto ***
*** the current stack. ***
*** OUTPUT ARGS : NONE ***
*** IN/OUT ARGS : NONE ***
*** RETURN : NONE ***
*******************************************************************************/
void StackType::push( const ElementType pushElem ) {
// Create a pointer to a new node
PointerType tempNode = new (nothrow) NodeType;
// Verify that the node isn't full
if (isFull( tempNode )) {
// Tell the user if new memory couldn't be allocated
cout << "[!] ERROR: (push) New dynamic node could not be created.";
cout << endl;
return;
}
#if DEBUG
ElementType tempElem;
cout << "[+] DEBUG: FUNCTION - push" << endl;
peek( tempElem );
cout << "[+] top before the push: " << tempElem << endl;
cout << "[+] Top ptr before: " << theTop << endl;
#endif
// Set the temporary node element to the element being pushed
tempNode->element = pushElem;
// Set the next pointer to the top
tempNode->next = theTop;
// If these two lines were flipped, the code works, but it creates a memory
// leak, so that doesnt work either
theTop = tempNode;
tempNode = NULL;
#if DEBUG
peek( tempElem );
cout << "[+] Top ptr after: " << theTop << endl;
cout << "[+] top after the push: " << tempElem << endl;
#endif
}
/*******************************************************************************
*** FUNCTION pop ***
********************************************************************************
*** DESCRIPTION : Pops the top element off of the current stack. ***
*** INPUT ARGS : NONE ***
*** OUTPUT ARGS : ElementType& popElem - Stores the element that was ***
*** popped from the stack.
*** IN/OUT ARGS : NONE ***
*** RETURN : NONE ***
*******************************************************************************/
void StackType::pop( ElementType& popElem ) {
// Create a temporary pointer
PointerType tempNode = theTop;
// Point temp to the same node the top is pointing to
//tempNode = theTop;
// Make sure the stack isn't empty
if (isEmpty( tempNode )) {
// Tell the user if the stack is empty
cout << "[!] ERROR: (pop) No node available to pop, stack is empty.";
cout << endl;
return;
}
#if DEBUG
cout << "[+] DEBUG: FUNCTION - pop" << endl;
cout << "[+] Top ptr before: " << theTop << endl;
#endif
// Point the top to the next node
theTop = theTop->next;
// Derefrence the next node of the current node being popped
tempNode->next = NULL;
// Pop the element into popElem
popElem = tempNode->element;
// Delete the node
delete tempNode;
// Point temp back to NULL
tempNode = NULL;
#if DEBUG
cout << "[+] Top ptr after: " << theTop << endl;
cout << "[+] Element being popped: " << popElem << endl;
#endif
}
/*******************************************************************************
*** FUNCTION peek ***
********************************************************************************
*** DESCRIPTION : Looks at the top element of the current stack by popping ***
*** it. The element is then pushed back onto the top of the ***
*** current stack. ***
*** INPUT ARGS : NONE ***
*** OUTPUT ARGS : ElementType& peekElem - stores the element being peeked. ***
*** IN/OUT ARGS : NONE ***
*** RETURN : NONE ***
*******************************************************************************/
void StackType::peek( ElementType& peekElem ) {
// Create a temporary pointer
//PointerType tempNode;
// Point temp to the top
//tempNode = theTop;
// Make sure the stack isn't empty
if (isEmpty( theTop )) {
// Tell the user if the stack is empty
cout << "[!] ERROR: (peek) Stack is empty, no element to peek at.";
cout << endl;
// Return a null value if the stack is empty
peekElem = '\0';
return;
}
// Pop the top element into peekElem
pop( peekElem );
// Push the popped element back onto the top of the stack
push( peekElem );
#if DEBUG
cout << "[+] DEBUG: FUNCTION - peek" << endl;
cout << "[+] Peeked value: " << peekElem << endl;
#endif
}
/*******************************************************************************
*** FUNCTION view ***
********************************************************************************
*** DESCRIPTION : Shows the user every element on the current stack by ***
*** popping every element and pushing them into a temporary ***
*** stack. Once the user has seen the contents of the stack, ***
*** the elements on the temporary stack are popped and ***
*** pushed back onto the current stack. ***
*** INPUT ARGS : NONE ***
*** OUTPUT ARGS : NONE ***
*** IN/OUT ARGS : NONE ***
*** RETURN : NONE ***
*******************************************************************************/
void StackType::view() {
// Create a temporary stack
StackType tempStack;
// Create a temporary element
ElementType tempElem;
// Point a temporary node to the top
//PointerType tempNode = theTop;
// Point a temporary node to the top of the copy stack
//PointerType copyTempNode;
// View output for the user
cout << "The Top -> ";
// Loop through the entire stack and pop each element into the temp stack
while (!isEmpty( theTop )) {
// Pop the current stack
pop( tempElem );
// Push the popped element into the temp stack
tempStack.push( tempElem );
// Output the elements as the stack is popped
cout << tempElem << " -> ";
}
cout << "The Bottom" << endl;
// Refill the current stack with the temp stack
while (!tempStack.isEmpty( tempStack.theTop )){
// Pop the temp stack
tempStack.pop( tempElem );
// Push the popped element onto the current stack
push( tempElem );
}
}
/*******************************************************************************
*** FUNCTION isEmpty ***
********************************************************************************
*** DESCRIPTION : Checks to see whether or not the stack is empty. ***
*** INPUT ARGS : NONE ***
*** OUTPUT ARGS : NONE ***
*** IN/OUT ARGS : NONE ***
*** RETURN : bool true/false - true if the stack is empty, false ***
*** if the stack is not empty. ***
*******************************************************************************/
bool StackType::isEmpty( PointerType tempNode ) {
// If the top isn't pointing to NULL, our stack isn't empty yet
if (tempNode != NULL) {
return false;
} else {
return true;
}
}
/*******************************************************************************
*** FUNCTION isFull ***
********************************************************************************
*** DESCRIPTION : Checks to see if the current stack is full after ***
*** attempting to allocate new memory for the next node. ***
*** This will only provide a relevent value if it is used ***
*** immediately after trying to allocate memory for a new ***
*** node being pointed to by the tempNode. ***
*** INPUT ARGS : NONE ***
*** OUTPUT ARGS : NONE ***
*** IN/OUT ARGS : NONE ***
*** RETURN : bool true/false - true if the tempNode is NULL, false ***
*** if a pointer value was assigned to tempNode. ***
*******************************************************************************/
bool StackType::isFull( PointerType tempNode ) {
// If temp isn't NULL, we have successfully allocated memory.
// This function should only be used immediately after allocating new
// memory to the tempNode.
if (tempNode != NULL) {
return false;
} else {
return true;
}
}
最后,这是我收到的输出(包括错误):
#include <iostream>
#include "kielasjc2.h"
using namespace std;
int main(int argc, char* argv[]) {
StackType stack;
StackType stack2;
stack.push('a');
stack2 = stack;
cout << "Stack: ";
stack.view();
cout << endl;
cout << "Stack2: ";
stack2.view();
cout << endl;
}
答案 0 :(得分:0)
stack2 = stack;
不会调用您的复制构造函数。它调用编译器生成的复制赋值运算符,它只执行stack2.theTop = stack.theTop
。于是你最终得到两个对象,认为它们都拥有相同的节点集。
另请参阅:https://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)