PTA:表达式转换 (25 分)

题目详情:

算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。

输入格式:

输入在一行中给出不含空格的中缀表达式,可包含+-*\以及左右括号(),表达式不超过20个字符。

输出格式:

在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。

输入样例:

2+3*(7-4)+8/4

结尾无空行

输出样例:

2 3 7 4 - * + 8 4 / +

结尾无空行

作者:DS课程组;单位:浙江大学

代码长度限制:16 KB;时间限制:400 ms;内存限制:64 MB

———————————————————————————————————————————

这个题还比较《友好》,输入以字符串的形式给出。根据教材上的算法就“很好过了”。再列举一下加深印象:

1.运算数直接输出

2.左括号:压如栈中

3.右括号:从栈内输出运算符,知道左括号为止。(左括号也要弹出去)

4.运算符:优先级大于栈顶或为空,压入栈中。小于等于栈顶,弹出栈顶并输出,再比较。

5.输出栈中余留的符号。

按照上面的思路,很快就写出了代码。但是一个测试点都过不了。

中途我改了亿次代码,大部分都是过不了,或者只通过一个,我就不放出来丢人了。总结一下这道题有哪些坑点:

1.这道题的输出要求很特殊,每个单位空格隔开,但最后一个友不能有空格,大大的增加了输出难度。

在这里自己写一个打印函数:

void print(char ch)

{

      len++;   //全局变量,记录打印长度

      if(len==n) cout<<ch;  //长度与原来长度相同代表最后一个

      else cout<<ch<<" ";

}

2.len的长度非常重要,特别是不输出时也要注意增加。

3. 对于一位的整数,我们可以一个一个的读,按照上面的函数输出。但是这道题的数有双位数甚至多位数,对于数字不能一个一个输出。对于数字的情况必须要整个输出,并且保证len的长度增加。

4.数字还会有小数的情况,不要忘了判断小数点。

5.最强AC拦路虎:”(“前面和算式最前面,遇到负数的话,要作为整体一起输出。

Code:

#include<iostream>

#include<ctype.h>

#include<string>

#include<stack>

using namespace std;

int len=0,n;

void trans(char &ch)  //转换函数,为了比较优先级,赋予不同的值

{

      if(ch=='+'||ch=='-') ch=1;

      else if(ch=='*'||ch=='/') ch=2;

      else ch=0;  //括号降为最低级,应为左括号必须遇到右括号才输出

}

int cmp(char a,char b)

{

      trans(a);

      trans(b);

      if(a>b) return 1;

      if(a==b) return 0;

      if(a<b) return -1;

}

void print(char ch)

{

      len++;

      if(len==n) cout<<ch;

      else cout<<ch<<" ";

}

int main()

{

      string s;

      getline(cin,s);

      n=s.size();

      stack<char>opra;

      for(int i=0;i<n;i++){

            while(isdigit(s[i])||s[i]=='.'){

                  if(i+1<n&&(isdigit(s[i+1])||s[i+1]=='.')){

                         cout<<s[i];

                         ++len;

                   } //长串数字不能用print输出

                   else print(s[i]);

                   ++i;

                   if(i>=n) break;

            }

            if(i>=n) break;

            if(s[i]=='(') opra.push(s[i]);

            else if(s[i]==')'){

                   while(opra.top()!='('){

                         print(opra.top());

                         opra.pop();

                   }

                   opra.pop();

                   len+=2; //左右两个括号并没有输出,但是它存在于原字符,必须要将len+2

            }

            else{

                   if(i==0||(i>0&&s[i-1]=='(')){

                         if(s[i]=='-')  cout<<s[i];

                         len++;

                         continue;

                   }//单独处理坑点5

            while(!opra.empty()&&cmp(s[i],opra.top())<=0){

                         print(opra.top());

                         opra.pop();

                   }

                   opra.push(s[i]);

            }

      }

      while(!opra.empty()){

            print(opra.top());

            opra.pop();

      }

      return 0;

}

运行结果:

看似很简单,其实很多坑。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值