编译器检查你的程序的语法错误,可是经常因为缺乏一个符号(如遗漏一个花括号或是注释起始符)引发编译器列出上百行的诊断,而真正的错误并米有找出。 在这种状况下一个有用的工具就是检验是否每件事情都能成对出现的一个程序。因而,每一右花括号,右方括号及右圆括号好比对应其相应的左括号。序列“[()]”是合法的,但“[())”是错误的。
显然,不值得为此编写一个大型程序,事实上检验这些事情是很容易的。为简单起见,咱们仅用圆括号,方括号与花括号进行检验并忽略出现的任何其余字符。 这个简单的算法用到一个栈,诉述以下:
作一个空栈,读取字符直至文件尾。若是字符是一个开放符号,则将其推入栈中,若是字符是一个封闭符号,则当栈空时报错。不然,将栈元素弹出。若是弹出的符号不是对应的开放符号,
则报错。在文件尾,若是栈非空则报错。算法
你应该可以确信这个算法会正确运行的。很清楚,它是线性的,事实上它只须要对输入进行一趟检验。所以,它是线性的,是至关快的。当报错时,决定如何处理须要作一些附加的工做--例如判断可能的缘由!工具
#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); }