简单计算器
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 11355 Accepted Submission(s): 3697
Problem Description
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
Input
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
Output
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
Sample Input
1 + 2 4 + 2 * 5 - 7 / 11 0
Sample Output
3.00 13.36
Source
思路:
对于中缀表达式的运算一般要转化成后缀表达式再作运算,开两个栈,一个作为操作数栈StackDigital,一个作为操作符栈StackOperator。
1.定义一个函数判定优先级:# 的优先级最低,为0,+ 和 - 的级别相同且高于 #,标为1,* 和 / 的级别相同且高于 + 和 - ,标志为2,
2.先往运算符栈放入一个 # (标定界限),表达式最后也加一个 #( (标定界限)),
3.遍历表达式,若读到数字,则以数字类型输入,直接放到操作数栈,
若读到的是运算符,则比较读到的运算符与运算符栈顶符号的级别,
若比栈顶的高,则入栈,否则,从数栈取两个操作数根据操作符栈顶的操作进行运算,再把结果压入数栈,刚刚读到的运算符再与现在运算符栈
顶元素的级别进行比较……最后数剩下的一个元素,就是结果。
#include <iostream>
#include <cstdio>
#include <string.h>
#include <ctype.h>
using namespace std;
double stDit[300];
char stOp[300],str[300];
int top1,top2;
int Priority(char op)
{
if (op=='#')
return 0;
if (op=='+' || op=='-')
return 1;
if (op=='*' || op=='/')
return 2;
else
return -1;
}
double Operate(double x,double y,char op)
{
if (op=='+') return x+y;
if (op=='-') return x-y;
if (op=='*') return x*y;
if (op=='/') return x/y;
else return -1;
}
double Calc()
{
double x,y,tmp;
char op;
int i,n = strlen(str);
top1 = top2 = -1;
stOp[++top2] = '#';
str[n++] = '#';
for(i=0; i < n; ++i)
{
if (str[i]==' ')
continue;
if (isdigit(str[i])) //是数字
{
sscanf(str+i,"%lf",&tmp);
stDit[++top1] = tmp; //stack push
while(isdigit(str[i+1])) //+1很重要
++i;
}
else //是操作符
{
while (Priority(stOp[top2]) >= Priority(str[i]))//如果操作栈顶的操作符优先级高,则作+-*/运算
{
if (str[i]=='#' && stOp[top2]=='#')
return stDit[top1];
y = stDit[top1--];
x = stDit[top1--];
op = stOp[top2--];
stDit[++top1] = Operate(x,y,op);
}
stOp[++top2] = str[i]; //如果新操作符优先级高,str[i]进栈
}
}
return stDit[top1];
}
int main()
{
int i;
while (gets(str) != NULL && strcmp(str,"0")!=0)
{
printf("%.2lf\n",Calc());
}
return 0;
}