Answer the question
In order to leave comments, you need to log in
What is a memory error and how to solve it?
I am writing a calculator. I want to solve the resulting expression using the Polish inversion algorithm. In order to make it easier to work with multi-digit numbers and symbols in one entity, I created the Autostack class. I ask you not to criticize much, because this is one from my first classes (but advice or a remark would not hurt). The essence of the problem after the source.
autostack.h:
#ifndef AUTOSTACK
#define AUTOSTACK
#define last_id c_size+i_size
#include <iostream>
#include <string.h>
using namespace std;
class Autostack
{
char* _char;
int* _int;
bool* is_char;//отображает последовательность чисел и символов в стеке
short c_size = 0;//количество символов в стеке
short i_size = 0;//количество чисел в стеке
public:
void push(char);
void push(int);
int top(string&);//возвращает и char, но тип возвращаемого значения записывается в string type
void pop();
bool empty();
unsigned short size();
~Autostack();
private:
void addId(string);
void dropLastId();
void dropLastChar();
void dropLastInt();
};
#endif
#include "Autostack.h"
#include <conio.h>
using namespace std;
void Autostack::push(char ch)
{
char* ptr = new char[c_size];
for (short i = 0; i < c_size; i++)
ptr[i] = _char[i];
delete[] _char;
_char = new char[c_size + 1];
for (short i = 0; i < c_size; i++)
_char[i] = ptr[i];
_char[c_size++] = ch;
delete[] ptr;
addId("char");
}
void Autostack::push(int val)
{
int* ptr = new int[i_size];
for (short i = 0; i < i_size; i++)
ptr[i] = _int[i];
delete[] _int;
_int = new int[i_size + 1];
for (short i = 0; i < i_size; i++)
_int[i] = ptr[i];
_int[i_size++] = val;
delete[] ptr;
addId("int");
}
void Autostack::addId(string type)
{
bool* nptr = new bool;
for (short i = 0; i < last_id - 1; i++)//-1 так-как только что увелился размер i/c_size
nptr[i] = is_char[i];
delete[] is_char;
is_char = new bool[last_id];
for (short i = 0; i < last_id - 1; i++)
is_char[i] = nptr[i];
(type == "char") ? is_char[last_id - 1] = true : is_char[last_id - 1] = false;
delete[] nptr;
}
void Autostack::dropLastId()
{
bool* nptr = new bool[last_id - 1];
for (short i = 0; i < last_id - 1; i++)
nptr[i] = is_char[i];
delete[] is_char;
is_char = nptr;
}
void Autostack::dropLastChar()
{
char* nptr = new char[--c_size];
for (short i = 0; i < c_size - 1; i++)
nptr[i] = _char[i];
delete[] _char;
_char = nptr;
}
void Autostack::dropLastInt()
{
int* nptr = new int[--i_size];
for (short i = 0; i < i_size - 1; i++)
nptr[i] = _int[i];
delete[] _int;
_int = nptr;
}
int Autostack::top(string& type)
{
if (is_char[last_id - 1])
{
type = "char";
return _char[c_size - 1];
}
else
{
type = "int";
return _int[i_size - 1];
}
}
void Autostack::pop()
{
if (is_char[last_id - 1])
{
dropLastId();
dropLastChar();
}
else
{
dropLastId();
dropLastInt();
}
}
bool Autostack::empty()
{
if (last_id == 0)
return true;
else
return false;
}
unsigned short Autostack::size()
{
return last_id;
}
Autostack::~Autostack()
{
delete[] _char;
delete[] _int;
}
#include "Autostack.h"
#include <conio.h>
#include <stack>
using namespace std;
int getNumFromStr(const string, short&);
short getPrior(const char);
bool is_operator(const char ch);
void main()
{
string exp = "45+12*20-(4+2)";
Autostack res;//resulted stack
stack<char> ops;//operators
for (short i = 0; i < exp.length(); i++)
{
if (exp[i] >= 48 && exp[i] <= 57)//если число
res.push(getNumFromStr(exp, i));//закинуть в результирующий стек (ну и сместить индекс)
else
if (exp[i] == '+' || exp[i] == '-' || exp[i] == '*' || exp[i] == '/')
if (ops.empty() || getPrior(ops.top()) < getPrior(exp[i]))
ops.push(exp[i]);
else if(getPrior(ops.top()) >= getPrior(exp[i]))
while (!(ops.empty()) && getPrior(ops.top()) >= getPrior(exp[i]))
{
res.push(ops.top());
ops.pop();
}
if (exp[i] == '(')
ops.push(exp[i]);
if (exp[i] == ')')
{
char next_push;
do
{
res.push(ops.top());
ops.pop();
next_push = ops.top();
} while (next_push != '(');
ops.pop();//drop '(' from stack
}
}
//если вся входная строка разобрана, а в стеке еще остаются знаки операций - извлечение их с стека в результирующий стек
while (!ops.empty())
{
res.push(ops.top());
ops.pop();
}
string type;
while (!res.empty())
{
cout << res.top(type) << ' ';
res.pop();
}
_getch();
}
int getNumFromStr(const string str, short& beg_id)
{
int ret = 0;
short dig_count = 0;//количество цифр в считываемом числе
//считывание dig_count
for (short i = beg_id; i < str.length() && str[i] >= 48 && str[i] <= 57; i++, dig_count++)
continue;
unsigned short factor = pow(10, dig_count - 1);//множитель
for (short i = beg_id; i < str.length() && str[i] >= 48 && str[i] <= 57; i++, factor /= 10)
ret += factor*(str[i] - 48);//'str[i] - 48' преобразование с char в значение очередной цифры
beg_id += dig_count - 1;//-1 потому, что по идее вызов функции будет произведен в цикле последовательного перебора
//с постфиксной формой инкремента
//поэтому индекс указывает на последнюю цифру считываемого числа
return ret;
}
short getPrior(const char ch)
{
switch (ch)
{
case '*':
case '/': return 3;
case '+':
case '-': return 2;
case '(': return 1;
}
}
bool is_operator(const char ch)
{
return
(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(') ? true : false;
}
Answer the question
In order to leave comments, you need to log in
Here it is necessary to allocate an array, not a variable.
In general, the code barely pulls on a C grade. Using four! stacks where you can get by with two. Double copying arrays in push, where you can get by with one, not to mention realloc. Copying arrays on pop where it's not needed at all. Memory re-allocation for every push/pop.
Passing the type as a string instead of bool or enum.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question