栈的应用-括号的就近匹配
代码块中,编译器通常会帮我们做符号等一些语法检查,提示在哪些地方语法错了,其中符号的就近匹配是用栈做的;
思路和代码如下:
//就近匹配是对栈的应用,程序中对括号的“就近匹配”用到的就是栈的思想
//1.从第一个字符开始扫描;2.当遇见普通字符的时候忽略;3.当遇见左符号的时候压栈;4.当遇见右符号时从栈顶弹出符号,并进行匹配
// 匹配成功:继续读入下一个字符
// 匹配失败:立即停止并报错
//结束:
// 成功:所有字符扫描完毕,且栈为空
// 失败:匹配失败或所有字符扫描完毕,栈不为空;
//需要说明的的是,压栈和出栈的一些api函数已经在上一篇文章中给出;
#include<iostream>
using namespace std;
#include"LinkStack.h"
int isLeft(char c)//判断是不是左符号
{
int ret = 0;
switch (c)
{
case'<':
case'(':
case'[':
case'{':
case'\'':
case'\"':
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
int isRight(char c)//判断是不是右符号
{
int ret = 0;
switch (c)
{
case'>':
case')':
case']':
case'}':
case'\'':
case'\"':
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
int match(char left, char right)//左符号和右符号匹配
{
int ret = 0;
switch (left)
{
case'<':
ret = (right == '>');
break;
case'(':
ret = (right == ')');
break;
case'[':
ret = (right == ']');
break;
case'{':
ret = (right == '}');
break;
case'\'':
ret = (right == '\'');
break;
case'\"':
ret = (right == '\"');
}
return ret;
}
int scanner(const char* code)
{
LinkStack* stack = LinkStack_Create();
int ret = 0;
int i = 0;
while (code[i] != '\0')//扫描字符串是不是已经到了末尾
{
if (isLeft(code[i]))//判断是不是左符号
{
LinkStack_Push(stack, (void*)(code + i));//如果是左符号,压栈
}
if (isRight(code[i]))//判断是不是右符号
{
char* c = (char*)LinkStack_Pop(stack);//如果是右符号,栈中的左符号出栈
if ((c == NULL) || !match(*c, code[i]))//如果c为空或者左右不匹配,打印"does not match",并直接退出
{
cout << code[i] << "does not match" << endl;
ret = 0;
break;
}
}
i++;
}
if ((LinkStack_Size(stack) == 0) && (code[i] == '\0'))//如果栈为空且所有字符都已经扫描完毕,打印"succeed"之后退出程序
{
cout << "succeed!" << endl;
ret = 1;
}
else
{
cout << "invalid code" << endl;
ret = 0;
}
return ret;
}
int main()
{
const char* code = "#include<stdio.h> int main() {int a[4][4];int(*p)[4];p=a[0];return 0;";
scanner(code);
return 0;
}