计算器(表达式)

//weizengke 2011-7-8
/*
计算器(表达式)
栈操作;
运算符栈顶的优先级较高
可以处理确保正确的表达式的求值,可以使浮点型的小数运算

  输入一下各种表达式:
    8*.2
 	-2
	5.6*(-2*(1+(-3)))
	2*((4+2)*5)-7/11
	((((2+3)*2+4.0*2)*4)+2)*4
	1+2+3
	2*(6+((2+3)*2+2)/2+3)
	2*(2+(3+(4+2*(5+6))))
*/
#include <stack>
#include<iostream>
#include <cmath>
#include <ctype.h> 
#include <cstdlib>
using namespace std;
const int NUM_MAX = 10;
const int MAX = 1000;
stack<char> sOper;
stack<double> sNum;
char expr[1000]="\0";
bool isNum(char c)
{
	if(c=='.'||isdigit(c)) return 1;
	else return 0;
}
bool isCalaOper(char c)
{
	if(c=='+'||c=='-'||c=='*'||c=='/') return true;
	else return false;
}
bool isOper(char c)
{
	if(c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')'||c=='=') return true;
	else return false;
}
double calc(double a, char oper, double b)
{
	switch (oper)
	{
	case '+': return a+b;
		break;
	case '-': return a-b;
		break;
	case '*': return a*b;
		break;
	case '/': return a/b;
		break;
	}
}
int YXJ(char op)
{

	if(op=='=') return -1;

	if(sOper.empty()) return 0;

	char preOper=sOper.top();

	if(preOper=='(') return 2; 

	if(op=='*'||op=='/')  {
		if(preOper=='+'||preOper=='-') return 1;
		else return -1;
	}
	if(op=='+'||op=='-')  {
		if(preOper=='*'||preOper=='/') return -1;
		else return -1;
	}
	
}

void getValue(int preI,int n) //应该限制n的长度。
{
	char cnum[NUM_MAX];
	memset(cnum,'\0',sizeof(cnum));
	double num;
	strncpy(cnum,&expr[preI],n);   	//	cout<<preI<<"--"<<i<<"=";
	num=atof(cnum);
	sNum.push(num);
}

double caculate()
{
	double res;
	char op=sOper.top();
	if(op!=')'&&op!='(')
	{
		sOper.pop();
		double a,b;
		b=sNum.top();
		sNum.pop();
		a=sNum.top();
		sNum.pop();
	//	cout<<"calc:"<<a<<op<<b<<"=";
		res = calc(a,op,b);
	//	cout<<res<<endl;
		sNum.push(res);
	}
	return res;
}
int init()
{
	int i=0,j;
	int len=strlen(expr);
	while(expr[i]!='\0')
	{
		if(!(isNum(expr[i])||isOper(expr[i])||expr[i]==' ')) return 0;

		if(expr[i]==' ')
		{
			for (j=i;j<len;j++)
			{
				expr[j]=expr[j+1];
			}
			expr[j]='\0';
			len--;
		}
		i++;
	}
	expr[i]='=';
	expr[i+1]='\0';
	return 1;
}
int Check(char *str)   //检查括号匹配性
{
	stack <char> s;
	int i=0;
	while (str[i]!='\0')
	{
		if(str[i]=='(') s.push(str[i]);
		if(str[i]==')'){
			if(s.empty()) return 0;
			else s.pop();
		}
		i++;
	}
	if(s.empty()) return 1;
	else return 0;
}
int main()
{

   freopen("in.txt","r",stdin);
   while(gets(expr))
   {
	 if(strcmp(expr,"0")==0) break;

	 if(!Check(expr)){
		 cout<<expr<<" is Not Format (括号不匹配)..."<<endl;
		 continue;
	 }
	 if(!init()) {//初始化去掉空格并加上=号......可增加检查语法错误方法
		 cout<<expr<<" is Not Format (存在非法字符)..."<<endl;
		 continue;
	 } 

	int i=0;
	int preI=0;
 	for (i=0;expr[i]!='\0';i++)
 	{
	
		if(isNum(expr[i])){
			preI=i;
			while(isNum(expr[i])) {
				i++;
			}
			getValue(preI,i-preI);
		}
		
		if(isOper(expr[i])) {
			if(expr[i]=='(') {//是'(',不必处理
				sOper.push(expr[i]);
				continue;
			}
		if(expr[i]==')') { //处理最近一对括号
			while(sOper.top()!='(')  //持续计算到弹出左括号
			{
				caculate();
			}
			sOper.pop();//弹出左括号
			continue;
		}
		if(isCalaOper(expr[i-1])) {
			//cout<<expr<<" Is Not Format..."<<endl;
			break;
				//表达是错误
		}
      //暂时无法处理 *2+1之类的非-+得变号问题
		if(/*(expr[i]=='-'||expr[i]=='+')&&*/(expr[i-1]=='('||i==0)) 
			sNum.push(0);  //处理变号  2*(-5+6) to 2*(0-5+6)
		else {
				//cout<<expr<<" Is Not Format..."<<endl;
				//break;
				//表达是错误
			}

			//循环判断是否需要持续进行计算,并执行相应动作
		while(!sOper.empty()){
			int Yxj=YXJ(expr[i]);
			if(Yxj==-1)	caculate();
			if(Yxj==0)	caculate();
			if(Yxj==1)	break;
			if(Yxj==2)	break;
		}
			//本次运算符入栈
			sOper.push(expr[i]);
			continue;
		}
		//表达是错误(出现其他字符)
 	}

	//处理最后一步(此时必然只剩下最后一次运算)
	sOper.pop();//剔除等号
	if(!sOper.empty()){
		caculate();
	}
	double ans=sNum.top();
	sNum.pop();

	if(!sNum.empty()||!sOper.empty()) cout<<expr<<" Is Not Format (运算符使用错误)..."<<endl;
 	else cout<<expr<<ans<<endl;

	while(!sNum.empty()) sNum.pop();
	while(!sOper.empty()) sOper.pop();

   }
	return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值