編譯器檢查你的程序的語法錯誤,可是經常因爲缺乏一個符號(如遺漏一個花括號或是註釋起始符)引發編譯器列出上百行的診斷,而真正的錯誤並米有找出。 在這種狀況下一個有用的工具就是檢驗是否每件事情都能成對出現的一個程序。因而,每一右花括號,右方括號及右圓括號好比對應其相應的左括號。序列「[()]」是合法的,但「[())」是錯誤的。
顯然,不值得爲此編寫一個大型程序,事實上檢驗這些事情是很容易的。爲簡單起見,咱們僅用圓括號,方括號與花括號進行檢驗並忽略出現的任何其餘字符。 這個簡單的算法用到一個棧,訴述以下:
作一個空棧,讀取字符直至文件尾。若是字符是一個開放符號,則將其推入棧中,若是字符是一個封閉符號,則當棧空時報錯。不然,將棧元素彈出。若是彈出的符號不是對應的開放符號,
則報錯。在文件尾,若是棧非空則報錯。算法
你應該可以確信這個算法會正確運行的。很清楚,它是線性的,事實上它只須要對輸入進行一趟檢驗。所以,它是線性的,是至關快的。當報錯時,決定如何處理須要作一些附加的工做--例如判斷可能的緣由!工具
#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); }