2010-11-25 67 views
0

無法讓我的代碼的一部分工作。建立一個基本的鏈表來學習指針。我認爲我的大部分工作都停止了,但是任何嘗試使用我創建的函數(push_back)都會在爲指針設置值時拋出內存訪問錯誤。設置對象屬性時出現C++內存訪問衝突

不完全確定有什麼問題,因爲它使用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; 
} 

鏈表。^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

清理格式,似乎對我很瘋狂。 – DivinusVox 2010-11-25 22:05:09

+1

選擇整個代碼並用1和0單擊該按鈕。 – Dialecticus 2010-11-25 22:11:13

+2

如果崩潰是在`push_back`,也許你應該提供`linklist.cpp`? – icecrime 2010-11-25 22:14:34

回答

1

根據node的定義,它是一個單鏈表。 (否則你必須包含prevNode)。

因此 - 操縱列表的「後退」並不重要。要彈出列表的「後面」,您需要橫切整個列表並確定新的「最後」元素。

你確定你是對的嗎?包括處理所有「極值」情況(如刪除最後一個元素等)?

很高興發佈push_backpop_back的代碼。

P.S.也許您在push_frontpop_front中沒有正確設置lastNode。除非你試圖操縱你的「背影」,否則你可能不會注意到這一點。

發佈代碼push_frontpop_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; 
} 
1

那麼,當列表爲空,在push_backtemp爲NULL。因此temp->setNextNode(input)失敗。你需要區分空列表的特例。順便說一下,如果你允許前後兩個操作,也許你需要一個雙向鏈表?否則,您將需要遍歷整個(可能很大)的列表以便彈出最後一個元素,因爲您沒有到其之前元素的「直接」鏈接。

順便說一句,你的操作是雙向的,而不是列表。

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。流行例程不返回任何東西並且不常見,而是與peek()例程配對,以支持異常中立/安全。

相關問題