使用C++模版实现一个模版栈,并将中缀字符串计算式转化为逆波兰表达式,实现一个简单计算器功能。计算器有 + - * / ,支持负号,不支持小数,数字范围为 int 类型的取值范围。
下面为代码:
stack_template.h
#ifndef _MY_STACK_H
#define _MY_STACK_H
#include
template
struct stackNode
{
T data;
stackNode *prev;
stackNode() {}
stackNode(const T& data) : data(data), prev(nullptr){}
stackNode(const T& data, stackNode* prev) : data(data), prev(prev){}
};
template
class my_stack
{
public:
my_stack() : stackSize(0), stackTop(nullptr){}
my_stack(T& data) : stackSize(1), stackTop(stackNode(data)){}
bool isEmpty() const { return stackSize == 0; }
unsigned int size() const { return stackSize; }
void push(const T& data);
void pop();
T& top() const;
private:
unsigned int stackSize;
stackNode *stackTop;
};
template
void my_stack::push(const T& data)
{
stackNode *newNode = new stackNode(data, stackTop);
stackTop = newNode;
++stackSize;
}
template
void my_stack::pop()
{
if (isEmpty())
throw std::range_error("Stack is empty,can't pop");
stackNode *temp = stackTop;
stackTop = stackTop->prev;
delete temp;
--stackSize;
}
template
T& my_stack::top() const
{
if (isEmpty())
throw std::range_error("Stack is empty,can't get the top");
return stackTop->data;
}
#endif // !_MY_STACK_H
postFixExp.h
#ifndef _POST_FIX_EXP_H
#define _POST_FIX_EXP_H
char* postFixExp(char inFixExp[]);
bool isOperator(char src);
//src符号比栈顶符号优先级高,返回1,不高(低或等于)返回0。
bool compareOper(char src, char stackTop);
char* pretreatment(char *src, int size);
char* disposeMinus(char **src, char **p_res);
#endif // !_POST_FIX_EXP_H
calculator.h
#ifndef _CALCULATOR_H
#define _CALCULATOR_H
int calculator(char *src);
int calculation(int left, int right, char oper);
int ten_power(int i);
#endif // !_CALCULATOR_H
postFixExp.cpp
#include "stack_template.h"
#include "postFixExp.h"
char* postFixExp(char inFixExp[])
{
my_stack t_stack;
int size = 0;
char *temp = inFixExp;
while (*temp != 0)
{
++size;
++temp;
}
char *res = new char[size * 2];
char *p_res = res;
temp = pretreatment(inFixExp, size);
char *drop = temp;
unsigned int flag = 0;
while (*temp != 0)
{
if (isOperator(*temp))
{
if (flag > 0)
{
*p_res = ',';
flag = 0;
++p_res;
}
if (t_stack.isEmpty() || *temp == '(')
{
t_stack.push(*temp);
++temp;
}
else if (*temp == ')')
{
while (t_stack.top() != '(')
{
*p_res = t_stack.top();
++p_res;
t_stack.pop();
}
t_stack.pop();
++temp;
}
else
{
if (compareOper(*temp, t_stack.top()))
{
t_stack.push(*temp);
++temp;
}
else
{
while (!t_stack.isEmpty() &&
!compareOper(*temp, t_stack.top()))
{
*p_res = t_stack.top();
++p_res;
t_stack.pop();
}
t_stack.push(*temp);
++temp;
}
}
}
else
{
*p_res = *temp;
++p_res;
++temp;
++flag;
}
}
if (flag > 0)
{
*p_res = ',';
flag = 0;
++p_res;
}
while (!t_stack.isEmpty())
{
*p_res = t_stack.top();
++p_res;
t_stack.pop();
}
*p_res = 0;
delete drop;
return res;
}
bool isOperator(char src)
{
if (src == '+' || src == '-' || src == '*'
|| src == '/' || src == '(' || src == ')'
|| src == '$')
return true;
return false;
}
bool compareOper(char src, char stackTop)
{
int left = 0; //src符号的优先级
int right = 0; //stackTop符号的优先级
//switch...case...
if (src == '+' || src == '-')
left = 1;
else if (src == '*' || src == '/')
left = 2;
else if (src == '$')
left = 3;
//switch...case...
if (stackTop == '+' || stackTop == '-')
right = 1;
else if (stackTop == '*' || stackTop == '/')
right = 2;
else if (stackTop == '$')
right = 3;
if (left > right)
return 1;
return 0;
}
char* pretreatment(char *src, int size)
{
char *res = new char[size * 2];
char *p_res = res;
if (*src == '-')
{
disposeMinus(&src, &p_res);
}
while (*src != 0)
{
if (*src == '-'
&& isOperator(*(src - 1))
&& *(src - 1) != ')')
{
disposeMinus(&src, &p_res);
}
else
{
*p_res = *src;
++p_res;
++src;
}
}
*p_res = 0;
return res;
}
char* disposeMinus(char **src, char **p_res)
{
**p_res = '(';
++(*p_res);
**p_res = '0';
++(*p_res);
**p_res = '-';
++(*p_res);
++(*src);
while (!isOperator(**src)
&& **src != 0)
{
**p_res = **src;
++(*p_res);
++(*src);
}
**p_res = ')';
++(*p_res);
return *p_res;
}
calculator.cpp
#include "stack_template.h"
#include "postFixExp.h"
#include "calculator.h"
int calculator(char *src)
{
char *temp = src;
my_stack t_stack;
int num = 0;
while (*temp != 0)
{
if (isOperator(*temp) || *temp == ',')
{
if (*temp == ',')
{
int t_num = 0;
for (int i = 0; i < num; ++i)
{
t_num += (t_stack.top() * ten_power(i));
t_stack.pop();
}
t_stack.push(t_num);
num = 0;
++temp;
}
else //计算过程
{
int left = 0;
int right = 0;
right = t_stack.top();
t_stack.pop();
left = t_stack.top();
t_stack.pop();
t_stack.push(calculation(left, right, *temp));
++temp;
}
}
else
{
t_stack.push((*temp) - '0');
++temp;
++num;
}
}
return t_stack.top();
}
int calculation(int left, int right, char oper)
{
switch (oper)
{
case '+':
return left + right;
case '-':
return left - right;
case '*':
return left * right;
case '/':
return left / right;
default:
break;
}
}
int ten_power(int i)
{
int temp = 1;
for (int j = 0; j < i; ++j)
{
temp *= 10;
}
return temp;
}
main.cpp
#include "stack_template.h"
#include "postFixExp.h"
#include "calculator.h"
#include
using std::cout;
using std::endl;
int main()
{
//$为假设的最高优先级符号,仅为测试
char test[100] = "33+555$222*48$250+6-(45*21-2*2)";
char *res = postFixExp(test);
cout << res << endl;
//计算器测试
//表达式中 对负号的特殊处理,基本完备
char test2[100] = "-33+5*(-2)-17*-2+(36-8*2)+100*-2+50*24+2*-2";
res = postFixExp(test2);
cout << res << endl;
cout << calculator(res) << endl;
delete res;
return 0;
}
程序很简单,功能也比较少,而且代码也比较乱,内容也有很多冗余,仅供交流。