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 }

 

转载于:https://www.cnblogs.com/dou-ya/p/4811929.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值