3.3.3.1 平衡符号
编译器检查你的程序的语法错误,但是常常由于缺少一个符号(如遗漏一个花括号或是注释起始符)引起编译器列出上百行的诊断,而真正的错误并米有找出。 在这种情况下一个有用的工具就是检验是否每件事情都能成对出现的一个程序。于是,每一右花括号,右方括号及右圆括号比如对应其相应的左括号。序列“[()]”是合法的,但“[())”是错误的。
显然,不值得为此编写一个大型程序,事实上检验这些事情是很容易的。为简单起见,我们仅用圆括号,方括号与花括号进行检验并忽略出现的任何其他字符。 这个简单的算法用到一个栈,诉述如下:
做一个空栈,读取字符直至文件尾。如果字符是一个开放符号,则将其推入栈中,如果字符是一个封闭符号,则当栈空时报错。否则,将栈元素弹出。如果弹出的符号不是对应的开放符号,
则报错。在文件尾,如果栈非空则报错。
你应该能够确信这个算法会正确运行的。很清楚,它是线性的,事实上它只需要对输入进行一趟检验。因此,它是线性的,是相当快的。当报错时,决定如何处理需要做一些附加的工作--例如判断可能的原因!
头文件
#define OPEN_BRACE '{'
#define CLOSE_BRACE '}'
#define OPEN_BRACKET '['
#define CLOSE_BRACKET ']'
#define OPEN_PAREN '('
#define CLOSE_PAREN ')'
// 3.3.3.1 平衡符号
extern int IsSymolsMatch(const char *);
// 是否开放符号
int IsOpenSymbols(const char);
// 是否封闭符号
int IsCloseSymbols(const char);
// 开放/封闭符号是否匹配
int IsMatch(const char, const char);
源文件
/**
* 3.3.3.1 平衡符号
* @param str
*/
int IsSymolsMatch(const char *str) {
Stack S = CreateStack();
char top, curr;
int i, len = strlen(str);
for (i = 0; i < len; i++) {
curr = str[i];
if (IsOpenSymbols(curr)) {
Push(curr, S);
}
if (IsCloseSymbols(curr)) {
top = Top(S);
if ( ! IsMatch(top, curr)) {
return 0;
}
Pop(S);
}
}
if (IsEmptyStack(S)) {
return 1;
}
MakeEmptyStack(S);
return 0;
}
/**
* 是否开放符号
* @param c
* @return
*/
int IsOpenSymbols(const char c) {
return (c == OPEN_BRACE) || (c == OPEN_BRACKET) || (c == OPEN_PAREN);
}
/**
* 是否封闭符号
* @param c
* @return
*/
int IsCloseSymbols(const char c) {
return (c == CLOSE_BRACE) || (c == CLOSE_BRACKET) || (c == CLOSE_PAREN);
}
/**
* 开放/封闭符号是否匹配
* @param c
* @param s
* @return
*/
int IsMatch(const char c, const char s) {
return ((c == OPEN_BRACE) && (s == CLOSE_BRACE)) || ((c == OPEN_BRACKET) && (s == CLOSE_BRACKET)) || ((c == OPEN_PAREN) && (s == CLOSE_PAREN));
}
调用示例 -- 平衡符号
#include <stdio.h>
#include <stdlib.h>
#include "ext/s15/stack.h"
int main(int argc, char** argv) {
char str[] = "{[(ab](cd)(ed)]}";
IsSymolsMatch(str);
return (EXIT_SUCCESS);
}