简单计算器 HDU 1237

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

你可能感兴趣的:(ACM,HDU)