第三章作业2-栈及其应用 符号配对

该博客介绍了一个C语言程序,用于检查输入的C语言源代码中符号是否正确配对,如/*与*/、(与)、[与]、{与}

7-2 符号配对 (20分)

请编写程序检查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

作者
DS课程组
单位
浙江大学
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

Accepted Code

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <string>
#include <iostream>

using namespace std;

//函数状态码定义
#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE -1
#define OVERFLOW   -2

#define MaxSize 100

typedef int Position;
typedef char ElementType;

struct stack {
    char elem[MaxSize];
    int top;
};

typedef struct stack seqstack;

int push(seqstack *s,char c);

int pop(seqstack *s,char *x);

int gettop(seqstack *s,char *x);

void InitStack(seqstack *s);

int match(char c1,char c2);


void InitStack(seqstack *s) {
    s->top=-1;
}

int push(seqstack *s, char c) {
    if (s->top == MaxSize - 1)
        return 0;
    else {
        s->elem[++s->top] = c;
        return 1;
    }
}

int pop(seqstack *s,char *x) {
    if(s->top==-1)
        return 0;
    else{
        *x=s->elem[s->top--];//这里用的*x
        return 1;
    }
}

int gettop(seqstack *s, char *x) {
    if (s->top == -1)
        return 0;
    else {
        *x = s->elem[s->top];
        return 1;
    }
}

int main() {
    seqstack s;
    char ch;
    int i;
    InitStack(&s);
    char str[1000];
    while (scanf("%s", str) != NULL) {
        if (str[0] == '.' && str[1] == 0)//这里有个跳出循环
            break;
        for (i = 0; str[i] != '\0'; i++) {
            switch (str[i]) {
                case '(':
                case '{':
                case '[':
                    push(&s, str[i]);
                    break;
                case '/':
                    if (str[i + 1] == '*') {
                        push(&s, str[i]);
                        push(&s, str[i + 1]);
                    }
                    i += 1;
                    break;
                case ')':
                case '}':
                case ']':
                case '*':
                    if (s.top == -1) {
                        printf("NO\n");
                        switch (str[i]) {
                            case ')':
                                printf("?-)");
                                break;
                            case '}':
                                printf("?-}");
                                break;
                            case ']':
                                printf("?-]");
                                break;
                            case '*':
                                if (str[i] == '*' && str[i + 1] == '/')
                                    printf("?-*/");
                                break;
                        }
                        return 0;
                    } else {
                        gettop(&s, &ch);
                        if (match(ch, str[i])) {
                            pop(&s, &ch);
                        } else if (str[i] == '*')//  *  字符 做单独处理
                        {
                            if (ch == '*' && str[i + 1] == '/')// 是*/的符号
                            {
                                pop(&s, &ch);
                                pop(&s, &ch);
                                i++;
                            } else {
                                //只是单一的 * 号
                                continue;
                            }
                        } else {
                            printf("NO\n");
                            switch (ch) {
                                case '{':
                                    printf("{-?");
                                    break;
                                case '(':
                                    printf("(-?");
                                    break;
                                case '[':
                                    printf("[-?");
                                    break;
                                case '*':
                                    printf("/*-?");
                                    break;
                            }
                            return 0;
                        }
                    }
            }
        }
    }

    if (s.top == -1)
        printf("YES\n");
    else {
        printf("NO\n");
        switch (ch) {
            case '{':
                printf("{-?");
                break;
            case '(':
                printf("(-?");
                break;
            case '[':
                printf("[-?");
                break;
            case '*':
                printf("/*-?");
                break;
        }
        return 0;
    }

}

int match(char c1, char c2) {
    switch (c1) {
        case '(':
            if (c2 == ')')
                return 1;
            else
                return 0;
        case '[':
            if (c2 == ']')
                return 1;
            else
                return 0;
        case '{':
            if (c2 == '}')
                return 1;
            else
                return 0;
        default:
            return 0;
    }
}


