实验三:用栈ADT应用:对称符号匹配判断

3 篇文章 0 订阅

用栈ADT应用:对称符号匹配判断

输入一行符号,以#结束,判断其中的对称符号是否匹配。对称符号包括:

{ } 、 [ ] 、 ( )、 < >

输出分为以下几种情况:

(1)对称符号都匹配,输出 “ right. “

(2) 如果处理到最后出现了失配,则输出两行:

        第一行:Matching failure.

        第二行:loss of right character $$....       
        其中$$... 是按嵌套顺序对应的右匹配符号。

(3)处理到某个符号时失配了,则输出两行或三行:

        第一行: The N character '$' is wrong." ,
        其中N是出错符号的序号,$是出错的符号;

        第二行:  loss of left character $.”      
        其中 $ 是当前符号的左匹配符号。   

        第三行:(如果有的话)loss of right character $$...”   
        其中$$... 是按嵌套顺序对应的右匹配符号。

测试用例

用例一:

输入
as(*x<{(({<>}))}>)#
输出:
right.

用例二:

输入:
(a.b)>#
输出:
The 6 character ‘>’ is wrong.
loss of left character <.

因为隐藏用力比较多,博主也寻找了很多隐藏用例,因此这里给出两个博主自己摸索的用例。这也用例也都满足,ac的概率更高一点

自创用例一:

输入:
{<{>}>}#
输出:
The 4 character ‘>’ is wrong.
loss of left character <.
loss of right character }>}.

自创用例二:

输入:
{{{}#
输出:
Matching failure.
loss of right character }}.

其实我这里自己写的也比较乱,做了一下午脑袋嗡嗡的。有几个要注意的坑:

1.对“栈”的理解;
之前看过一个博主写的非常好,我的印象很深刻。他说,栈就像一个口袋,先放进去的在最底下,只能最后取出来。最后放进去的在最顶上,能最先取出来。
我的栈定义写了
变量:

存放栈元素的数组 ElemType *elements;
栈顶指示器top,并赋初值为-1(运行程序的时候因为没赋初值报错了)
栈的最大容量maxsize

方法

栈的溢出处理void overflowProcess();
进栈 void Push(ElemType x);
出栈 bool Pop (ElemType x);
判断栈是否为空 bool IsEmpty()const;
判断栈是否栈满 bool IsFull();
取栈顶内容 bool GetTop(ElemType &x);
得到栈的容量 int GetSize()const;
栈置空void MakeEmpty();

其中本题只用到了进栈,出栈、判断栈是否为空,栈制空(析构函数中)
2.本题难点
这个题我觉得最难的地方是考虑多种失配情况。
这个题的中心思路是:
将输入的字符串进行比对,压进栈中→分析多种情况得到输出
(可能是我的算法太差了,我输出这里真是一言难尽,搞了好久)

