括号匹配的意思
假设只允许出现两种括号:圆括号和方括号,其嵌套顺序随意,即不管[([])]或[([])]等都为正确匹配,但是形如([][)就成为错误的匹配。
实现的算法
可以用“期待的紧急程度”的概念来描述:
如 [([][])] 共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 : %sn”, 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/nn”);
getchar();//这个getchar函数是用来接收回车符的,这个回车符是当你在屏幕上输入选项y或n之后敲回车的那个回车产生的。
con = getchar();//这个才是真正的选项y或n
}
return 0;
}
void start()
{
printf(“please input a trial of parensn”);
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 reinputn”);
}
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 %cn”, *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 reinputn”);
}
}
三个文件的下载地址: