堆栈所具有的后进先出的特性使得它在计算机领域中称为十分重要、也是应用十分广泛的数据结构之一。也就是说,实际应用中只要问题满足“后进先出”的原则,就可以使用堆栈。比如说在编译和运行的过程中,就需要利用堆栈进行语法检查(包括括号是否配对)和表达是求值。接下来我们就来探讨编译过程中计算机是如何对程序进行符号的匹配的。
问题描述
我们都知道C语言的语法中,很多符号都是成对出现的,比如说“()”、“{ }”、“ 【】”、“<>”。或者说是这样的“ { < ( ) > } ”.
然而像这样 “{ < } >” 、 " { { } "、 “{}} ” 等都是不符合语法的,都是错误的。基本上所有的编译器都有检查符号匹配性的功能,那么他们是如何工作的呢?
问题分析
所有的程序都可以看成是字符串组成的,所以我们可以将他们分成一个一个的字符,只需要将左右括号拿出来对比就行了,其他的字符可以不需要管。
例如一个字符串:" { while ( !Stack_Empty ( top ) ) }”
在这里
1对应6
2对应5
3对应4
只有他们相互匹配才能说不出语法问题。那么我们该怎么做呢?
创建一个栈,然后一个一个读取字符串中所有的字符,遇到左括号将其压入栈中,遇到右括号则将栈中的栈顶元素出栈并进行匹配,否则跳过读取下一个字符。这个是一个大框架。
那么我们就得判断一个字符串中所有的符号是否匹配成功,有以下几点:
- 如果第一个读取的不是左括号则错误,直接返回并提示错误信息
- 如果读取的右括号与栈顶的左括号不匹配,直接返回并提示错误信息
- 如果读取完所有的字符串之后栈中还有多余未匹配的左括号,直接返回并提示错误信息
这就是简单的符号匹配的核心思想。
算法框架
***********************************************************************
该函数用来判断是否为左括号
如果是:返回1
否则:返回0
***********************************************************************
int isLeft(char ch)
{
int ret;
switch (ch)
{
case '<':
case'(':
case'[':
case'{':
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
***********************************************************************
判断是否为右括号
是:返回1
否:返回0
***********************************************************************
int isRight(char ch)
{
int ret;
switch (ch)
{
case']':
case'}':
case')':
case'>':
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
***********************************************************************
该函数用来判断左右符号是否匹配
是:返回1
否:返回0
***********************************************************************
int check(char Left, char Right)
{
int ret;
switch (Left)
{
case'<':
if (Right == '>')ret = 1;
break;
case'[':
if (Right == ']')ret = 1;
break;
case'{':
if (Right == '}')ret = 1;
break;
case'(':if (Right == ')')ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
***********************************************************************
该函数主要功能是读取字符串,调用判断左、右括号的函数,调用判断是否匹配的函数
判断是否栈中有剩余左括号
如果无错误:返回1
否则:返回0
***********************************************************************
int scanner(char cost[])
{
int i = 0;
int ret = 0;
Stack top = Stack_Inten();
char ch;
while (cost[i] != '\0')
{
if (isLeft(cost[i]))
top = Stack_Push(top, cost[i]);
if (isRight(cost[i]))
{
if (top == NULL)
return (ret = 0);
else
{
top = Stack_Pull(top, &ch);
if (!(ret = check(ch, cost[i])))
return ret;
}
}
i++;
}
if (!Stack_Empty(top))
{
Stack_Free(top);
return (ret = 0);
}
return (ret = 1);
}
总的测试代码(包含栈)
头文件“check.h”
#include<stdio.h>
#include <stdlib.h>
typedef struct Stack_operate
{
char ch;
struct Stack_operate* link;
}Sta, *Stack;
Stack Stack_Inten();
int Stack_Empty(Stack);
int Stack_Len(Stack);
Stack Stack_Push(Stack , char );
Stack Stack_Pull(Stack , char *);
int Stack_Free(Stack );
int isLeft(char );
int isRight(char );
int check(char , char );
int scanner(char cost[]);
void panduan(int );
函数定义
#include"check.h"
Stack Stack_Inten()
{
return NULL;
}
int Stack_Empty(Stack top)
{
return(top == NULL);
}
int Stack_Len(Stack top)
{
int i = 0;
while (top != NULL)
{
top = top->link;
i++;
}
return i;
}
Stack Stack_Push(Stack top, char ch)
{
Stack p;
p = (Stack)malloc(sizeof(Sta));
p->ch = ch;
p->link = top;
top = p;
return top;
}
Stack Stack_Pull(Stack top, char *p_ch)
{
Stack p;
*p_ch = top->ch;
p = top;
top = top->link;
free(p);
return top;
}
int Stack_Free(Stack top)
{
Stack p;
while (top != NULL)
{
p = top;
top = top->link;
free(p);
}
return 1;
}
int isLeft(char ch)
{
int ret;
switch (ch)
{
case '<':
case'(':
case'[':
case'{':
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
int isRight(char ch)
{
int ret;
switch (ch)
{
case']':
case'}':
case')':
case'>':
ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
int check(char Left, char Right)
{
int ret;
switch (Left)
{
case'<':
if (Right == '>')ret = 1;
break;
case'[':
if (Right == ']')ret = 1;
break;
case'{':
if (Right == '}')ret = 1;
break;
case'(':if (Right == ')')ret = 1;
break;
default:
ret = 0;
break;
}
return ret;
}
int scanner(char cost[])
{
int i = 0;
int ret = 0;
Stack top = Stack_Inten();
char ch;
while (cost[i] != '\0')
{
if (isLeft(cost[i]))
top = Stack_Push(top, cost[i]);
if (isRight(cost[i]))
{
if (top == NULL)
return (ret = 0);
else
{
top = Stack_Pull(top, &ch);
if (!(ret = check(ch, cost[i])))
return ret;
}
}
i++;
}
if (!Stack_Empty(top))
{
Stack_Free(top);
return (ret = 0);
}
return (ret = 1);
}
void panduan(int i)
{
if (i = 1)
puts("Right!!!!!");
else
puts("Error!!!!!");
}
主函数等
int main(void)
{
int ret1 = 0;
int ret2 = 0;
char cost1[] = "the bookis< kkko,(slkj(sfd)sdg)agds{}>";
char cost2[] = "lkdjfklajg<<jlksjfio>{}";
ret1 = scanner(cost1);
ret2 = scanner(cost2);
puts("The first string is:");
panduan(ret1);
puts("The second string is:");
panduan(ret2);
return 0;
}
最终结果啦
这个算法到这里就算是结束了。
嗝~