用栈实现的算术表达式的运算

    用栈实现算术表达式的运算,需要两个栈:一个用于保存操作数,一个用于保存操作码(运算符)。基本的操作

过程是:(1)定义一个栈,这里用数组实现。说明两两个栈:numStack,opStack.

                (2)对表达式进行扫描:

  1. 如果是操作数直接进入操作数栈。
  2. 如果是操作向右的小括号,直接入栈。
  3. 如果是操作码,操作栈为空时,直接入栈。如果不空,弹出栈顶操作码,和当前的操作码比较优先级, 如果低于当前操作码,则弹出的操作码和当前的操作码先后入栈。如果不低于当前操作码,从操作数栈弹出二个操作数,用之前弹出的操作符进行运算(注意操作数先后顺序),结果入操作数栈。继续弹操作码栈,和当前操作码 比较,重复前面的处理方法,直到遇见低的操作码或操作码栈空,当前操作码入操作码栈。
  4. 如果遇到向左的小括号),直接弹出栈顶操作码和两个操作数,运算,结果入操作数栈,继续弹操作码和操作数,直到遇见向右的(,继续检查下一个表达式元素。

按上述步骤,直到表达的所以元素处理完毕。

下面是代码:该程序可以完成:加、减、乘、除和求余运算(+,-,* ,/,%),可以使用()改变优先级顺序。按浮点float类型运算。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_SIZE  100
typedef struct
 {
	char *pStr[MAX_SIZE];
	int top;
} STACK;

STACK numStack,opStack;

void initStack()
{
	opStack.top=-1;
	numStack.top=-1;
}
int push(char *num,STACK *stack)
{
   if (stack->top>=MAX_SIZE-1) 
	   return -1;
   stack->top++;
   stack->pStr[stack->top]=num;
   return 0;
}
int pop(char **num,STACK *stack)
{
   if (stack->top<0)
	   return -1;
	*num=stack->pStr[stack->top];
	stack->top--;
    return 0;
}
//比较优先级:return 1:op1>=op2, -1:op1<op2
int cmpPriority(char *op1,char *op2)
{
	int p=1;
	if ((strcmp(op1,"+")==0||strcmp(op1,"-")==0)&&(strcmp(op2,"*")==0||strcmp(op2,"/")==0||strcmp(op2,"%")==0)) 
		p=-1;
	return p;
}

void compute(char *num1,char *num2,char* op,char **value)
{
	char *str;
	float n1,n2,tmp;
	float result;
	int f=1;
	n1=(float)atof(num1);
	n2=(float)atof(num2);
	if (strcmp(op,"+")==0)
		result=n1+n2;
	else if (strcmp(op,"-")==0)
		result=n1-n2;
	else if (strcmp(op,"*")==0)
		result=n1*n2;
	else if (strcmp(op,"/")==0)
		result=n1/n2;
	else if (strcmp(op,"%")==0)
		result=(float)((int)n1%(int)n2);
    tmp=result;
	while (tmp/10) {f++;tmp=tmp/10;}
	str=(char*)malloc(f+8);   //可以保存到小数点后六位。
    sprintf(str,"%.6f",result); //浮点数转为字符串。小数点后保留六位
	*value=str;
}
//从字符串str中提取一个运算单元,返回1:数值,返回2:操作符。*start开始位置值,返回结束位置值,*subStr:返回串指针。
int getElement(char *str,int *start,int *type,char **subStr)
{
   int ret=0;
   unsigned i;
   *subStr=NULL;*type=1;
   for (i=*start;i<strlen(str);i++)
   {
	   if (str[i]=='('||str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/'||str[i]=='%'||str[i]=='('||str[i]==')')
	   {
		   *subStr=(char*)malloc(2);
		   (*subStr)[0]=str[i];(*subStr)[1]='\0';
		   *type=2;
		   *start=i+1;
		   break; 
	   } 
	   else if (str[i]>='0'&&str[i]<='9')
	   {    
		   int count=1,i0=i;
		   i++;
		   while ((str[i]>='0'&&str[i]<='9')||str[i]=='.') {i++;count++;}
		   *start=i++;
           *subStr=(char*)malloc(count+1);
            strncpy(*subStr,str+i0,count);(*subStr)[count]='\0';
			*type=1;
            break;
	   } else {ret=-1;break;}
   }
   return ret;
}
void main()
{
   char *result=0;
   char ops[MAX_SIZE]="5*6.7-(60.8-21.5)*2",*subStr;
   int re,status=0;
   char *c=NULL,*c0;
   char *num1,*num2;
   int type=1,start=0;
   initStack();
   
   printf("请输入计算式:");
   gets(ops);

   status=getElement(ops,&start,&type,&subStr);
   while (subStr!=NULL&&status>=0)
   {
	  
      if (type==2)
	  {
         if (opStack.top>=0)
		 {
		   if (strcmp(subStr,"(")==0)
			   push(subStr,&opStack); 
		    else if (strcmp(subStr,")")==0)
			{
				pop(&c0,&opStack);
				if (strcmp(c0,"(")!=0)
				{
				  status=pop(&num2,&numStack);
				  if (status<0) break;
				  status=pop(&num1,&numStack);
				  if (status<0) break;
                  compute(num1,num2,c0,&result);
				  push(result,&numStack);
				  free(num1);free(num2);free(c0);
				  continue;
				}
			}
		     else 
			{
			  pop(&c0,&opStack);
			  if (strcmp(c0,"(")==0)
			  {
				  push(c0,&opStack);push(subStr,&opStack);
			  }
			  else if ((re=cmpPriority(c0,subStr))>0)
			  {
				
                 status=pop(&num2,&numStack);
			     if (status<0) break;
				 status=pop(&num1,&numStack);
			      if (status<0) break;
				 compute(num1,num2,c0,&result);
			     push(result,&numStack);
				 free(num1);free(num2);free(c0);
			     continue;
			  }
		      else {push(c0,&opStack);push(subStr,&opStack);}
			}
		 } else push(subStr,&opStack);
	  } else push(subStr,&numStack);
	  status=getElement(ops,&start,&type,&subStr);
   }
   
   
   while (opStack.top>=0&&status>=0)
   {
	   pop(&c,&opStack);
	   
       status=pop(&num2,&numStack);
	   if (status<0) break;
	   status=pop(&num1,&numStack);
       if (status<0) break;
	   compute(num1,num2,c,&result);
	   free(num1);free(num2);free(c);
	   push(result,&numStack);
   }
   if (numStack.top==0)
       pop(&result,&numStack);
   else status=-1;
   if (status>=0) {
	   printf("Result=%s\n",result);
	   
   }
   else printf("表达式中有错误.\n");
}

                     经测试,能正确完成运算。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值