简单计算器 HDU 1237

来源:互联网 发布:图表数据区域格式 编辑:程序博客网 时间:2024/06/05 15:49

简单计算器
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;}
0 0