C++逆波兰表达式转化实现简单计算器

使用C++模版实现一个模版栈,并将中缀字符串计算式转化为逆波兰表达式,实现一个简单计算器功能。计算器有 + - * / ,支持负号,不支持小数,数字范围为 int 类型的取值范围。C++逆波兰表达式转化实现简单计算器_第1张图片

下面为代码:

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;
}

程序很简单,功能也比较少,而且代码也比较乱,内容也有很多冗余,仅供交流。

你可能感兴趣的:(C++逆波兰表达式转化实现简单计算器)