用栈实现括号匹配

来源:互联网 发布:我想在淘宝上卖东西 编辑:程序博客网 时间:2024/06/07 03:04

括号匹配的意思

假设只允许出现两种括号:圆括号和方括号,其嵌套顺序随意,即不管[([])]或[([])]等都为正确匹配,但是形如([][)就成为错误的匹配。

实现的算法

可以用“期待的紧急程度”的概念来描述:

如 [([][])] 共8个括号,从左往右依次标代号为1-8,即第一个[代号为1,第二个(代号为2,第三个[代号为3,依次类推

当计算机收到了第一个括号后,期待它与第八个括号匹配,然而等来的却是第二个括号,此时第一个括号‘[’只能暂时靠边,第二个括号的急迫程度又大于第一个括号,期待与之匹配的第七个括号的到来,然而却等来了第三个括号,这时第二个括号又要暂时靠边,第三个括号的急迫程度比第二个括号大,期待与之匹配的第四个括号的到来,第四个括号到来后与第三个括号相匹配,所以第三个括号的急迫就解决了。此时急迫程度最大的变成了第二个括号了,依次类推下去。

啊,我估计各位看完上面一小段的描述之后,可能觉得天花乱坠,云里雾里的。下面就用比较通俗的语言来说一下。

代码的设计思路:

首先计算机接收一串括号表达式,如[([][])],这时一个一个括号的检查。

1.建立一个空栈,用于存放左括号和表达相应左括号的急迫程度,栈顶的左括号的急迫程度为1,其他非栈顶左括号的急迫程度为0,显然栈顶左括号的急迫程度大于非栈顶的左括号急迫程度;

2.若第一个括号是左括号,不管是‘(’还是‘[’,都被压栈,急迫度为1,进入第三步;若第一个括号为右括号,不管是‘)’还是‘]’,就是错误的。因为栈顶没有与之相匹配的左括号,此时弹出出错提示,重新进入第一步;

3.若第二个括号为左括号,则被压栈,急迫度为1,刚刚压栈的左括号急迫度变为0,进入第四步;若为右括号,则查看是否与栈顶的左括号相匹配,若匹配成功,则删除栈顶左括号,若匹配失败,则弹出出错提示,重新进入第一步;

4.依次类推下去

总而言之一句话:是左括号的,压栈,急迫度为1,是右括号的,则看其是否与栈顶的左括号相匹配,若匹配,则删除栈顶括号,若不匹配,出错。

 

代码:

1.match_pa.h

//Headfile
//    match paren
//History
//    Xinspace    5 Mar    First release

#ifndef xinspace_
#define xinspace_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/ip.h>

#include <pthread.h>

#define error_show(function)    \
do  \
{   \
fprintf(stderr, “in file:%s, in function:%s, at line %d, %s : %s\n”, __FILE__, __FUNCTION__, __LINE__, function, strerror(errno));    \
exit(-1);   \
}while(0)

#define MAX 10
void start(); //开始函数,包含在main函数内
void judge(char **st, char *sb, char pa);//判断一个右括号是否与栈顶的左括号匹配的函数,char **st是栈顶左括号指针的地址,sb是栈底指针,pa表示一个右括号

char *create_stack();//创建栈
char pop(char *st, char *sb);//出栈
void push(char *st, char pa);//压栈

#endif

 

2.主函数 main.c

//Program
//    paren match
//History
//    Xinspace    5 Mar    First release

#include “match_pa.h”

int main(void)
{
char con = ‘y’;//这是一个选项,y表示再执行一遍程序,n表示不执行程序了,退出

while(1)
{
if(con == ‘y’ || con == ‘Y’)//如果选项为y,则执行start函数
start();
else//否则,退出程序
{
printf(“you quit!\n”);
break;
}

fflush(NULL);
printf(“continue? y/n\n”);
getchar();//这个getchar函数是用来接收回车符的,这个回车符是当你在屏幕上输入选项y或n之后敲回车的那个回车产生的。
con = getchar();//这个才是真正的选项y或n
}

return 0;
}

void start()
{
printf(“please input a trial of parens\n”);
char array[MAX*2];    //用来保存一串括号表达式
scanf(“%s”, array);

char *sp, *st, *sb;//sp是指栈底指针,st是栈顶指针,sb是栈底指针
int count = 0;//括号的数量,大于等于0小于strlen(array)
sp = create_stack();//创建栈
st = sb = sp;

while(count < strlen(array))
{
switch(array[count])
{
case ‘(‘://如果是左括号,则压栈
case ‘[':
push(st++, array[count]);
break;
case ‘)’://如果是右括号,则先检查是否与栈顶的左括号匹配,如果不匹配,则出错,若匹配,则继续
judge(&st, sb, ‘)’);
break;
case ‘]’:
judge(&st, sb, ‘]’);
break;
default:
fprintf(stderr, “wrong paren!please reinput\n”);
}

count++;
}
if(st != sb) //如果出错了,即左右括号不匹配的时候,栈中肯定还存在一些左括号没有被匹配,即st与sb不相等,把这些括号依次出栈打印到屏幕上
{
printf(“the paren stack is still left(right to left):”);
while(st != sb)
{
putchar(pop(–st, sb));
}
putchar(10);
}
}

 

3.附加文件match_pa.c

//Program
//    match paren
//History
//    Xinspace    5 Mar    First release
//

#include “match_pa.h”

char *create_stack()//创建栈
{
char *sp = (char *)malloc(sizeof(char) * MAX);
if(!sp)
error_show(“malloc”);

return sp;
}

void push(char *st, char pa)//压栈
{
*st = pa;
//    printf(“insert %c\n”, *st);
}

char pop(char *st, char *sb)//出栈
{
if(st < sb)
{
fprintf(stderr, “stack is NULL!\n”);
exit(1);
}

return *st;
}

void judge(char **st, char *sb, char pa)//判断一个右括号是否与栈顶的左括号匹配
{
if(pa == ‘)’)
{
if(pop(*st – 1, sb) == ‘(‘)
pop(–*st, sb);
else
{
fprintf(stderr, “before ‘)’ must be ‘(‘, but your is %c!\n”, pop(*st – 1, sb));
return;
}
}
else if(pa == ‘]’)
{
if(pop(*st – 1, sb) == ‘[')
pop(--*st, sb);
else
{
fprintf(stderr, "before ']‘ must be ‘[‘, but your is %c!\n”, pop(*st – 1, sb));
return;
}
}
else
{
fprintf(stderr, “paren wrong!please reinput\n”);
}
}

 

更多文章请见blog.xinspace.name

三个文件的下载地址:

match_pa.h

main.c

match_pa.c

原创粉丝点击