Постфиксный расчет с классом стека, C ++ - PullRequest
1 голос
/ 24 февраля 2020

Я пытаюсь использовать собственный класс стека для вычисления уравнения в постфиксной форме. По какой-то причине программа продолжает падать.

Вот файл заголовка стека

#ifndef aStack_h
#define aStack_h
#include <string>
#include <iostream>

using std::string; using std::cout;
class aStack
{
    private:
        int top, size;
        int *stack;
    public:
        aStack(int s)
        {
            size = s;
            top = -1;
            stack = new int [s];
        }

        ~aStack() 
        {
            delete [] stack;
        }
        void reset();
        void push(int);
        void pop();
        int getTop();
        void getSize()
        {
            std::cout << size;
        }
};

#endif

Файл реализации класса:

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

void aStack::pop()
{
    if (top == -1)
        { cout << "Stack is already empty.\n";}
    stack[--top];

}

void aStack::push(int v)
{
    if (top == size)
        { cout << "Stack is full.\n";}
    stack[top++] = v;
}

void aStack::reset()
{
    top = -1;
}

int aStack::getTop()
{
    return top;
}

Вот основная программа

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

int main()
{
    string equation {"35+1*"};
    int op, count = 0, *oparray, result;
    aStack stack(equation.length());

    for (int i = 0; i < equation.length(); i++)
        {
            if (isdigit(equation[i]))
            {

                stack.push(equation[i]);
                count++;
            }
            else 
                {
                    oparray = new int [count];
                    for (int o = 0; o < count; o++) 
                        {
                            oparray[o] = stack.getTop();
                            stack.pop();
                        }
                    switch(equation[i])
                        {
                            case '+':
                                for (int i =0; i < count; i++)
                                    {
                                        op += oparray[i];
                                        count--;
                                    }
                                stack.push(op);
                                break;


                            case '-':
                                for (int i =0; i < count; i++)
                                    {
                                        op-=oparray[i];
                                        count--;
                                    }
                                stack.push(op);
                                break;
                            case '*':
                                for (int i =0; i < count; i++)
                                    {
                                        op*=oparray[i];
                                        count--;
                                    }
                                stack.push(op);
                                break;
                            case '/':
                                for (int i =0; i < count; i++)
                                    {
                                        op/=oparray[i];
                                        count--;
                                    }
                                stack.push(op);
                                break;
                        }
                    delete [] oparray;
                }
        }
    result = stack.getTop();
    cout << result;
}

I знаете, я не должен использовать "использование пространства имен std;", я спешил. Я сомневаюсь, что это станет причиной моих проблем. Любая помощь очень ценится.

1 Ответ

1 голос
/ 24 февраля 2020

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

Я использовал std::unique_ptr<> в вашем массиве вместо необработанного указателя и отключил семантику перемещения, поэтому он не может быть скопирован (из-за unique_ptr) ни подвижный.

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

#include <cctype>
#include <cstddef>
#include <exception>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>

template<typename T>
class aStack {
public:
    using value_type = T;

    explicit aStack(size_t c) :
        cap(c), stored(0), stack(std::make_unique<value_type[]>(cap)) {}

    aStack(aStack&&) = delete;  // moving disabled

    void reset() noexcept { stored = 0; }

    void push(const value_type& v) {
        if(stored == cap) throw std::runtime_error("stack is full");
        stack[stored++] = v;
    }
    void push(value_type&& v) {
        if(stored == cap) throw std::runtime_error("stack is full");
        stack[stored++] = std::move(v);
    }
    value_type& pop() {
        if(stored == 0) throw std::runtime_error("stack is empty");
        return stack[--stored];
    }
    [[nodiscard]] const value_type& top() const {
        if(stored == 0) throw std::runtime_error("stack is empty");
        return stack[stored - 1];
    }
    [[nodiscard]] value_type& top() {
        if(stored == 0) throw std::runtime_error("stack is empty");
        return stack[stored - 1];
    }
    [[nodiscard]] size_t capability() const noexcept { return cap; }
    [[nodiscard]] size_t size() const noexcept { return stored; }

private:
    size_t cap, stored;
    std::unique_ptr<value_type[]> stack;
};

Когда дело доходит до основной программы, основной проблемой было то, что вы забыл преобразовать значение ASCII каждого di git в целое число. Другой проблемой был расчет op. Вы сохранили значение из последней итерации вместо того, чтобы получить новое значение из стека. Было также дополнительное выделение памяти, которое было ненужным, поэтому я удалил его. У вас также были shadowing переменные, которые не вызывали ошибок, но затрудняли чтение кода.

int main(int argc, char* argv[]) {
    if(argc < 2) {
        std::cout << "USAGE: " << argv[0] << " <equation>\n";
        return 1;
    }
    std::string equation(argv[1]);
    try {
        int op, result;
        aStack<int> stack(equation.length());

        for(size_t ei = 0; ei < equation.length(); ++ei) {
            if(std::isdigit(equation[ei])) {
                stack.push(equation[ei] - '0'); // from ASCII to digit
            } else {
                op = stack.pop();               // start with what's on the stack
                switch(equation[ei]) {
                case '+':
                    while(stack.size()) {
                        op += stack.pop();
                    }
                    stack.push(op);
                    break;
                case '-':
                    while(stack.size()) {
                        op -= stack.pop();
                    }
                    stack.push(op);
                    break;
                case '*':
                    while(stack.size()) {
                        op *= stack.pop();
                    }
                    stack.push(op);
                    break;
                case '/':
                    while(stack.size()) {
                        op /= stack.pop();
                    }
                    stack.push(op);
                    break;
                default:
                    throw std::runtime_error("invalid operation");
                }
            }
        }
        result = stack.pop();
        if(stack.size() != 0)
            throw std::runtime_error("stack not empty when calculation ended");

        std::cout << result << '\n';
    } catch(const std::exception& ex) {
        std::cerr << "Exception: " << ex.what() << '\n';
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...