PTA 7-4 符号配对

请编写程序检查C语言源程序中下列符号是否配对:/**/()[]{}

输入格式:

输入为一个C语言源程序。当读到某一行中只有一个句点.和一个回车的时候,标志着输入结束。程序中需要检查配对的符号不超过100个。

输出格式:

首先,如果所有符号配对正确,则在第一行中输出YES,否则输出NO。然后在第二行中指出第一个不配对的符号:如果缺少左符号,则输出?-右符号;如果缺少右符号,则输出左符号-?

输入样例1:

void test()
{
    int i, A[10];
    for (i=0; i<10; i++) { /*/
        A[i] = i;
}
.

输出样例1:

NO
/*-?

输入样例2:

void test()
{
    int i, A[10];
    for (i=0; i<10; i++) /**/
        A[i] = i;
}]
.

输出样例2:

NO
?-]

输入样例3:

void test()
{
    int i
    double A[10];
    for (i=0; i<10; i++) /**/
        A[i] = 0.1*i;
}
.

输出样例3:

YES

 代码+总结:

        换种方式来写吧

        首先这种括号配对问题肯定先想到栈。这里为了方便,我把 ([{ /* 统称为左括号,另一边统称为右括号。

        输入的是一个以 单行. 为结尾的c语言代码,而我们要的只是符号,所以能想到我们先用循环把代码逐部分读入,当读到以 . 为首元素的部分时退出循环。

        再这个大循环内我们还要对读入的部分再做循环,来找到我们需要的括号类字符处理。其中比较特殊的时 /* */ 两个,我们再读取的时候对这两个字符做特殊处理,用 值 1,2分别代表这两个字符,再把读取到的有效字符进行处理,这里我把读取到的字符用函数judge()处理:

char str[1000]; scanf("%s", str);  // 先输入下字符数组
    while (str[0] != '.')
    {
        for (int i = 0; str[i]; i++)
        {
            // 下面一堆if其实就是查找是不是括号啥的
            if (str[i] == '/' && str[i+1] == '*')  {i ++;  flag = judge(1);}
            else if (str[i] == '*' && str[i+1] == '/')  {i ++; flag = judge(2);}
            else if (str[i] == '(' || str[i] == ')') flag = judge(str[i]);
            else if (str[i] == '[' || str[i] == ']') flag = judge(str[i]);
            else if (str[i] == '{' || str[i] == '}') flag = judge(str[i]);
            if (flag) return 0;  // 如果上面的judge返回1就直接return
        }
        memset(str, 0, sizeof(str));  // 重置一下暂存的字符数组
        scanf("%s", str);  // 输入新的字符数组
    }

       

        可以看到我还用flag来接收了judge()的返回值,先留着不说,我们来分析judge()要干的活都有啥。

        judge()负责处理输入的括号字符,可以说是这段代码的核心函数。那么怎么样才算是不能匹配呢?

接下来介绍一下分辨条件:

        如果栈是空的,且读入的是右括号--不匹配,直接输出NO+七七八八的

        如果栈非空:

                读取到左括号,直接入栈

                读取到右括号:

                        1.如果与栈顶匹配,栈顶退栈。

                        2.如果不匹配--不匹配,直接输出NO+七七八八的。

        最后读取代码结束后,如果栈内非空,说明有左括号没得匹配,直接输出NO+七七八八的。

        知道了条件,写judge()就轻松多了,但是想要输出 NO+七七八八的 之后就让程序停止运行,就得有个东西通知主函数我已经输出过 NO+七七八八的 的了,这就是用flag来接收judge()返回值的作用。

int judge(char ch)
{
    // 如果栈还是空的
    if (top == 0 )
    {
        to_str(ch);
        // 如果读取到的是右侧字符,那么肯定不匹配,直接输出no
        if (ch == 2 || ch == ')' || ch == ']' || ch == '}') {printf("NO\n?-%s", note); return 1;}
        stack[top++] = ch;
    }
    else  // 栈非空
    {
        to_str(stack[top - 1]);
        if (ch == 1 || ch == '(' || ch == '[' || ch == '{') stack[top++] = ch;  // 左括号直接入栈
        else  // 右括号判断
        {
            if (ch - stack[top-1] == 1 || ch - stack[top-1] == 2) top--; // 能配对的话退栈
            else {printf("NO\n%s-?", note); return 1;}  // 不能配对的话结束
        }
    }
    return 0;
}

        可以看到我在这里面又弄了个 to_str(),由于之前图方便把 /* */ 作了特殊处理,因此在输出的时候就要把 1、2 翻译成 /* 、*/。

void to_str(char ch)
{
    memset(note, 0, sizeof(note));
    if (ch == 1)   {note[0] = '/';  note[1] = '*';}
    else if (ch == 2) {note[0] = '*';  note[1] = '/';}
    else note[0] = ch;
}

       

        到这代码就差不多结束了,再在主函数循环后添加一个判断栈是否非空的语句就ok了,不过需要注意一下,如果非空的话我们要输出栈底的元素(题目要求第一个不匹配的)

// 结束循环后如果栈内还有东西的话,那么括号肯定不匹配
    if (top != 0)
    {
        to_str(stack[0]);  // stack[0] 栈底
        printf("NO\n%s-?", note);
        return 0;
    }
    printf("YES");

        

        接下来给出完整代码

#include<stdio.h>
#include<string.h>
char stack[200], note[3];
int top = 0;
void to_str(char ch)  // 因为把 /* */ 当作一个字符处理了,所以在这里要还原一下
{
    memset(note, 0, sizeof(note));
    if (ch == 1)   {note[0] = '/';  note[1] = '*';}
    else if (ch == 2) {note[0] = '*';  note[1] = '/';}
    else note[0] = ch;
}

int judge(char ch)
{
    // 如果栈还是空的
    if (top == 0 )
    {
        to_str(ch);
        // 如果读取到的是右侧字符,那么肯定不匹配,直接输出no
        if (ch == 2 || ch == ')' || ch == ']' || ch == '}') {printf("NO\n?-%s", note); return 1;}
        stack[top++] = ch;
    }
    else  // 栈非空
    {
        to_str(stack[top - 1]);
        if (ch == 1 || ch == '(' || ch == '[' || ch == '{') stack[top++] = ch;  // 左括号直接入栈
        else  // 右括号判断
        {
            if (ch - stack[top-1] == 1 || ch - stack[top-1] == 2) top--; // 能配对的话退栈
            else {printf("NO\n%s-?", note); return 1;}  // 不能配对的话结束
        }
    }
    return 0;
}

int main()
{
    int flag = 0;
    char str[1000]; scanf("%s", str);  // 先输入下字符数组
    while (str[0] != '.')
    {
        for (int i = 0; str[i]; i++)
        {
            // 下面一堆if其实就是查找是不是括号啥的
            if (str[i] == '/' && str[i+1] == '*')  {i ++;  flag = judge(1);}
            else if (str[i] == '*' && str[i+1] == '/')  {i ++; flag = judge(2);}
            else if (str[i] == '(' || str[i] == ')') flag = judge(str[i]);
            else if (str[i] == '[' || str[i] == ']') flag = judge(str[i]);
            else if (str[i] == '{' || str[i] == '}') flag = judge(str[i]);
            if (flag) return 0;  // 如果上面的judge返回1就直接return
        }
        memset(str, 0, sizeof(str));  // 重置一下暂存的字符数组
        scanf("%s", str);  // 输入新的字符数组
    }
    // 结束循环后如果栈内还有东西的话,那么括号肯定不匹配
    if (top != 0)
    {
        to_str(stack[0]);
        printf("NO\n%s-?", note);
        return 0;
    }
    printf("YES");
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值