Пишу калькулятор. Хочу решить полученное выражение, используя алгоритм польской инверсии. Для того, чтобы проще было работать с многоразрядными числами и символами в одной сущности - создал класс Autostack. Попрошу сильно не критиковать, ибо это один с моих первых классов (но совет или замечание не помешали б). Суть проблемы после исходников.
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
Autostack.cpp:
#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;
}
Ну и исполняемый файл с функцией main (source.cpp):
#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;
}
Ошибка "heap corruption detected: after normal block (#158) at (адрес)" возникает при каждой попытке закинуть число 20 (5-я итерация; 19-я строка кода). Я так подозреваю, что проблема с динамическим выделением памяти. Можете помочь решить эту проблему, ибо я уже без понять что делать?