利用栈实现一个简易的计算器(数据结构之栈)

利用栈实现一个简易的计算器

实现了加减乘除运算(没有使用STL)

基本思想:

1.一个数据栈,一个符号栈

2.优先级判断

3.负号和减号的判别与处理

4.括号匹配

代码如下:

代码语言:javascript
复制
#include<iostream>
#include<string>
#include<cstdlib>
/*1、创建栈类,采用数组描述;
2、计算数学表达式的值。
输入数学表达式,输出表达式的计算结果。数学表达式由单个数字和
运算符“+”、“-”、“*”、“/”、“(”、“) ”构成,例如 2+3*(4+5)–6/4。
假定表达式输入格式合法。
选做:*3、以一个 m*n 的长方阵表示迷宫,0 和 1 分别表示迷宫中的通路和障碍。
设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
迷宫根据一个迷宫数据文件建立。迷宫数据文件由一个包含 0、1 的矩阵
组成。迷宫的通路可以使用通路上各点的坐标序列进行展示(使用图形展示最佳)。*/
using namespace std;
template<class T>
class mystack
{//创建一个栈类 
	public:
		mystack();                  //无参构造函数 
		mystack(int initialCapacity){//含参构造函数 
			stackLength=initialCapacity;
			stack=new T[stackLength];     //stack为一个数组 
			stackTop=-1;//初始化栈顶元素 
		}
		~mystack(){delete [] stack;	}//析构函数 
		bool empty(){ return stackTop==-1;}//判断栈是否为空 
		int size(){ return stackTop+1;}//返回栈中元素个数 
		T & top()//返回栈顶元素 
		{
			if(stackTop==-1){//栈空 
				cout<<"该栈为空"<<endl;
			} 
			else return stack[stackTop];
		}
		void pop()//弹出栈顶元素 
		{
			if(stackTop==-1){
				cout<<"该栈为空"<<endl;
			} 
			else stack[stackTop--];//.~T()
		}
		void push(T theElement){//将theElement压入栈 
			if(stackTop==stackLength-1)//栈满扩充 
			{
				stackLength*=2;      //将栈的容量扩充二倍 
				T newStack[stackLength];
				for(int i=0;i<stackLength;i++)
				{
					newStack[i]=stack[i];
				}
				delete stack;
				stack=newStack;	
			}
			stack[++stackTop]=theElement;//然栈顶元素等于目前需要压入栈中的元素 
		}
	private:
		int stackTop;   //栈顶元素索引 
		int stackLength;//栈大小 
		T * stack;      //栈 
};
void calculate(mystack<long int> &n, mystack<char> &c)
{//定义运算,将数字栈的前两个数和符号栈栈顶元素取出做一次运算 并将结果压入数字栈 
	if(c.top()=='(') return;
	long int a,b;
	a=n.top();    
	//cout<<a<<"    a的值"<<endl;       //取数字栈栈顶元素 
	n.pop();             //弹出栈顶元素 
	b=n.top();   
	//cout<<b<<"    b的值"<<endl;         //取数字栈第二个元素 
	n.pop();             //弹出栈顶元素 
	switch(c.top())
	{                    //根据符号栈的栈顶元素不同进行不同运算 
		case '+':
			n.push(a+b);
			break;
		case '-':
			n.push(b-a);
			break;
		case '*':
			n.push(a*b);
			break;
		case '/':
			n.push(b/a);
			break;	
		default:break;
	}
	c.pop();//将运算完的符号弹出栈 
}
void operate(string s,int length) 
{
	bool flag=false;      //用来判断输入-的是否为负号 
	mystack<long int> n(length);     //声明一个数字栈 
	mystack<char> c(length);       //声明一个字符栈 
		for(int i=0;i<length;i++)      //遍历输入的表达式 
	{
		if(s[i]==' ') continue;       //如果输入的如果是空格,跳过 
		if(s[i]>='0'&&s[i]<='9')      //当输入为数字时 
		{
			int k=s[i]-'0';
			while(s[i+1]>='0'&&s[i+1]<='9')//如果下一个为数字 则记录整个数字
			{
				k=10*k+(s[i+1]-'0');
				i++;
			}
			if(flag){                //判断是否为负数 
			 //   c.pop(); 
				k=-k;
				flag=false;          //读到一个负数,标识符归零 
			}
			n.push(k);               //将读入的数字压到数字栈 
		}
		else
		{//读到的是字符 
			if((i==0||s[i-1]=='(')&&s[i]=='-')//-号前面为(或者-号为第一个代表-为负号而不是减号 
			{
				flag=true;
				continue;
			}
			switch(s[i]){
				case '+':
				case '-':
					if(c.empty()||c.top()=='(') c.push(s[i]);//如果符号栈为空或者栈顶元素为(,+、-直接压入栈 
					else{
						calculate(n,c);                      //+-运算符优先级最低,对之前运算先运算 
						if(!c.empty()&&c.top()!='(') calculate(n,c);
						c.push(s[i]);                        //将读到的符号压入栈 
					}
					break;
				case '*':
				case '/':
					if(c.empty()||c.top()=='(') c.push(s[i]);//如果符号栈为空或者栈顶元素为(,*/直接压入栈 
					else if(c.top()=='+'||c.top()=='-') c.push(s[i]);//如果前一个运算符为+或-,*/直接压入栈 
					else if(c.top()=='*'||c.top()=='/')
						{                                     //前一个运算符为*或/可以直接运算 
							calculate(n,c);
							c.push(s[i]);
						 } 				
					break;
				case '('://左括号直接入栈 
					c.push(s[i]);
					break;
				case ')'://遇到右括号 ,对括号内运算直至运算到左括号 
					while (c.top()!='(') {
					calculate(n,c);
				//	c.pop();
					}
					c.pop();//将左括号弹出栈 
					break;
				default:break;
			}
		}
	}
		cout<<"计算所得的结果是:"; 
	while(!c.empty()) calculate(n,c);
			cout<<n.top()<<endl;
}
int main()
{  
    while(1){
	string s;             //将输入的表达式存到一个字符串中 
	int length;           //记录字符串长度 
	cout<<"请输入一个运算表达式:"<<endl; 
	cin>>s;               //输入表达式 
	length=s.length();	
    operate(s,length);
	}
    return 0;
}