C语言实现括号匹配检测
1. 项目介绍
在编程中,括号匹配是一个常见的问题,尤其是在编译器、解释器、数学表达式解析等场景中尤为重要。括号匹配问题的本质是检查一个字符串中的括号是否成对出现,并且嵌套关系正确。例如,在数学表达式 ((a + b) * c)
中,所有的括号都是匹配的;但在 (a + b))
或 ((a + b)
这种情况下,则存在括号不匹配的问题。
本项目使用 C 语言实现一个括号匹配检测程序,它能够检查字符串中的 ()
、{}
和 []
三种括号是否匹配。项目采用 栈(stack) 这一经典的数据结构来处理括号匹配问题,因为栈的 后进先出(LIFO, Last In First Out) 特性正好适用于括号的嵌套匹配。
2. 实现思路
本项目的核心思想是使用 栈 来存储未匹配的左括号,并在遇到右括号时检查是否匹配,具体流程如下:
- 遍历字符串:逐个读取字符串中的字符。
- 入栈操作:遇到左括号
(
、{
、[
,将其压入栈中。 - 出栈检查:
- 遇到右括号
)
、}
、]
时,检查栈顶元素是否是对应的左括号。 - 若匹配,则弹出栈顶元素继续检查下一个字符。
- 若不匹配或栈为空,则说明括号匹配错误,直接返回
false
。
- 遇到右括号
- 最终检查:
- 遍历完成后,如果栈为空,则说明所有括号正确匹配;
- 如果栈不为空,说明仍然有未匹配的左括号,匹配失败。
为了实现上述逻辑,我们需要设计以下几个核心部分:
- 栈的实现(数组模拟栈操作)
- 括号匹配检查函数
- 主函数用于输入和测试
3. 代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 1000 // 栈的最大容量
// 定义栈结构体
typedef struct {
char data[MAX_SIZE]; // 存储括号
int top; // 栈顶指针
} Stack;
// 初始化栈
void initStack(Stack *s) {
s->top = -1; // 栈顶指针初始化为 -1,表示空栈
}
// 判断栈是否为空
int isEmpty(Stack *s) {
return s->top == -1;
}
// 判断栈是否已满
int isFull(Stack *s) {
return s->top == MAX_SIZE - 1;
}
// 入栈操作
void push(Stack *s, char ch) {
if (isFull(s)) {
printf("错误: 栈已满,无法入栈\n");
return;
}
s->data[++(s->top)] = ch; // 先自增 top,再存入数据
}
// 出栈操作
char pop(Stack *s) {
if (isEmpty(s)) {
printf("错误: 栈为空,无法出栈\n");
return '\0';
}
return s->data[(s->top)--]; // 先取出数据,再自减 top
}
// 获取栈顶元素
char peek(Stack *s) {
if (isEmpty(s)) {
return '\0'; // 空栈返回 '\0' 代表无效字符
}
return s->data[s->top];
}
// 检查括号是否匹配
int isMatchingPair(char left, char right) {
return (left == '(' && right == ')') ||
(left == '{' && right == '}') ||
(left == '[' && right == ']');
}
// 括号匹配检查函数
int isBalanced(char *expr) {
Stack s;
initStack(&s); // 初始化栈
for (int i = 0; i < strlen(expr); i++) {
char ch = expr[i];
// 如果是左括号,压入栈中
if (ch == '(' || ch == '{' || ch == '[') {
push(&s, ch);
}
// 如果是右括号,则检查栈顶是否匹配
else if (ch == ')' || ch == '}' || ch == ']') {
if (isEmpty(&s)) {
return 0; // 栈为空,说明没有匹配的左括号
}
char topChar = pop(&s);
if (!isMatchingPair(topChar, ch)) {
return 0; // 匹配失败
}
}
}
// 遍历完成后,若栈为空,则匹配成功,否则失败
return isEmpty(&s);
}
// 主函数:测试代码
int main() {
char expr[1000];
printf("请输入要检查的表达式: ");
scanf("%s", expr);
if (isBalanced(expr)) {
printf("括号匹配正确!\n");
} else {
printf("括号匹配错误!\n");
}
return 0;
}
4. 代码解读
栈的实现
- 使用
Stack
结构体模拟栈,包含一个数组data[MAX_SIZE]
存储括号,以及一个top
变量记录栈顶索引。 initStack()
负责初始化栈,isEmpty()
和isFull()
用于判断栈状态。push()
用于压入括号,pop()
取出栈顶括号,peek()
获取栈顶但不弹出。
括号匹配检查
isMatchingPair(left, right)
用于检查一对括号是否匹配。isBalanced(expr)
逐个遍历expr
:- 若是左括号,入栈。
- 若是右括号,检查栈顶是否匹配,否则返回错误。
- 遍历完成后,检查栈是否为空。
主函数
scanf("%s", expr);
获取用户输入的字符串。isBalanced(expr)
进行括号匹配检查,输出匹配结果。
5. 项目总结
优点
- 时间复杂度低:本算法只需遍历字符串一次,时间复杂度为
O(n)
。 - 空间复杂度低:使用栈存储左括号,最坏情况下
O(n)
,通常远小于n
。 - 结构清晰:基于栈的实现使代码更直观易懂。
缺点
- 仅支持三种括号:
()
、{}
、[]
,若需扩展至 HTML 标签匹配,则需改进。 - 不考虑其他字符:例如
if (a > b) { return a; }
仍然会被处理,而不会忽略if
语句结构。
改进方向
- 支持 HTML 标签匹配:可使用字符串栈存储标签名称,匹配
<div>
和</div>
这类标签。 - 优化错误提示:当前仅返回
匹配错误
,可以进一步提供错误位置提示。
本项目完整实现了 C 语言括号匹配检测功能,并采用栈数据结构进行优化,适用于编译器、数学表达式解析等应用场景。