zoukankan      html  css  js  c++  java
  • nyoj 35-表达式求值(stack, 栈的应用)

    35-表达式求值


    内存限制:64MB 时间限制:3000ms Special Judge: No
    accepted:37 submit:53

    题目描述:

    ACM队的mdd想做一个计算器,但是,他要做的不仅仅是一计算一个A+B的计算器,他想实现随便输入一个表达式都能求出它的值的计算器,现在请你帮助他来实现这个计算器吧。
    比如输入:“1+2/4=”,程序就输出1.50(结果保留两位小数)

    输入描述:

    第一行输入一个整数n,共有n组测试数据(n<10)。
    每组测试数据只有一行,是一个长度不超过1000的字符串,表示这个运算式,每个运算式都是以“=”结束。这个表达式里只包含+-*/与小括号这几种符号。其中小括号可以嵌套使用。数据保证输入的操作数中不会出现负数。
    数据保证除数不会为0

    输出描述:

    每组都输出该组运算式的运算结果,输出结果保留两位小数。

    样例输入:

    2
    1.000+2/4=
    ((1+2)*5+1)/4=

    样例输出:

    1.50
    4.00

    分析与步骤:
      ①、类似于表达式求解问题需要用到栈(stack)的思想(即就是先进后出)
      ②、遇到数字就将数字放入数字栈中
      ③、遇到字符串就要分开考虑
        1、是‘(’就直接入栈,方便遇到')'时,就将'('以后所有的运算栈带入数字栈运算,结果保存于数字串
        2、如果操作栈为空栈直接入栈
        3、如果操作栈的栈顶元素优先级小于带输入字符的优先级直接入栈
        4、其他情况就是要将数字栈与操作栈结合,算出结果保存在数字栈中
        5、数字栈中的最后一个元素即为题解

    核心代码(表达式求值模板);
     1 int priority(char c) // 表达优先级的大小关系
     2 {
     3     if (c == '*' || c == '/') return 2;
     4     if (c == '+' || c == '-') return 1;
     5     return 0;
     6 }
     7 
     8 void cal(stack<char> &my_op, stack<double> &my_num) // 将数字栈与操作栈通过引用的形式实现调用与更改
     9 {
    10     double b = my_num.top();
    11     my_num.pop();
    12     double a = my_num.top();
    13     my_num.pop();
    14     switch(my_op.top())
    15     {
    16         case '+': my_num.push(a + b); break;
    17         case '-': my_num.push(a - b); break;
    18         case '*': my_num.push(a * b); break;
    19         case '/': my_num.push(a / b); break;
    20     }
    21     my_op.pop();
    22 }
    23 for(int i = 0; i < len; ++ i) // 判断是因该执行什么操作
    24 {
    25     if(isdigit(s[i]))
    26     {
    27         double temp = atof(&s[i]);
    28         while(isdigit(s[i]) || s[i] == '.') ++ i;
    29         my_num.push(temp);
    30         -- i;
    31     }
    32     else if(s[i] == '(')
    33     {
    34         my_op.push(s[i]);
    35     }
    36     else if(s[i] == ')')
    37     {
    38         while(my_op.top() != '(')
    39             cal(my_op, my_num);
    40         my_op.pop();
    41     }
    42     else if(my_op.empty())
    43     {
    44         my_op.push(s[i]);
    45     }
    46     else if(priority(my_op.top()) < priority(s[i]))
    47     {
    48         my_op.push(s[i]);
    49     }
    50     else if(priority(my_op.top()) >= priority(s[i]))
    51     {
    52         while(!my_op.empty() && priority(my_op.top()) >= priority(s[i])) // 比较的是优先级关系不是ASCⅡ
    53             cal(my_op, my_num);
    54         my_op.push(s[i]);
    55     }
    56 }

    C/C++代码实现(AC):

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <cstdio>
     5 #include <cmath>
     6 #include <stack>
     7 #include <map>
     8 #include <queue>
     9 #include <set>
    10 
    11 using namespace std;
    12 const int MAXN = 1010;
    13 
    14 int priority(char c) // 表达优先级的大小关系
    15 {
    16     if (c == '*' || c == '/') return 2;
    17     if (c == '+' || c == '-') return 1;
    18     return 0;
    19 }
    20 
    21 void cal(stack<char> &my_op, stack<double> &my_num) // 将数字栈与操作栈通过引用的形式实现调用与更改
    22 {
    23     double b = my_num.top();
    24     my_num.pop();
    25     double a = my_num.top();
    26     my_num.pop();
    27     switch(my_op.top())
    28     {
    29     case '+':
    30         my_num.push(a + b);
    31         break;
    32     case '-':
    33         my_num.push(a - b);
    34         break;
    35     case '*':
    36         my_num.push(a * b);
    37         break;
    38     case '/':
    39         my_num.push(a / b);
    40         break;
    41     }
    42     my_op.pop();
    43 }
    44 
    45 int main()
    46 {
    47 
    48     int t;
    49     scanf("%d", &t);
    50     while(t --)
    51     {
    52         char s[MAXN];
    53         scanf("%s", s);
    54         int len = strlen(s);
    55         stack <double> my_num;
    56         stack <char> my_op;
    57 
    58         for(int i = 0; i < len; ++ i)
    59         {
    60             if(isdigit(s[i]))
    61             {
    62                 double temp = atof(&s[i]);
    63                 while(isdigit(s[i]) || s[i] == '.') ++ i;
    64                 my_num.push(temp);
    65                 -- i;
    66             }
    67             else if(s[i] == '(')
    68             {
    69                 my_op.push(s[i]);
    70             }
    71             else if(s[i] == ')')
    72             {
    73                 while(my_op.top() != '(')
    74                     cal(my_op, my_num);
    75                 my_op.pop();
    76             }
    77             else if(my_op.empty())
    78             {
    79                 my_op.push(s[i]);
    80             }
    81             else if(priority(my_op.top()) < priority(s[i]))
    82             {
    83                 my_op.push(s[i]);
    84             }
    85             else if(priority(my_op.top()) >= priority(s[i]))
    86             {
    87                 while(!my_op.empty() && priority(my_op.top()) >= priority(s[i])) // 比较的是优先级关系不是ASCⅡ,my_op.top()忘记放在priority中,弄的找了半天的bug,::>_<::
    88                     cal(my_op, my_num);
    89                 my_op.push(s[i]);
    90             }
    91         }
    92         my_op.pop();
    93         printf("%.2lf
    ", my_num.top());
    94         my_num.pop();
    95     }
    96     return 0;
    97 }
  • 相关阅读:
    C语言 sprintf 函数 C语言零基础入门教程
    C语言 printf 函数 C语言零基础入门教程
    C语言 文件读写 fgets 函数 C语言零基础入门教程
    C语言 文件读写 fputs 函数 C语言零基础入门教程
    C语言 fprintf 函数 C语言零基础入门教程
    C语言 文件读写 fgetc 函数 C语言零基础入门教程
    C语言 文件读写 fputc 函数 C语言零基础入门教程
    C语言 strlen 函数 C语言零基础入门教程
    Brad Abrams关于Naming Conventions的演讲中涉及到的生词集解
    适配器模式
  • 原文地址:https://www.cnblogs.com/GetcharZp/p/9070083.html
Copyright © 2011-2022 走看看