C语言之表达式括号匹配

题目描述

假设一个表达式有英文字母(小写)、运算符(+-*/)和左右小(圆)括号构成,以 @ 作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则输出 YES;否则输出 NO。表达式长度小于 255,左圆括号少于 20 个。

输入格式

一行:表达式。

输出格式

一行:YESNO

cs 复制代码
输入
2*(x+y)/(1-x)@
输出
YES
输入
(25+x)*(a*(a+b+b)@
输出
NO
说明/提示
表达式长度小于 255,左圆括号少于 20 个。
cs 复制代码
#include<stdio.h>
#include<string.h>

int main()
{
    char ch;
    int balance = 0;  // 括号平衡计数器,记录当前未匹配的左括号数量
    //while循环判断在前面是否右括号多于左括号。在前面左括号可以多于右括号,因为后面可以补右括号。
   //最后可以通过计数器是否为0来判断后面是否补上了。而如果在前面右括号多,就补不回来了。
    while ((ch = getchar()) != '@') {
        if (ch == '(') {
            balance++;  // 遇到左括号,计数器加1
        } else if (ch == ')') {
            balance--;  // 遇到右括号,计数器减1
            if (balance < 0) {
                // 右括号出现在对应的左括号之前,不匹配
                printf("NO\n");
                return 0;
            }
        }
    }
    
    // 最后检查计数器是否为0
    if (balance == 0) {
        printf("YES\n");
    } else {
        printf("NO\n");
    }
    
    return 0;
}

我写代码主要有一个误区:我想的是一个在前面左括号必须要有一个右括号对应,完全忘记考虑可以在一个括号里套另一个括号,所以就导致我一直在考虑如何保证在第二个左括号前面有一个右括号,实际上,这是我无法写代码的,就一直进行不下去。

还有另一种方法,用栈数组:

cs 复制代码
#include<stdio.h>
#include<string.h>

int main()
{
    char input[255];
    char ch;
    int i = 0;//数组索引计数器
    
    // 读取输入直到遇到 @
    while ((ch = getchar()) != '@') {//这是用于字符串结束的固定方法,一定要记住
        input[i++] = ch;//先用后加,所以应该是input[0]=ch;i++;
    }
    input[i] = '\0'; // 在数组末尾添加字符串结束符
    
    int stack[255];  // 用数组模拟栈,存储左括号的位置
    int top = -1;    // 栈顶指针,-1表示空栈
    int valid = 1;   // 有效性标志,1表示有效,0表示无效
    
    for (i = 0; i < strlen(input); i++) {
        if (input[i] == '(') {
            // 遇到左括号,入栈
            stack[++top] = i;//先加后用,所以下标是从0开始的
        } else if (input[i] == ')') {
            // 遇到右括号
           //这其实和上面的代码一样的思路,都是通过一个标志变量的值看是否括号匹配
            if (top == -1) {//说明右括号在前面出现了两次,一个左括号对应两个右括号
                // 栈为空,说明右括号没有对应的左括号
                valid = 0;//标志变量用于输出后面的结果
                break;
            } else {
                // 弹出栈顶的左括号
                top--;
            }
        }
    }
    
    // 检查:所有括号都应该匹配,栈应该为空
    if (valid == 1 && top == -1) {
        printf("YES\n");
    } else {
        printf("NO\n");
    }
    
    return 0;
}
cs 复制代码
示例1:a(b)c
索引 | 字符 | 操作           | stack  | top | valid
-----|------|----------------|--------|-----|-------
0    | 'a'  | 忽略           | []     | -1  | 1
1    | '('  | 入栈 stack[0]=1| [1]    | 0   | 1
2    | 'b'  | 忽略           | [1]    | 0   | 1
3    | ')'  | 出栈 top--     | [1]    | -1  | 1
4    | 'c'  | 忽略           | [1]    | -1  | 1
结束:top = -1, valid = 1
示例2:a(b@
索引 | 字符 | 操作           | stack  | top | valid
-----|------|----------------|--------|-----|-------
0    | 'a'  | 忽略           | []     | -1  | 1
1    | '('  | 入栈 stack[0]=1| [1]    | 0   | 1
2    | 'b'  | 忽略           | [1]    | 0   | 1
结束:top = 0, valid = 1
示例3:a)b(c@
索引 | 字符 | 操作           | stack  | top | valid
-----|------|----------------|--------|-----|-------
0    | 'a'  | 忽略           | []     | -1  | 1
1    | ')'  | top==-1 → valid=0| []   | -1  | 0
立即退出循环

判断逻辑

  1. valid == 1:在处理过程中没有发现不匹配的情况

  2. top == -1:所有左括号都被匹配了(栈为空)

四种可能情况

  1. valid=1, top=-1 → YES(完全匹配)

  2. valid=1, top≠-1 → NO(左括号多余)

  3. valid=0, top=-1 → NO(右括号多余)

  4. valid=0, top≠-1 → NO(多种错误)

为什么要在输入所有字符后要在后面添加字符串结束符呢?

是因为计算字符串长度的时候,遇到字符串结束符才会停止。如果没有字符串结束符就会一直读取后面的随机值,长度会不停的增加,长度测量不精准。

需要明确的是:

复制代码
char str[] = "Hello";  // 实际存储:['H','e','l','l','o','\0']
概念 含义 示例值 包含 \0 吗?
数组大小 分配的内存空间 6个字节 ✅ 包含 \0
字符串长度 有效字符个数 5个字符 ❌ 不包含 \0
相关推荐
Daydream.V1 小时前
逻辑回归实例问题解决(LogisticRegression)
算法·机器学习·逻辑回归
不穿格子的程序员2 小时前
从零开始写算法——普通数组篇:缺失的第一个正数
算法·leetcode·哈希算法
Nebula_g2 小时前
线程进阶: 无人机自动防空平台开发教程(更新)
java·开发语言·数据结构·学习·算法·无人机
沐知全栈开发2 小时前
滑块(Slider)在网页设计中的应用与优化
开发语言
又见野草2 小时前
C++类和对象(下)
开发语言·c++
rit84324992 小时前
基于MATLAB的环境障碍模型构建与蚁群算法路径规划实现
开发语言·算法·matlab
hoiii1872 小时前
MATLAB SGM(半全局匹配)算法实现
前端·算法·matlab
lang201509282 小时前
Java JSR 250核心注解全解析
java·开发语言
Wpa.wk2 小时前
接口自动化测试 - 请求构造和响应断言 -Rest-assure
开发语言·python·测试工具·接口自动化