Parentheses(字符串模拟)

题目描述
The correspondence among the operators and the operands can be clarified using parentheses. In a C program, for example, the expression a-b-c can be clarified as (a-b)-c since the minus operator is left associative.
The parentheses can be used to override the default precedences and associativities of operators. For instance, in the expression a-(b-c), the left associativity of the minus operator is overridden by the parentheses.
A novice C programmer Dennis has been stressed too much in remembering the operator precedences and associativities. Therefore, he made a new language namely ICPC (I can parenthesize C), in which the operator-operand correspondence should be clarified fully using parentheses; except for this, all the other features are same as C. For instance, one should write (a-b)-c instead of a-b-c and a+(bc) rather than a+bc.
However, the usage of the parentheses can be too much in some cases. For the expression a-b-c, it is enough to write
(a-b)-c
but one can write it as
(a-(b))-c
or as
((a-b)-c)
where the pairs of parentheses underlined are superfluous.
Dennis wants to convert the C expression into the ICPC expression, in which the pairs of parentheses should be used exactly as needed. You have to help Dennis. For simplicity, you can assume that the input C expression contains only five binary arithmetic operators (+, -, *, /, and %), left and right parentheses ( and ), and single-lowercase alphabet operands. Given such a C expression, write a program to determine whether it is an ICPC expression or not.
If the expression is not an error in ICPC, then it should not be an error in C. Once it is not an error in C, the usage of parentheses should be checked to determine whether it is a proper expression in ICPC or not. If the expression is not properly parenthesized, i.e., the number of parentheses is not exact as needed, then it is considered improper.
Beware that some of the input C expressions may be erroneous originally. For instance, a%/b is an error since it requires one more operand between % and / to be valid. As another example, a b + c is also an error since it requires one more operator between a and b.

输入
Your program is to read from standard input. The input consists of a single line containing a C expression. The expression is a string of single-lowercase alphabets, special symbols including left and right parentheses and five binary arithmetic operators (+, -, *, /, and %), and spaces. The input line contains at least one operand. The length of the input line (the number of characters in it) is no more than 1000 including the spaces and the single newline character at the end.

输出
Your program is to write to standard output. Print exactly one line. The line should contain one of the following words: error, proper, and improper. Print error if the input C expression is erroneous. Once it is not an error, print proper or improper depending on the parenthesized status of the expression: print proper if it is parenthesized properly with the exact number of parentheses needed for ICPC, and print improper otherwise.

样例输入
a + a

样例输出
proper

思路
字符串模拟,具体见注释

代码实现

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int N=1005;
char s[N];
int len,id[N];
bool judgef(char t)
{
    if(t == '+' ||t == '-' ||t == '*' || t == '/' ||t== '%') return true;
    else return false;
}
bool judge()
{
    len=strlen(s+1);
    for(int i=1;i<=len;i++)
    {
        if(isalpha(s[i])) id[i]=0;
        else if(judgef(s[i])) id[i]=1;
        else if(s[i]=='(') id[i]=2;
        else id[i]=3;
    } //根据每个字符的特性转换为数字
    if(id[1]==3 || id[len]==2) return false;  //当首字符为‘)’或尾字符为‘(’时,合法性检测不通过
    if(id[1]==1 || id[len]==1) return false;//当首字符或尾字符为符号时,合法性检测不通过
    if(len==1 && id[1]==0) return true; //当长度为1且为字符时,合法性检测通过
    for(int i=2,x,y;i<=len;i++)
    {
        x=id[i-1],y=id[i];
        if(x==0 && y==0) return false;
        if(x==1 && y==1) return false;
        if(x==1 && y==3) return false;
        if(x==2 && y==1) return false;
        if(x==2 && y==3) return false;
        if(x==3 && y==2) return false;
        if(x==3 && y==0) return false;
        if(x==0 && y==2) return false;
    } // 枚举可能使合法性检测不通过的情况
    int cnt=0;
    for(int i=1;i<=len;i++)
    {
        if(id[i]==2) cnt++;
        else if(id[i]==3)
        {
            if(cnt==0) return false;
            cnt--;
        }
    }
    return cnt==0; //确定左右括号匹配
}
bool ready()
{
    if(len==1) return true;
    int cnt=0,fh=0;
    for(int i=1;i<=len;i++) if(id[i]==1) fh++; //确定字符串中符号个数
    stack<int> sta;
    for(int i=1;i<=len;i++)
    {
        if(id[i]==0) continue;
        if(id[i]<=2) sta.push(id[i]); 
        else if(id[i]==3)
        {
            int sf=0;
            while(!sta.empty())
            {
                int t=sta.top();
                sta.pop();
                if(t==2) break;
                else if(t==1) sf++;
            }
            if(sf==1) cnt++; //确定每个括号内的符号对应情况
            else return false;
        }
    }
    return cnt==fh-1; //确定整个字符串内的符号对应情况

}
int main()
{
    gets(s+1);
    int l=0;
    len=strlen(s+1);
    for(int i=1;i<=len;i++) if(s[i]!=' ') s[++l]=s[i];
    s[++l]='\0'; // 将字符串中的空格去除
    if(!judge()) puts("error"); //进行合法性检测
    else
    {
        if(ready()) puts("proper"); //判断是否是符合规定的字符串
        else puts("improper");
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值