• Complicated Expression


    2016 网易校招的一道题

    写了一年多的lua, C++ 都生锈了,拿出来操练一下
     
    在lisp语言中,表达式都用前缀法表示,例如,1 + 2 在lisp中使用(+ 1 2)来表示,其中,表达式的括号是必需的。Bob 想实现一种类 lisp 的脚本语言,这个语言中的表达式是这样定义的:

    1、每个表达式的形式都是 ( operator arg_1 arg_2 ... ),即由左括号,运算符,运算数,和右括号组成。

    2、运算符包括三种,分别是'+', '-', '*'。

    3、运算符如果可以接受一个运算数,就称为一元运算符,如果可以接受两个运算数,就称为二元运算符,如果可以接受三个及以上运算数,就称为多元运算符。

    + 可以是一元,二元,乃至多元运算符。

    (+ 9) 表示正整数9;

    (+ 1 2) 代表 1 + 2;

    (+ 1 2 3 4) 代表 1, 2, 3, 4 的连加和。

    - 可以是一元或者二元运算符。

    (- 9) 表示整数-9;

    (- 5 4) 代表 5 - 4。

    * 可以是二元运算符或者多元运算符。

    (* 2 3) 代表 2 * 3;

    (* 1 2 3 4) 代表 1 * 2 * 3 * 4。

    4、运算数可以是一个正整数,或者0,还可以是另外一个表达式,例如

    (+ (* 2, 3) 1) 也是一个合法的表达式,代表了 2 * 3 + 1

    5、运算符与运算数之间,运算数与运算数相互之间都以空格进行分隔。在不产生歧义的情况下,空格也可以省略。例如,

    (+ 2 3) 和 ( +2 3) 都被认为是合法的输入,且有相同的意义,代表 2 + 3。(+ 23)也是一个合法的输入,但其代表的是正整数23。

    输入
    输入由多行组成,第一行包含一个正整数T(T <= 5000)。代表共包含T组测试数据。

    接下来会有T行输入。每一行包含一个表达式。这个表达式可能是一个合法的表达式,也可能是不合法的表达式。

    每行数据所包含的字符数,不超过1000000。

    输入数据中的数字全部是十进制正整数或者0,而且正整数的值不会大于65535。

    输入中的表达式只包含三种不同类型的错误,除此之外的情况,都不必考虑。

    第一类错误,括号不匹配,例如

    (+ (* 2 3) 1)) 多了一个右括号;

    + 2 3 缺少括号等。

    第二类错误,运算符缺失,例如

    (2 3) 没有运算符。

    第三类错误,运算符与数字不匹配,例如

    (- 1 2 3),由于 - 只能接受最多两个算数,所以这也是一个不合法的表达式。

    输出
    对于合法的表达式,请输出表达式的值,对于不合法的表达式,请输出“invalid expression”。

    可以假设最后的结果不超过32位整数的表示范围,但不保证在某些情况下,计算的中间值全部不超过32位整数的表示范围。

    样例输入
    5
    (+ 1 (* 2 3)))
    (2 3)
    (- 3 2 1)
    (+ (+ 1 2) (* 2 3) (- 2 1))
    (- 2)
    样例输出
    invalid expression
    invalid expression
    invalid expression
    10
    -2
     
     
     这题就是对栈的使用,学过数据结构的应该都会。只是时间长短而已,不得不承认工作久了写这种东西明显不如学生时代了。
     
    源代码:
     
      1 #include <iostream>
      2 //#include <string>
      3 #include <stack>
      4 #include <stdio.h>
      5 #include <string.h>
      6 
      7 using namespace std;
      8 
      9 typedef std::stack<std::string> strStack;
     10 typedef std::stack<double> valueStack;
     11 
     12 
     13 inline int parseStr(const char*& str, strStack &tempStack)
     14 {
     15     const char* begin = str;
     16     const char* p = str;
     17     while (*p)
     18     {
     19         char buf[50];
     20         if (*p == '(' || *p == '+' || *p == '-' || *p == '*')
     21         {
     22             buf[0] = *p;
     23             buf[1] = 0;
     24             tempStack.push(buf);
     25             if (p == begin)
     26                 ++begin;
     27         }
     28         else if (*p == ' ')
     29         {
     30             if (p == begin)
     31                 ++begin;
     32             else
     33             {
     34                 int size = p - begin;
     35                 strncpy(buf, begin, size);
     36                 buf[size] = 0;
     37                 tempStack.push(buf);
     38                 begin = p + 1;
     39             }
     40         }
     41         else if (*p == ')')
     42         {
     43             if (p != begin)
     44             {
     45                 int size = p - begin;
     46                 strncpy(buf, begin, size);
     47                 buf[size] = 0;
     48                 tempStack.push(buf);
     49                 begin = p + 1;
     50             }
     51             ++p;
     52             break;
     53         }
     54         else
     55         {
     56             // 可以做一些非法字符检查, 这题貌似不需要
     57         }
     58         ++p;
     59     }
     60     str = p;
     61     return 0;
     62 }
     63 
     64 
     65 inline int calAdd(strStack& stack, double&result)
     66 {
     67     if (stack.size() < 1)
     68         return -1;
     69 
     70     double r = 0;
     71     while (!stack.empty())
     72     {
     73         std::string str = stack.top();
     74         stack.pop();
     75         double val;
     76         sscanf(str.c_str(), "%lf", &val);
     77         r += val;
     78     }
     79     result = r;
     80     return 0;
     81 }
     82 
     83 inline int calSub(strStack& stack, double&result)
     84 {
     85     if (stack.size() < 1 || stack.size() > 2)
     86         return -1;
     87 
     88     std::string str = stack.top();
     89     stack.pop();
     90     double val1;
     91     sscanf(str.c_str(), "%lf", &val1);
     92     if (stack.size() == 0)
     93     {
     94         result = -val1;
     95         return 0;
     96     }
     97 
     98     str = stack.top();
     99     stack.pop();
    100     double val2;
    101     sscanf(str.c_str(), "%lf", &val2);
    102     result = val1 - val2;
    103 
    104     return 0;
    105 }
    106 
    107 inline int calMul(strStack& stack, double& result)
    108 {
    109     if (stack.size() < 1)
    110         return -1;
    111 
    112     double r = 1;
    113     while ( !stack.empty())
    114     {
    115         std::string str = stack.top();
    116         stack.pop();
    117         double val;
    118         sscanf(str.c_str(), "%lf", &val);
    119         r *= val;
    120     }
    121     result = r;
    122     return 0;
    123 }
    124 
    125 
    126 // 成功返回0
    127 int calSubOprator(strStack& stack, double &result)
    128 {
    129     int r = 0;
    130     double val = 0;
    131     std::string operaterStr = stack.top();
    132     stack.pop();
    133     if (operaterStr == "+")
    134     {
    135         r = calAdd(stack, val);
    136     }
    137     else if (operaterStr == "-")
    138     {
    139         r = calSub(stack, val);
    140     }
    141     else if (operaterStr == "*")
    142     {
    143         r = calMul(stack, val);
    144     }
    145     else
    146         return -1;
    147 
    148     if (r == -1)
    149         return -1;
    150 
    151     result = val;
    152     return 0;
    153 }
    154 
    155 inline int calcStr(strStack &tempStack, valueStack& resultStack)
    156 {
    157     strStack temp;
    158     while (true)
    159     {
    160         if (tempStack.empty())
    161             return -1;
    162 
    163         std::string str = tempStack.top();
    164         if (str == "#")
    165         {
    166             double val = resultStack.top();
    167             resultStack.pop();
    168             tempStack.pop();
    169             char buf[50];
    170             sprintf(buf, "%d", int(val));
    171             temp.push(buf);
    172         }
    173         else if (str == "(")
    174         {
    175             tempStack.pop();
    176             break;
    177         }
    178         else
    179         {
    180             temp.push(tempStack.top());
    181             tempStack.pop();
    182         }
    183     }
    184 
    185     double val;
    186     if (calSubOprator(temp, val) == -1)
    187         return -1;
    188 
    189     resultStack.push(val);
    190     return 0;
    191 }
    192 
    193 
    194 int calc(const char* str, double &resultVal)
    195 {
    196     if (str == NULL || *str == 0)
    197         return -1;
    198 
    199     const char* p = str;
    200     strStack tempStr;
    201     valueStack tempVal;
    202 
    203     while (true)
    204     {
    205         int r = 0;
    206         r = parseStr(p, tempStr);
    207         if (r == -1)
    208             return -1;
    209 
    210         r = calcStr(tempStr, tempVal);
    211         if (r == -1)
    212             return -1;
    213 
    214         if (*p == 0)
    215         {
    216             if (tempStr.empty())
    217             {
    218                 resultVal = tempVal.top();
    219                 tempVal.pop();
    220             }
    221             else
    222                 return -1;
    223             break;
    224         }
    225         else
    226         {
    227             // 临时结果入栈
    228             tempStr.push("#");
    229         }
    230     }
    231 
    232     return 0;
    233 }
    234 
    235 
    236 int main()
    237 {
    238 
    239     const char*arr[] = {
    240         "(+ 1 (* 2 3)))",
    241         "(2 3)",
    242         "(- 3 2 1)",
    243         "(+ (+ 1 2) (* 2 3) (- 2 1))",
    244         "(- 2)"
    245     };
    246 
    247 
    248     for (int i = 0; i < 5; ++i)
    249     {
    250         const char* buf = arr[i];
    251         double result = 0;
    252         if (calc(buf, result) == 0)
    253         {
    254             cout << result << endl;
    255         }
    256         else
    257         {
    258             cout << "invalid expression" << endl;
    259         }
    260 
    261     }
    262 
    263     return 0;
    264 }
  • 相关阅读:
    app.config应该放哪?
    Connection 和Dispose的学习日志
    简单的sqlhelper的学习日志
    EF 事务(非分布式事务)
    Angularjs 地址联动2.1.1
    C# 如何物理删除有主外键约束的记录?存储过程实现
    C# 枚举基本用法及扩展方法
    JS 去除重复元素的方法
    MVC4程序运行报错
    ASP.NET MVC4 & Entity Framework 6.0 IIS 部署出错解决方案
  • 原文地址:https://www.cnblogs.com/dou-ya/p/4811929.html
Copyright © 2020-2023  润新知