[C++] Odwracanie stosu i jego przetwarzanie

0

Napisałem program do liczenia wyrażeń ONP (odwrotnej notacji polskiej). Okazało się, że muszę go trochę zmienić i ta zmiana nastręcza mi problemów.
Z klawiatury wpisuję wyrażenie które następnie układane jest na stos. Następnie żeby obliczyć wartość wyrażenia muszę je odczytać od dołu (wiem, że mógłbym ze stosu zrobić listę, ale nie o to mi chodzi), zatem odwracam stos i przetwarzam kolejne elementy. Problem w tym, że przy przetwarzaniu dostaję segmentation fault i nie mogę dociec dlaczego.

Oto klasy mojego programu:

#include <iostream>

using namespace std;

class Stos;

class Element
{
    protected:
        Element* next;

    public:
        Element() : next(0) {};
        Element(const Element & e);
        Element * nxt() { return next; }
        virtual string pokaz()=0;
        virtual void przetwarzaj(Stos & s)=0;
        virtual double pokaz_l()=0;
        virtual char pokaz_z()=0;
        virtual int precShow()=0;
        friend class Stos;
        Element* wpisz();
        friend void rev(Stos & s);

};

class Liczba : public Element
{
    private:
        double el;

    public:
        Liczba(double l=0) {el=l;}
        virtual double pokaz_l() {return el;}
        virtual char pokaz_z() {return el;}
        virtual int precShow() { return 0; }
        virtual void przetwarzaj(Stos & s);
        virtual string pokaz();
        operator const double*();
};

class Dzialanie : public Element
{
    private:
        char el;
        int prec;

    public:
        Dzialanie(char z=0);
        virtual char pokaz_z() {return el;}
        virtual double pokaz_l() {return el;}
        virtual int precShow() { return prec; }
        virtual void przetwarzaj(Stos & s);
        virtual string pokaz();
        Dzialanie& operator=(const Dzialanie & d);
        operator const char*();

};

class Stos
{

    private:
        Element* top;
        int count;

    public:
        Stos() : top(0), count (0) {};
        ~Stos();
        Stos(const Stos & s);
        Stos& operator=(const Stos & s);
        void put(Element* e);
        void pop();
        Element * showTop();
        Stos & reverse();
        int countShow() { return count; }
    friend class Element;
    friend class Liczba;
    friend class Dzialanie;
    friend double oblicz_onp_lepsze(Stos & s);
        void pokaz_caly();

};
double oblicz_onp_lepsze(Stos & s)
{
    Stos s1;

    int cnt=s.countShow();
    for(int u=0; u<cnt; u++)
    {
        s.top->przetwarzaj(s1);
        s.pop();
    }

    return s1.top->pokaz_l();
}

countShow() - liczba elementów na stosie

przetwarzaj(Stos & s) to funkcja wirtualna klasy Element, jeśli jest to Liczba to po prostu kładzie się ją na stosie, a jeśli operator - bierzemy dwie kolejne liczby ze stosu, wykonujemy na nich działanie i kładziemy na stos wynik.

void Dzialanie::przetwarzaj(Stos & s)
{
    double a, b;

    //double a = static_cast<Liczba*>(s.top)->el;
    if(s.countShow()>1)
    {
        a = s.top->pokaz_l();
        s.pop();
        b = s.top->pokaz_l();
        s.pop();
    }
    else
    {
        cout << "Wprowadzono niepoprawne wyrazenie ONP. Wychodze...";
        exit(1);
    }

    Element * tmp;
    double e;

    switch (el)
    {
    case '+':
        tmp = new Liczba(a+b);
        break;
    case '-':
        tmp = new Liczba(b-a);
        break;
    case '/':
        tmp = new Liczba(b/a);
        break;
    case '*':
        tmp = new Liczba(a*b);
        break;
    case '^':
        e = b;
        if(a>0)
        {
            for(int j=1; j<a; j++)
            e*=b;
        }
        else if (a<0)
        {
            for(int j=a; j<=0; j++)
            e*=1/b;
        }
        else
            e = 1;
        tmp = new Liczba(e);
        break;
    default:
        break;
    }

    s.put(tmp);
}

Sprawdzałem czy dobrze odwraca stos wyświetlając go - wszystko w porządku. Wrzucę jeszcze funkcję odwracającą, kładącą element i zdejmującą go.

Stos& Stos::reverse()
{
    if(!count)
        return *this;

    Element* pt=top;
    Element** tmp=new Element*[count];



    for(int j=0; j<count; j++)
    {
        tmp[j]=pt;
        pt=pt->next;
    }

    tmp[0]->next=0;

    for(int j=1; j<count; j++)
        tmp[j]->next=tmp[j-1];

    top=tmp[count-1];
    delete [] tmp;

    return *this;
}

void Stos::put(Element* e)
{
    e->next = top;
    top = e;
    count++;
}

void Stos::pop()
{
    Element* tmp=top;
    top=top->next;
    delete tmp;
    count--;
}

Przy debugowaniu widzę, że pętla w pierwszym przejściu działa poprawnie (przetwarza stos i dobrze rozpoznaje wskaźnik na obiekt Liczba), lecz już w drugim przejściu wywala segfaulta na linijce s.top->przetwarzaj(s1); - tak jakby s.top nie było tym czego oczekuje.

Mam nadzieję że nie zapomniałem o żadnym ważnym fragmencie kodu. Bardzo proszę o wskazówkę - jeśli rozwiążę ten problem, program będzie gotowy (:

0

Jeśli można, to podbiję... bo temat chyba już zaginął.

1 użytkowników online, w tym zalogowanych: 0, gości: 1