Реализация стека в C ++ с использованием класса, вызывающего ошибку сегментации - PullRequest
2 голосов
/ 16 марта 2019

Я реализовал некоторые функции стека в C ++.Я не уверен, почему я получаю ошибку сегментации.Сейчас у меня есть 7 разных файлов: node.h, node.cpp, LL.h, LL.cpp, Stack.h, Stack.cpp и main.cpp, которые я использую для тестирования LL.cpp и Stack.cpp.Если бы кто-нибудь мог направить меня к ошибке, я был бы очень признателен.Вот коды:

node.h:

// node.h

class node { // node class used in the LL (linked list) class
    private:
        node * next; // Pointer to next node of an LL
        int data;    // integer data stored in this node

    public:
        node(int x, node * n);  // Constructor
        ~node();                // Destructor
        void set_data(int x);   // Change the data of this node
        void set_next(node * n);// Change the next pointer of this node
        int get_data();         // Access the data of this node
        node * get_next();      // Access the next pointer of this node
};  

LL.h:

// LL.h
#include "node.h"

// Linked list class, used in the Stack class
class LL {
    private:
        node * head; // pointer to first node
        node * tail; // pointer to last node

    public:
        LL(); // Constructor
        ~LL(); // Destructor
        void prepend(int value); // add a node to the beginning of the LL
        int removeHead();        // remove the first node of the LL
        void print();            // print the elements of the LL
    node * get_head();       // access the pointer to the first node of the LL
};

Stack.h:

// Stack.h
#include "LL.h"

class Stack {
    private:
        LL * intlist;

    public:

        Stack();    // Constructor
        ~Stack();       // Destructor

        void push(int value);
        int pop();      
        int isEmpty();
        void Sprint();
};

Stack.cpp:

// Stack.cpp
#include "Stack.h"
#include <stdio.h>

Stack::Stack() {
}

Stack::~Stack() {
}

int Stack::isEmpty() {
    return ( (intlist->get_head()) ==NULL);
}

void Stack::push(int value) {
    intlist->prepend(value);
}

int Stack::pop() {

    if ( ! isEmpty() ) {
        int result=intlist->removeHead();
        return result;
    }
    return -1;
}

void Stack::Sprint() {

    intlist->print();
}

А вот main.cpp, который я использую для его проверки:

// main.cpp
#include "Stack.h"
#include <stdio.h>

int main() {
        LL a;
        a.prepend(3);
        a.prepend(4);
        a.prepend(5);
        a.print();
        a.removeHead();
        a.print();

        Stack sta;
    sta.pop();
        sta.push(3);
        sta.push(4);
        sta.push(10);
    sta.Sprint();

    printf("Popping %d\n", sta.pop());
        sta.Sprint();

        sta.pop();
    printf("Stack empty? %d\n", sta.isEmpty());

        sta.pop();
        printf("Stack empty? %d\n", sta.isEmpty());
    return 0;
}

Я пытался найти причину ошибки сегментации дляв то время как.Любая помощь приветствуется

Ответы [ 2 ]

3 голосов
/ 16 марта 2019

Эта программа дает сбой, потому что ваш класс Stack никогда не инициализирует указатель связанного списка (LL * intlist), поэтому, когда вы проверяете, пуст ли он, он пытается ссылаться на мусор:

Stack.pop() => Stack.isEmpty() => intlist->isEmpty() => segfault

Вы можете просто сделатьэто член вместо указателя (рекомендуется):

class Stack {
   private:
    LL intlist; // There's no need for it to be a pointer

   public:

    Stack();    // Constructor
    ~Stack();       // Destructor

    void push(int value);
    int pop();      
    int isEmpty();
    void Sprint();
};

Кроме того, вы можете инициализировать его в конструкторе и удалить в деструкторе.Вы действительно должны делать это только тогда, когда переменная-член нуждается в , чтобы быть указателем;в противном случае вы должны просто хранить его регулярно.

Stack::Stack() : intlist(new LL()) {       
}

Stack::~Stack() {
    delete intlist; 
}
2 голосов
/ 16 марта 2019

Указатель intlist в Stack никогда не инициализируется, поэтому попытка разыменования вызвала ваш segfault (в данном случае это было, когда sta.pop() был впервые вызван).

Вы можете выделить память для intlist в конструкторе Stack (например, intlist = new LL;) и удалить ее, когда закончите (или использовать вместо этого умный указатель). Но в этом случае это принесет больше вреда, чем пользы.

Вероятно, вам лучше определить intlist как объект типа LL, а не указатель на него, в Stack:

class Stack {
    private:
        LL intlist;

    ...
};

Конечно, при работе с intlist.

не забудьте заменить все операторы стрелок (->) на точечные (.).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...