Ошибка необработанного исключения с функцией Stack Pop()

Я работаю над домашним заданием, связанным со связанными списками, и у меня возникли проблемы с функцией Pop(). Вот мой код:

void CardStack::Pop( )
{
    if ( m_top->m_next == NULL )
    {
        delete m_top;
        m_top = NULL;
    }

    else
    {
        Node* ptrNode = m_top;

        // gets 2nd to last node
        while ( ptrNode->m_next != m_top )
        {
            ptrNode = ptrNode->m_next;
        }
        // delete last node, then set second to last to null
        delete m_top;
        m_top = NULL;

        ptrNode->m_next = NULL;
        m_top = ptrNode;
    }
    m_size--;
}

Я продолжаю получать эту ошибку времени выполнения, когда запускаю программу, прерывая оператор if:

Необработанное исключение по адресу 0x008e2009 в назначении 7 — CS201.exe: 0xC0000005: место чтения с нарушением прав доступа 0x00000004.

Мой друг порекомендовал удалить m_top = NULL из программы, чтобы оператор if работал. Я бы предпочел сохранить нулевое значение без изменений, но это заставило программу двигаться. В любом случае, он прерывает цикл while с этой ошибкой:

Необработанное исключение по адресу 0x00b91f4a в назначении 7 — CS201.exe: 0xC0000005: место чтения с нарушением прав доступа 0xfeeefeee.

Я проверил это с помощью инструкции cout, и ошибка исходит из тела цикла while; ptrNode = ptrNode->m_next. Я не совсем уверен, как обойти это. Мы будем очень признательны за любые советы.

Кроме того, вот большая часть остальной части моей программы, если это поможет:

Заголовок:

class Node
{
public:
    friend class CardStack;

private:
    Node* m_next;
    int m_data;
};

class CardStack
{
public:
    CardStack();
    ~CardStack();

    void Push( int value );
    void Pop();
    int Top();
    int GetSize();

private:
    int m_size;
    Node* m_top;
};

Конструктор, деструктор, Push():

#include <iostream>
#include "CardStack.h"
using namespace std;

CardStack::CardStack( )
{
    m_top = NULL;
    m_size = 0;
}

CardStack::~CardStack( )
{
    while ( m_top != NULL )
    {
        Pop( );
    }
}

void CardStack::Push( int value )
{
    //creates new node
    Node* newNode = new Node;
    newNode->m_data = value;
    newNode->m_next = NULL;

    // tests if the list is empty
    if ( m_top == NULL )
    {
        m_top = newNode;
    }
    // if the list does contain data members and a last node exists
    else
    {
        m_top->m_next = newNode;
        m_top = newNode;
    }
    m_size++;
}

Главный:

#include <iostream>
#include <string>
#include <fstream>
#include "CardStack.h"
using namespace std;

void loadDeck ( ifstream&, CardStack& );
void playGame ( CardStack& );

void loadDeck ( ifstream& inFile, CardStack *card )
{
    int currentCard;

    while( !inFile.eof() )
    {
        inFile >> currentCard;
        card->Push( currentCard );
    }
}

void playGame( CardStack *card )
{
    int score[ 4 ];
    int player;
    while( card->GetSize() != 0 )
    {
        player = card->GetSize() % 4;
        score[ player ] += card->Top();
        card->Pop();
    }

    for ( player = 0; player < 4; player++ )
        cout << "Player " << player << "'s score is " << score[ player ] << endl;
}

int main()
{
    CardStack *card = new CardStack;
    string fileName;
    ifstream inFile;

    do
    {
        cout << "Input the name of the card file (not including extension): ";
        cin >> fileName;

        fileName += ".txt";

        inFile.open( fileName );

        if ( !inFile.is_open() )
            cout << "File could not be opened. Reenter the file name." << endl;
    }
    while( !inFile.is_open() );

    loadDeck( inFile, card );
    playGame( card );

    inFile.close();

    system( "pause" );
    return 0;
}

person user2767836    schedule 04.12.2013    source источник


Ответы (2)


Это круговой связанный список? если нет, то почему вы тестируете в цикле:

while ( ptrNode->m_next != m_top )

и нет:

while ( ptrNode->m_next != NULL )

Если да, то почему вы устанавливаете:

ptrNode->m_next = NULL;

а не к "оригинальному" m_top->next??

person yosim    schedule 04.12.2013
comment
Я использовал пример кода, предоставленный моим профессором, чтобы заставить стек функционировать. Я думал, что понял код, но теперь я почти уверен, что это круговой связанный список, и я пытаюсь сделать линейный. Чувствую себя теперь идиотом. Итак, теперь я думаю, что моя главная проблема заключается в том, чтобы ptrNode указывал на начало списка или просто не на вершину. Единственное значение, которое я могу придумать, которое указывает на это, это newNode в Push(). - person user2767836; 04.12.2013

Вы должны только убедиться, что в первый раз в цикле

while ( ptrNode->m_next != m_top )
    {
        ptrNode = ptrNode->m_next;
    }

ptrNode не будет NULL, потому что вы проверили его в блоке if, но во второй раз в цикле ptrNode может быть NULL, потому что теперь он на самом деле

m_top->m_next->m_next

Но как вы можете убедиться, что m_top->m_next не равно NULL, когда оно равно NULL, произойдет сбой

Может быть, вы должны изменить его на

while ( ptrNode->m_next != NULL )
{
    ptrNode = ptrNode->m_next;
}

Кроме того, есть еще одна проблема, в вашей функции push

else
{
    m_top->m_next = newNode;
    m_top = newNode;
}

должно быть

else
{
    newNode->m_next = m_top;
    m_top = newNode;
}
person Daniel King    schedule 04.12.2013