(1)压栈时,左侧符号-({<[-直接进栈,当检测到右侧符号时(下面称其为当前符号),开始与比较。

  • 当栈为空栈时,说明从第一个字符就开始错了,输出第一行

第一行: The N character ‘$’ is wrong." ,

然后将这个字符保存下来(我再程序中定义了一个全局变量),到后面比对输出。此时,后面的字符就不需要再遍历了,直接break;

  • 当栈不是空栈时,比较栈顶和当前字符:
    栈顶和当前符号适配时,让栈顶的符号出栈(Pop);
    栈顶和当前符号不适配时,说明从这个字符开始错了,输出第一行

第一行: The N character ‘$’ is wrong." ,

同样的,将这个字符保存下来,然后break出循环;

这里需要注意,栈为空的不适配和栈不为空的不适配是不一样的,关系到输出时三行还是两行。所以要分别标记。
栈为空时的不适配,说明多余了右侧符号,此时只需要两行(输出所缺失的左侧符号,就像测试用例二)
栈不为空时不适配,说明右侧符号没法和栈内已有的左侧符号适配,此时需要输出三行(既要输出所确实的左侧符号,又要输出当前存在栈内的的符号的右侧符号,就像自创用例一)

(2)比对输出
首先分为两种情况,栈为空和栈不为空;

  • 栈为空
    (1)如果不存在失配现象(我的做法是设一个全局flag=0,然后一旦出现失配现象都让flag=1),说明可以完全适配,可以输出right;
    (2)如果存在失配现象
    说明多余了右侧符号,此时只需要两行(输出所缺失的左侧符号,就像测试用例二)
  • 栈不为空
    (1)若无失配现象,说明是处理到了最后,符号不够和前边的匹配了。
    此时输出:

第一行:Matching failure.
第二行:loss of right character $$…

其中第二行的“$$”就是把还在栈里的左侧符号的适配右侧符号输出(例如自创用例二)
(2)若有失配现象
那么既要输出这个适配符号的左侧符号,又要把还在栈里的左侧符号的适配右侧符号输出(自创用例一)

#include <iostream>
#include <assert.h>
#include <string>
using namespace std;
int countit=0;
char cun;
int judge=0;     //栈内错误

int right1=0;    //外部错误
char you;
typedef char ElemType;
class SeqStack
{
    //顺序栈类定义
public:
    ElemType *elements;        //数组存放栈元素
    int top=-1;                   //栈顶指示器
    int maxSize;               //栈最大容量
    void overflowProcess();    //栈的溢出处理

    SeqStack() {}
    SeqStack(int sz);         //构造函数
    ~SeqStack()
    {
        delete []elements;
    }
    void Push(ElemType x);       //进栈
    bool Pop(ElemType x);         //出栈
    bool GetTop(ElemType &x);       //取栈顶内容
    bool IsEmpty()const
    {
        return top==-1;
    }
    bool IsFull()const
    {
        return top==maxSize-1;
    }
    int GetSize()const
    {
        return top+1;
    }
    void MakeEmpty()
    {
        top=-1;
    }
    //friend ostream&operator<<(ostream &os,SeqStack &S);       //重载运算符<<
};
SeqStack::SeqStack(int sz)          //构造函数
{
    elements=new ElemType[sz];      //申请连续空间
    assert(elements!=NULL);          //头文件,#include <assert.h>,宏断言,如果括号内语句是假就结束程序
    top=-1;                         //栈顶指示器指向栈底
    maxSize=sz;                     //栈的最大空间
}
void SeqStack::overflowProcess()
{
    //私有函数,当栈满则执行扩充栈存储空间处理
    ElemType *newArray=new ElemType[2*maxSize];   //创建更大的存储数组
    for(int i=0; i<=top; i++)
    {
        newArray[i]=elements[i];
    }
    maxSize+=maxSize;        //栈空间扩大
    delete []elements;       //释放原来的连续空间
    elements=newArray;        //改变elements指针
}
void SeqStack::Push(ElemType x)
{
    //若栈满,则溢出处理,将元素X插入该栈栈顶
    if(IsFull()==true)
        overflowProcess();       //栈满
    top++;
    elements[top]=x;            //栈顶指针先+1.再元素进栈
}
bool SeqStack::Pop(ElemType x)
{
    //若栈不空,函数退出栈顶元素并将栈顶元素赋值给X
    //返回true,否则返回false
    if(IsEmpty()==true)
        return false;
    x=elements[top--];          //先去元素,栈顶指针退1
    return true;                //退栈成功
}
int main()
{
    string str;
    cin>>str;
    SeqStack s(1000);
    int i=0;
    while(str[i]!='#')
    {
        if(str[i]=='(')
        {
            s.Push('(');

        }
        if(str[i]=='[')
        {
            s.Push('[');

        }
        if(str[i]=='<')
        {
            s.Push('<');

        }
        if(str[i]=='{')
        {
            s.Push('{');
        }
        if(str[i]==')')
        {
            if(s.IsEmpty()!=true)                  //如果栈非空
            {
                if(s.elements[s.top]=='(')         //如果栈顶适配,则让栈顶出栈
                {
                    s.Pop('(');
                }
                else                               //如果栈顶不适配,那么就有错,记下来这个符号然后break;
                {
                    cout<<"The "<<i+1<<" character '"<<str[i]<<"' is wrong."<<endl;
                    cun=str[i];
                    countit++;
                    judge=1;
                    break;
                }
            }
            else                                  //如果栈是空的,那么就错了
            {
                cout<<"The "<<i+1<<" character '"<<str[i]<<"' is wrong."<<endl;
                you=str[i];
                right1++;
                judge=1;
                break;

            }
        }
        if(str[i]==']')
        {
            if(!s.IsEmpty())                       //如果栈非空
            {
                if(s.elements[s.top]=='[')           //如果栈顶适配
                {
                    s.Pop('[');
                }
                else
                {
                    cout<<"The "<<i+1<<" character '"<<str[i]<<"' is wrong."<<endl;
                    cun=str[i];
                    countit++;
                    judge=1;
                    break;
                }
            }
            else                    //如果栈是空的
            {
                cout<<"The "<<i+1<<" character '"<<str[i]<<"' is wrong."<<endl;
                you=str[i];
                right1++;
                judge=1;
                break;
            }
        }
        if(str[i]=='>')
        {
            if(!s.IsEmpty())           //如果栈非空
            {
                if(s.elements[s.top]=='<')
                {
                    s.Pop('<');
                }
                else
                {
                    cout<<"The "<<i+1<<" character '"<<str[i]<<"' is wrong."<<endl;
                    cun=str[i];
                    countit++;
                    judge=1;
                    break;
                }
            }
            else                    //如果栈是空的
            {
                cout<<"The "<<i+1<<" character '"<<str[i]<<"' is wrong."<<endl;
                you=str[i];
                right1++;
                judge=1;
                break;
            }
        }
        if(str[i]=='}')
        {
            if(!s.IsEmpty())           //如果栈非空
            {
                if(s.elements[s.top]=='{')
                {
                    s.Pop('{');
                }
                else
                {
                    //收栈内的错误
                    cout<<"The "<<i+1<<" character '"<<str[i]<<"' is wrong."<<endl;
                    cun=str[i];
                    countit++;
                    judge=1;
                    break;
                }
            }
            else                    //如果栈是空的
            {
                cout<<"The "<<i+1<<" character '"<<str[i]<<"' is wrong."<<endl;
                you=str[i];
                right1++;
                judge=1;
                break;

            }
        }
        i++;
    }


    if(s.IsEmpty()==true)               //空栈时
    {
        if(right1==0 && judge==0)        //不存在失配现象,那么就是right
        {
            cout<<"right."<<endl;
        }
        else if(right1!=0)               //其他情况都是不适配。
                                         //输出缺失的左侧运算符
        {
            cout<<"loss of left character ";

                if(you=='>')
                {
                    cout<<"<";
                }
                if(you==')')
                {
                    cout<<"(";
                }
                if(you=='}')
                {
                    cout<<"{";
                }
                if(you==']')
                {
                    cout<<"[";
                }

            cout<<"."<<endl;
        }
    }
   else                                    //没空栈时
    {
        if(countit==0 )                    //看有没有匹配完
        {
            cout<<"Matching failure."<<endl;
        }
        else if(countit!=0)
        {
            cout<<"loss of left character ";
                if(cun=='>')
                {
                    cout<<"<";
                }
                if(cun==')')
                {
                    cout<<"(";
                }
                if(cun=='}')
                {
                    cout<<"{";
                }
                if(cun==']')
                {
                    cout<<"[";
                }

            cout<<"."<<endl;
        }
        cout<<"loss of right character ";
        while(s.IsEmpty()!=true)
        {
            if(s.elements[s.top]=='{')
            {
                cout<<"}";
                s.Pop('{');
            }
            if(s.elements[s.top]=='(')
            {
                cout<<")";
                s.Pop('(');
            }
            if(s.elements[s.top]=='[')
            {

                cout<<"]";
                s.Pop('[');
            }
            if(s.elements[s.top]=='<')
            {
                cout<<">";
                s.Pop('<');
            }

        }
        cout<<"."<<endl;

    }
    return 0;
}


代码写的有点乱,思路也比较乱,如果发现错误欢迎批评指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值