几乎所有的编译器都具有检测括号是否匹配的能力,那么如何实现编译器中的符号成对检测呢?
如下字符串:检测括号是否成对匹配。
5+5*(6)+9/3) - (1+3(
这就是一个栈的经典应用场景:就近匹配原则:
算法思路:
- 从第一个字符开始扫描
- 当遇到普通字符时忽略。
- 当遇到左符号时压入栈中
- 当遇到右符号时从栈中弹出栈顶符号,并进行匹配。
- 匹配成功:继续读入下一个字符。
- 匹配失败:立即停止,并报错。
- 结束:
- 成功:所有字符扫描完毕,且栈为空。
总结一句:如果左括号时入栈,右括号时出栈;如果出无所出,则说明不匹配。如果整个字符串遍历完,栈中还有数据这说明,有一个孤立不成对符号。如果有入也有出,且最后都出去了,那么说明都匹配上了。
首先建立栈的数据结构:定义栈的结构体并实现如下:
#pragma once
#include<stdlib.h>
#include<string.h>
#ifdef __cplusplus
extern "C"{
#endif
#define MAX 1024
//顺序栈数据结构
struct SStack
{
void *data[MAX]; //存放数据的数组
int size;//栈中元素的个数
};
typedef void * SeqStack;
//数组高下标的位置当做栈顶,因为不需要移动数组中的元素在插入和删除中
//初始化
SeqStack Init_SeqStack();
//入栈
void Push_SeqStack(SeqStack stack, void *data);
//出栈
void Pop_SeqStack(SeqStack stack);
//获得栈顶元素
void *Top_SeqStack(SeqStack stack);
//获得栈的大小
int Size_SeqStack(SeqStack stack);
//销毁栈
void Destroy_SeqStack(SeqStack stack);
#ifdef __cplusplus
}
#endif
#include"SeqStack.h"
//初始化
SeqStack Init_SeqStack()
{
struct SStack *stack = malloc(sizeof(struct SStack));
if (NULL == stack)
{
return NULL;
}
//memset(stack->data, 0, sizeof(struct SStack));
stack->size = 0;
for (int i = 0; i < MAX; ++i)
{
stack->data[i] = NULL;
}
return stack;
}
//入栈
void Push_SeqStack(SeqStack stack, void *data)
{
if (NULL == stack)
{
return;
}
if (NULL == data)
{
return;
}
struct SStack *s = (struct SStack *)stack;
if (s->size == MAX)
{
return;
}
s->data[s->size] = data;
s->size++;
}
//出栈
void Pop_SeqStack(SeqStack stack)
{
if (NULL == stack)
{
return;
}
struct SStack *s = (struct SStack *)stack;
if (s->size == 0)
{
return;
}
s->data[s->size - 1] = NULL;
s->size--;
}
//获得栈顶元素
void *Top_SeqStack(SeqStack stack)
{
if (NULL == stack)
{
return NULL;
}
struct SStack *s = (struct SStack *)stack;
if (s->size == 0)
{
return NULL;
}
return s->data[s->size - 1];
}
//获得栈的大小
int Size_SeqStack(SeqStack stack)
{
if (NULL == stack)
{
return -1;
}
struct SStack *s = (struct SStack *)stack;
return s->size;
}
//销毁栈
void Destroy_SeqStack(SeqStack stack)
{
if (NULL == stack)
{
return;
}
free(stack);
}
检测:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include"SeqStack.h"
int IsLeft(char ch)
{
return ch == '(';
}
int IsRight(char ch)
{
return ch == ')';
}
void printError(const char *str,char *errMsg,char *pos)
{
printf("错误信息:%s\n", errMsg);
printf("%s\n",str);
int dis = pos - str;
for (int i = 0; i < dis; ++i)
{
printf(" ");
}
printf("A\n");
}
void test()
{
const char *str = "5+5*(6()+9/3*1)-(1)+3(";
char *p = (char *)str;
//初始化栈
SeqStack stack = Init_SeqStack();
while (*p != '\0')
{
//判断当前字符是否是左括号
if (IsLeft(*p))
{
Push_SeqStack(stack, p);
}
//判断当前字符是否是右括号
if (IsRight(*p))
{
if (Size_SeqStack(stack) > 0)
{
//弹出栈顶元素
Pop_SeqStack(stack);
}
else
{
printError(str,"右括号没有匹配的左括号!",p);
}
}
p++;
}
while (Size_SeqStack(stack) > 0)
{
printError(str,"没有匹配的右括号!",Top_SeqStack(stack));
//弹出栈顶元素
Pop_SeqStack(stack);
}
//销毁栈
Destroy_SeqStack(stack);
stack = NULL;
}
int main(){
test();
char *s = "1 + 2 / 2 - 4";
system("pause");
return EXIT_SUCCESS;
}