简单计算器
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 14384 Accepted Submission(s): 4861
Problem Description
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
Input
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
Output
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
Sample Input
1 + 2
4 + 2 * 5 - 7 / 11
0
Sample Output
3.00
13.36
思路:
字符串读入一行数据;
1、从字符串末尾开始倒着将数据分别压入数字栈和操作符栈(注意在转换十进制数字时对数据的处理,因为是倒着读取的,会有点麻烦。)
2、取出一个操作符和两个操作数
3、比较取出的操作符与栈顶的操作符的优先级,若取出的操作符大,则计算该操作符将结果押回数字栈;
4、若栈顶的操作符优先级大,则取出操作符栈顶操作符与数字栈顶的数据,先运算第二个操作符,将结果押回数据栈,把最开始的那个操作数与操作符分别押回数据和操作栈;
5、循环上述2、3、4步骤,直到有一个栈为空。输出结果。
最开始一直wa,看别人的代码嫌太长,第一版代码晾了很久,昨天拿出来把十进制处理过程改了一下,把数据类型改成double,终于AC了。。。
/*有bug——输入数据为单个数字或者为00000...时输出为0,但是杭电居然过了
*代码不长,就是注释占了版面。。。
*/
#include <iostream>
#include <stack>
#include <string.h>
#include <cstdio>
using namespace std;
char inputs[201];
int judge(char c)
//判断字符类型
{
if(c >= '0' && c <= '9') return 1;
else if(c == '+' || c == '-') return 2;
//加减符号优先级小,所以返回值小于乘除号的返回值
else if(c == '*' || c =='/' ) return 3;
else return 0;
}
double cacul(double i,char c,double j)
//运算
{
double sum;
switch (c)
{
case '+':
sum = i + j;
break;
case '-':
sum = i - j;
break;
case '*':
sum = i * j;
break;
case '/':
sum = i / j;
break;
}
return sum;
}
int main()
{
double sum = 0,n1,n2,n3;
//养成用double类型的习惯,float类型精度不够,第一次用float WA了
char op1,op2;
int len,i,j,flag,k;
gets(inputs);
len = strlen(inputs);
while(len != 1 || inputs[0] != '0')
{
j =0;
i = len;
stack<char> stOperator;
stack<double> stNumber;
flag = k = 0;
//flag用于标记当前十进制数字位数,k用来存储十进制数
while(i >= 0)
//进栈处理,从字符串后部开始倒着压入
{
if(judge(inputs[i]) == 1)
//当前字符为数字,转换为十进制
{
int l = inputs[i] - '0';
for(j = 0;j < flag;j++)
//因为是倒着处理的,所以与平常转化为十进制的方法不同,建议手动调试一个样例
l = l * 10;
k += l;
flag++;
}
else if(judge(inputs[i]) >= 2)//遇到一个运算符,则将十进制数字与运算符压入栈
{
stNumber.push(k);
//十进制数进栈
flag = 0;
//位数清0
stOperator.push(inputs[i]);
//操作符进栈
k = 0;
}
i--;
}
stNumber.push(k);
//将最后一个数字压入栈
while(!stNumber.empty() && !stOperator.empty())
//当栈有一个为空时,说明已经计算完毕
{
op1 = stOperator.top();
stOperator.pop();
// 取出第一个运算符
if(!stOperator.empty())op2 = stOperator.top();
//如果运算符栈不为空则取出下一个运算符
else op2 ='\0';
//否则op2用空字符标记
n1 = stNumber.top();
stNumber.pop();
//取出第一个操作数
n2 = stNumber.top();
stNumber.pop();
//取出第二个操作数
if( judge(op2) > judge(op1))
//后一个符号优先级大于前一个
{
n3 = stNumber.top();
stNumber.pop();
//取出第三个操作数
sum = cacul(n2,op2,n3);
//运算优先级高的操作符
stNumber.push(sum);
//将结果押回操作数栈
stNumber.push(n1);
//将先前第一个操作数押回
stOperator.pop();
//删除已经运算完的操作符,因为在取第二个操作符时没有删除操作
stOperator.push(op1);
//押回第一个操作符
}
else//前后优先级相同
{
sum = cacul(n1,op1,n2);
//计算第一个操作符
stNumber.push(sum);
//押回结果
}
}
printf("%.2f\n",sum);
gets(inputs);
len = strlen(inputs);
}
return 0;
}