DS18 Alice做算术(3)

  • A+
所属分类:ACM

DS18 Alice做算术(3)

memory limit: 65536KB time limit: 1000MS

accept: 3 submit: 6

Description

对于单个的算术运算,Alice都已经掌握得很好了。爸爸开始出一些混合运算的题目给Alice做。每做完10道题目,就可以吃一个香蕉船。现在,Alice不但会求余运算,也学会了负数,因此,无论运算的中间结果和最终结果是负数,她都会做。
一般来说,一天下来,Alice都做不完10题。为什么呢?因为爸爸使坏了:虽然这些式子的每个运算都很简单,只有四则运算以及括号,但有些式子很长,有近万个运算数。有时Alice一条式子还没做完,就已经累得睡着了。

Input

有多行,每行代表一个算式。每行不超过10000个字符。式子中不含空格。

Output

对每行输入,输出一行结果。

对于非法运算,输出 illegal operation

Sample Input

1+2*10-10/2=

6/(5+1)=

1+1*3=

4/2*8=

10-5/2=

3*2/1=

12*5+3-10/5=

1/0=

Sample Output

16

1

4

16

8

6

61

illegal operation

Author

John

思路

做的时候发现ZQU的测试数据表达式居然包含空格,另外测试数据也不包含‘-(2+3)’,‘-(-3)’之类的数据,似乎有点弱。

下面给出我的代码,不过以下代码可以处理上面比较特别的数据,但需保证表达式绝对不含空格。

PS:如果包含空格的话,请自行在代码中多加一行除去空格即可。

#include <iostream>
#include <stack>
using namespace std;
const int maxn = 10010;
bool error; // 表达式是否存在错误
stack <int> istack; // 存放操作数
stack <char> cstack; // 存放操作符
stack <int> fstack; // 存放‘(’前的正负号
bool preop; // 前一个符号是否是操作符
bool prenum; // 前一个符号是否是操作数
int flag, num; // 正负号,及数字大小
void Init()
{
 while (!istack.empty()) istack.pop();
 while (!cstack.empty()) cstack.pop();
 while (!fstack.empty()) fstack.pop();
 preop = true;
 prenum = false;
 error = false;
 num = 0;
 flag = 1;
}
void Get(int &a)
{
 if (!istack.empty())
 {
  a = istack.top();
  istack.pop();
 }
 else error = true;
}
void Add()
{
 int a, b;
 Get(a);
 Get(b);
 if (!error) istack.push(b+a);
}
void Sub()
{
 int a, b;
 Get(a);
 Get(b);
 if (!error) istack.push(b-a);
}
void Mul()
{
 int a, b;
 Get(a);
 Get(b);
 if (!error) istack.push(b*a);
}
void Div()
{
 int a, b;
 Get(a);
 Get(b);
 if (!a) error = true;
 if (!error) istack.push(b/a);
}
void GetOp(char &op)
{
 if (!cstack.empty())
 {
  op = cstack.top();
  cstack.pop();
 }
 else error = true;
}
void play(char s[])
{
 char op;
 while (*s && !error)
 {
  if (*s>='0' && *s<='9')
  {
   num *= 10; num += *s - '0';
   prenum = true;
   preop = false;
  }
  else
  {
   if (prenum && *s!='(')
   {
    istack.push(flag*num);
    flag = 1; // 重新赋值为正号
    num = 0;
    if (!cstack.empty())
    {
     GetOp(op);
     // 先做乘除运算
     if (op == '*') Mul();
     else if (op == '/') Div();
     else cstack.push(op); // 其他符号放回去暂不处理
    }
   }
   if (*s == '(') // 特殊处理,为了处理类似“-(9+3)=”,“-(-5)=”之类的表达式
   {
    fstack.push(flag); // 保存括号前的符号
    flag = 1;
    num = 0;
   }
   if (*s=='-' && preop) // 表示当前是负号而不是减号
   {
    flag = -flag;
   }
   else
   {
    if (*s == ')') // 先将括号内的部分全部计算完成
    {
     while (!cstack.empty())
     {
      GetOp(op);
      if (op == '*') Mul();
      else if (op == '/') Div();
      else if (op == '+') Add();
      else if (op == '-') Sub();
      else if (op == '(') break;
     }
     if (op != '(') // 括号不匹配
     {
      error = false;
      return;
     }
     if (!istack.empty())
     {
      int top = istack.top(); istack.pop();
      if (fstack.empty()) // 括号不匹配使可能出现,不过程序那时走不到这句
      {
       error = true;
       return;
      }
      int ft = fstack.top(); fstack.pop();
      istack.push(top*ft); // 与括号前的符号一起计算括号内的值
     }
     while (!cstack.empty()) // 把括号前面与括号相连的乘除一并计算
     {
      GetOp(op);
      if (op == '*') Mul();
      else if (op == '/') Div();
      else 
      {
       cstack.push(op);
       break;
      }
     }
    }
    else cstack.push(*s); // 除‘)’外的操作符全部进栈
   }
   prenum = false; // 当前符号不是操作数
   preop = true; // 当前符号是操作符
  }
  s++;
 }
 // ‘=’出栈
 if (!cstack.empty() && cstack.top()=='=') cstack.pop();
 while (!error && !cstack.empty())
 {
  GetOp(op);
  if (op == '*') Mul();
  else if (op == '/') Div();
  else if (op == '+') Add();
  else if (op == '-') Sub();
  else error = false; // 若表达式存在错误操作符
 }
 if (istack.size() != 1) error = true; // 非正常计算
}
int main()
{
 char exp[maxn];
 while (gets(exp))
 {
  Init();
  play(exp);
  if (!error) printf("%d\n",istack.top());
  else printf("illegal operation\n");
 }
 return 0;
}
百分购

发表评论

您必须才能发表评论!