#define is unsafe

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 10   Accepted Submission(s) : 8
Problem Description
Have you used #define in C/C++ code like the code below?

#include <stdio.h>
#define MAX(a , b) ((a) > (b) ? (a) : (b))
int main()
{
  printf("%d\n" , MAX(2 + 3 , 4));
  return 0;
}

Run the code and get an output: 5, right?
You may think it is equal to this code:

#include <stdio.h>
int max(a , b) {  return ((a) > (b) ? (a) : (b));  }
int main()
{
  printf("%d\n" , max(2 + 3 , 4));
  return 0;
}

But they aren't.Though they do produce the same anwser , they work in two different ways.
The first code, just replace the MAX(2 + 3 , 4) with ((2 + 3) > (4) ? (2 + 3) : 4), which calculates (2 + 3) twice.
While the second calculates (2 + 3) first, and send the value (5 , 4) to function max(a , b) , which calculates (2 + 3) only once.

What about MAX( MAX(1+2,2) , 3 ) ? 
Remember "replace".
First replace: MAX( (1 + 2) > 2 ? (1 + 2) : 2 , 3)
Second replace: ( ( ( 1 + 2 ) > 2 ? ( 1 + 2 ) : 2 ) > 3 ? ( ( 1 + 2 ) > 2 ? ( 1 + 2 ) : 2 ) : 3).
The code may calculate the same expression many times like ( 1 + 2 ) above.
So #define isn't good.In this problem,I'll give you some strings, tell me the result and how many additions(加法) are computed.
 
Input
The first line is an integer T(T<=40) indicating case number. The next T lines each has a string(no longer than 1000), with MAX(a,b), digits, '+' only(Yes, there're no other characters). In MAX(a,b), a and b may be a string with MAX(c,d), digits, '+'.See the sample and things will be clearer.

Output
For each case, output two integers in a line separated by a single space.Integers in output won't exceed 1000000.
 
Sample Input
  
  
6 MAX(1,0) 1+MAX(1,0) MAX(2+1,3) MAX(4,2+2) MAX(1+1,2)+MAX(2,3) MAX(MAX(1+2,3),MAX(4+5+6,MAX(7+8,9)))+MAX(10,MAX(MAX(11,12),13))

Sample Output
  
  
1 0 2 1 3 1 4 2 5 2 28 14
 
            这是一道表达式求值问题,模拟题。题目意思就是MAX计算加法的次数其实是比较时进行了一次,返回时又进行了一次。例如:MAX(3+2,4)其实是进行了两次加法。 
    解题思路:
    表达式求值要用到数据结构中的中缀转后缀计算表达式。这就要借助栈来将中缀转为后缀表达式。然后在计算加法的次数即可。本题的关键就在于表达式的中缀转后缀。


代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stack>
#include <cstring>
#include <sstream>
using namespace std;
string S1,S2;///S1为中缀表达式,S2为中缀转化为后缀的表达式
struct Num
{
    int numb;
    int time;
};
int change(double d)///计算各位数字之和
{
    int sum=0;
    ostringstream o;
    string c;
    if(o<<d)
        c=o.str();
    for(int i=0;i<c.size();i++)
    {
        if(c[i]>='0'&&c[i]<='9')
            sum+=c[i]-'0';
    }
    return sum;
}
/**
代码的核心就是定义各个运算符的优先级,通过优先级来将其中缀表达式转化为后缀表达式,进行运算。
**/
int level(char a)///定义运算符的优先级
{
    int flag;
    switch(a)
    {
        case ',':flag=1;break;
        case 'S':flag=4;break;
        case 'M':flag=4;break;
        case '+':flag=2;break;
        case '-':flag=2;break;
        case '*':flag=3;break;
        case '/':flag=3;break;
        default :flag=0;
    }
    return flag;
}
void conversion()///中缀转后缀
{
    stack<char>Q;
    char a;
    a='#';
    Q.push(a);
    int i=0,m=S1.length();
    while(i<m)
    {
        a=Q.top();
        if(S1[i]=='(')
        {
            Q.push(S1[i]);i++;
        }
        else if(S1[i]==')')
        {
            while(a!='(')
            {
                S2=S2+a+'#';Q.pop();a=Q.top();
            }
            Q.pop();i++;
        }
        else if(S1[i]=='+'||S1[i]=='-'||S1[i]=='*'||S1[i]=='/'||S1[i]=='S'||S1[i]=='M'||S1[i]==',')
        {
            while(level(a)>=level(S1[i]))
            {
                S2=S2+a+'#';Q.pop();a=Q.top();
            }
            if(S1[i]=='S')
            {
                Q.push(S1[i]);i+=4;
            }
            else if(S1[i]=='M')
            {
                Q.push(S1[i]);i+=3;
            }
            else if(S1[i]==',')
            {
                i++;
            }
            else
            {
                Q.push(S1[i]);i++;
            }

        }
        else
        {
            while((S1[i]>='0'&&S1[i]<='9')||S1[i]=='.')
            {
                S2=S2+S1[i];i++;
            }
            S2+='#';
        }
    }
    while(!Q.empty())
    {
        a=Q.top();
        Q.pop();
        if(a!='#')
        {
            S2=S2+a+'#';
        }
    }
   // cout<<S2<<endl;///查看中缀转后缀的结果
}
void calculate()///后缀进行值运算
{
    int m=S2.length();
    int i=0;
    Num a,b,N;
    stack<Num>W;
    int num=0,num1=1;
    while(i<m)
    {
        switch(S2[i])///计算以后将得到的结果入栈
        {
            case '+':
                {
                    a=W.top();W.pop();
                    b=W.top();W.pop();
                    a.numb=a.numb+b.numb;
                    a.time=a.time+b.time+1;
                    W.push(a);
                    i++;break;
                }
            case 'M':
                {
                    a=W.top();W.pop();
                    b=W.top();W.pop();
                    if(a.numb>=b.numb)
                    {

                        a.time=a.time*2+b.time;
                        W.push(a);
                        i++;break;
                    }
                    else
                    {
                        b.time=b.time*2+a.time;
                        W.push(b);
                        i++;break;
                    }
                }
            default:///对数字进行处理
            {
                if(S2[i]>='0'&&S2[i]<='9'&&num1==1)
                {
                    num=num*10+S2[i]-'0';
                    if((S2[i+1]<'0')||(S2[i+1]>'9'))
                    {
                        N.numb=num;
                        N.time=0;
                        W.push(N);
                    }
                }
                else
                {
                    num1=1;
                    num=0;
                }
                i++;
            }
        }
    }
    printf("%d %d\n",W.top().numb,W.top().time);///按题目要求定义输出格式
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        cin>>S1;
        S2="";
        conversion();
        calculate();
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值