仅供参考

### 符号匹配中的应用 #### 使用解决符号匹配问题的核心原理 当遇到左括号或其他起始符号时,将其压入中;当遇到右括号或终止符号时,则尝试从顶弹出对应的起始符号并进行比较。如果两者不匹配则表示存在错误[^1]。 对于任何合法的表达式而言,在遍历过程中: - 左侧开启字符应当始终先于右侧关闭字符出现; - 对应位置上的开闭字符需严格配对- 遍历结束后内不应残留未匹配项[^2]。 #### Python实现示例 下面是一个简单的Python程序来验证给定字符串内的各种类型的圆括号`()`、方括号`[]`以及花括号`{}`是否能够正确地相互匹配。 ```python def is_valid(s: str) -> bool: stack = [] mapping = {")": "(", "}": "{", "]": "["} for char in s: if char in mapping.values(): stack.append(char) elif char in mapping.keys(): top_element = stack.pop() if stack else '#' if mapping[char] != top_element: return False else: continue return not stack if __name__ == "__main__": test_cases = ["()", "()[]{}", "(]", "([)]", "{[]}"] for case in test_cases: print(f"{case}: {'Valid' if is_valid(case) else 'Invalid'}") ``` 此代码片段定义了一个名为 `is_valid` 的函数用于判断传入参数s所代表的一串由不同种类括号成的序列是否有效。通过维护一个列表作为模拟的空间,并利用字典记录各括号之间的对应关系以便快速查找对比。最终返回布尔值指示输入字符串里的所有括号能否完全匹配。 #### Rust实现案例 同样地,在Rust语言里也可以采用类似的思路去构建解决方案。这里给出一段基于向量(Vector)模仿行为来进行括号平衡检测的小例子: ```rust fn check_parentheses(input: &str) -> bool { let mut v: Vec<char> = vec![]; for c in input.chars() { match c { '(' | '[' | '{' => v.push(c), ')' => if v.pop().unwrap_or('0') != '(' {return false}, ']' => if v.pop().unwrap_or('0') != '[' {return false}, '}' => if v.pop().unwrap_or('0') != '{' {return false}, _ => (), } } v.is_empty() } ``` 这段Rust代码实现了相同的功能逻辑:每当遇见左侧符号即刻存入vector容器充当临时储存空间的角色;而一旦碰见右边界的标记就要立刻取出最近一次加入的那个元素做检验工作。整个过程一直持续到扫描完毕为止,最后再确认该容器里面是不是已经没有任何剩余物件了才算是完成了全部的任务。 #### C语言版本 而在C语言环境中,可以通过数加指针的方式简单模拟的操作完成同样的任务[^3]。 ```c #include <stdio.h> #include <stdbool.h> #define MAX_SIZE 100 bool isValid(const char *s){ int i=0,top=-1; char stack[MAX_SIZE]; while (s[i]!='\0'){ switch(s[i]){ case '(' : case '[' : case '{' : stack[++top]=s[i]; break; case ')': if(top==-1 || stack[top--]!='(' ) return false;break; case ']': if(top==-1 || stack[top--]!='[' ) return false;break; case '}': if(top==-1 || stack[top--]!='{' ) return false;break; default:break; } ++i; } return top==-1?true:false; } int main(){ const char* tests[]={"()","()[]{}","(]","([)]","{[]}"}; size_t n_tests=(sizeof(tests)/sizeof(*tests)); for(size_t j=0;j<n_tests;++j){ printf("%s:%s\n",tests[j],isValid(tests[j])?"valid":"invalid"); } return 0; } ``` 上述C语言源码展示了如何运用基本控制语句和条件分支结构配合一维字符型数共同作用下达成目标效果。其中值得注意的是边界情况处理部分,比如当试图访问越界索引或是期望获取不存在前驱节点的情形都需要特别小心对待以防止潜在运行期异常的发生。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值