You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求解K&R习题1-24:括号匹配类语法错误检测难题

解决K&R习题1-24:C程序语法错误检查(括号匹配核心)

核心思路:用栈处理嵌套匹配

括号、方括号、大括号的嵌套匹配本质是后进先出逻辑,栈刚好能完美解决:

  • 遇到左括号((、[、{),直接压入栈
  • 遇到右括号()、]、}),检查栈顶是否是对应的左括号:
    • 匹配则弹出栈顶
    • 不匹配或栈为空,直接标记错误
  • 遍历完程序后,栈不为空说明存在未闭合的左括号,同样是错误

必须处理的特殊场景

1. 引号内的括号忽略

单引号'或双引号"里的括号只是普通字符,不算语法符号:

  • 遇到引号时切换到「引号模式」,直到遇到对应的结束引号(注意跳过转义引号\"或\',不能当作结束标记)

2. 注释内的括号忽略

  • 遇到/*进入「块注释模式」,直到*/才退出
  • 遇到//进入「行注释模式」,直到换行才退出

3. 转义序列处理

引号内的转义字符(如\"、\'、\\)要正确识别,避免把转义后的引号当成结束符号

针对嵌套顺序错误的案例分析

比如({ ) }:

  • 先压入(,再压入{
  • 遇到)时,栈顶是{,和)不匹配,直接判定错误

再比如((({(({}}))))):

  • 压入一系列左括号后,遇到第一个},栈顶是{,匹配弹出;接着遇到第二个},此时栈顶是(,不匹配,判定错误

代码实现框架(C语言)

#include <stdio.h>
#include <stdlib.h>

#define MAX_STACK_SIZE 100

char stack[MAX_STACK_SIZE];
int top = -1;

// 压栈操作
void push(char c) {
    if (top >= MAX_STACK_SIZE - 1) {
        printf("栈溢出:程序嵌套层级过深\n");
        exit(1);
    }
    stack[++top] = c;
}

// 弹栈操作
char pop() {
    if (top < 0) {
        return '\0'; // 返回空字符表示栈空
    }
    return stack[top--];
}

// 检查左右括号是否匹配
int is_match(char left, char right) {
    return (left == '(' && right == ')') ||
           (left == '[' && right == ']') ||
           (left == '{' && right == '}');
}

int main() {
    int c;
    int in_quote = 0;       // 0: 不在引号内, 1: 单引号模式, 2: 双引号模式
    int in_comment = 0;     // 0: 不在注释内, 1: 块注释模式, 2: 行注释模式
    int line_num = 1;

    while ((c = getchar()) != EOF) {
        // 处理行注释:直到换行退出
        if (in_comment == 2) {
            if (c == '\n') {
                in_comment = 0;
                line_num++;
            }
            continue;
        }

        // 处理块注释:直到遇到*/退出
        if (in_comment == 1) {
            if (c == '*') {
                int next_c = getchar();
                if (next_c == '/') {
                    in_comment = 0;
                } else if (next_c != EOF) {
                    ungetc(next_c, stdin); // 把非/的字符放回输入流
                }
            }
            continue;
        }

        // 处理引号内的内容
        if (in_quote) {
            if (c == '\\') { // 跳过转义字符
                getchar();
                continue;
            }
            if ((in_quote == 1 && c == '\'') || (in_quote == 2 && c == '\"')) {
                in_quote = 0;
            }
            continue;
        } else {
            if (c == '\'') {
                in_quote = 1;
            } else if (c == '\"') {
                in_quote = 2;
            }
        }

        // 检测注释起始
        if (c == '/') {
            int next_c = getchar();
            if (next_c == '*') {
                in_comment = 1;
            } else if (next_c == '/') {
                in_comment = 2;
            } else if (next_c != EOF) {
                ungetc(next_c, stdin); // 把非注释的/后续字符放回
                push(c); // 这里的/是普通字符,若需要可以根据需求调整
            }
            continue;
        }

        // 处理左括号
        if (c == '(' || c == '[' || c == '{') {
            push(c);
        }
        // 处理右括号
        else if (c == ')' || c == ']' || c == '}') {
            char left = pop();
            if (!is_match(left, c)) {
                printf("第%d行:括号不匹配,遇到%c,期望匹配的是%c\n", 
                       line_num, c, left ? left : "无对应左括号");
            }
        }

        // 统计行数
        if (c == '\n') {
            line_num++;
        }
    }

    // 检查剩余未闭合的左括号
    while (top >= 0) {
        char left = pop();
        printf("文件结束:存在未闭合的左括号%c\n", left);
    }

    return 0;
}

注意事项

  • 栈的大小可根据实际需求调整,避免嵌套过深导致溢出
  • 转义字符的处理要严谨,确保不会误判引号结束
  • 标准C不允许嵌套块注释,所以代码未处理该场景,若需支持可额外扩展逻辑
  • 可添加更详细的错误定位信息,比如列号,提升调试效率

内容的提问来源于stack exchange,提问作者hansoko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 01:46:26