开发括号匹配解析器时,能否用enum优化冗余的if条件判断语句?
括号匹配解析器优化方案
现有需求与问题
开发一款简易括号匹配解析器,核心功能为接收字符串输入,校验小括号、中括号、大括号的开闭逻辑正确性,仅校验括号语法,不需要校验括号内表达式有效性,遍历过程中跳过所有非括号字符。
当前存在的问题是parse函数内的非括号字符判断逻辑冗余丑陋,希望找到更优实现方式,比如使用enum优化逻辑。
现有代码
简化parse函数代码
void parse(char *string) { for (int i = 0; i < strlen(string); i++) { if (string[0] == ')' || string[0] == ']' || string[0] == '}') { printf("ParseError: Statement begins with invalid token '%c'", string[0]); return; } if (string[i] != '(' || string[i] != '[' || string[i] != '{' || string[i] != ')' || string[i] != ']' || string[i] != '}') { continue; } } }
完整程序代码
#include <stdio.h> #include <stdlib.h> #include <string.h> struct Node { char character; struct Node *link; } * top; struct Node *getNewNode(char); void push(char); void pop(void); void parse(char *); void print(void); int main() { top = NULL; char string[100]; char *string_ptr = string; printf("Enter an expression to parse: "); fgets(string, sizeof(string), stdin); parse(string_ptr); print(); } struct Node *getNewNode(char character) { struct Node *newNode = (struct Node *)(malloc(sizeof(struct Node))); newNode->character = character; newNode->link = top; return newNode; } void push(char character) { struct Node *newNode = getNewNode(character); top = newNode; } void pop(void) { struct Node *temp; if (top == NULL) { printf("Stack is empty!"); return; } temp = top; top = top->link; free(temp); temp = NULL; } void print(void) { struct Node *temp = top; while (temp != NULL) { printf("%c", temp->character); temp = temp->link; } } void parse(char *string) { for (int i = 0; i < strlen(string); i++) { if (string[0] == ')' || string[0] == ']' || string[0] == '}') { printf("ParseError: Statement begins with invalid token '%c'", string[0]); return; } if (string[i] != '(' || string[i] != '[' || string[i] != '{' || string[i] != ')' || string[i] != ']' || string[i] != '}' ||) { continue; } } }
现有代码问题梳理
首先修正4个明显问题:
- 语法错误:第二个
if判断末尾多了一个多余的||,会直接触发编译报错,需要先删除 - 逻辑错误:非括号判断的条件使用
||连接所有“不等于括号”的判断,这个条件永远为真,会导致所有字符都被跳过,后续括号校验逻辑永远不会触发,需要把||替换为&& - 性能问题:每次循环都调用
strlen计算字符串长度,会带来O(n²)的不必要性能损耗,建议提前计算字符串长度 - 冗余问题:首字符校验逻辑放在循环内,会重复执行,应该提前到循环外
优化方案
方案1:辅助函数简化判断(轻量场景首选)
如果仅需要括号校验功能,不需要后续扩展其他语法解析,封装一个判断是否为括号的工具函数即可,代码简洁易读:
// 辅助函数:判断字符是否为有效括号 int isBracket(char c) { return c == '(' || c == '[' || c == '{' || c == ')' || c == ']' || c == '}'; }
改造后的parse函数:
void parse(char *string) { // 首字符判断提前到循环外,不需要每次循环都执行 if (string[0] == ')' || string[0] == ']' || string[0] == '}') { printf("ParseError: Statement begins with invalid token '%c'", string[0]); return; } int len = strlen(string); for (int i = 0; i < len; i++) { char curr = string[i]; if (!isBracket(curr)) continue; // 后续括号匹配逻辑:左括号入栈,右括号判断栈顶是否匹配 } }
方案2:enum+查找表优化(适合后续扩展解析器功能)
如果后续要扩展解析器支持更多符号解析,可以用enum定义Token类型,配合查找表快速判断字符类型,后续新增语法类型时修改成本极低:
typedef enum { TOKEN_LEFT_PAREN, TOKEN_RIGHT_PAREN, TOKEN_LEFT_BRACKET, TOKEN_RIGHT_BRACKET, TOKEN_LEFT_BRACE, TOKEN_RIGHT_BRACE, TOKEN_OTHER } TokenType; TokenType getTokenType(char c) { switch(c) { case '(': return TOKEN_LEFT_PAREN; case ')': return TOKEN_RIGHT_PAREN; case '[': return TOKEN_LEFT_BRACKET; case ']': return TOKEN_RIGHT_BRACKET; case '{': return TOKEN_LEFT_BRACE; case '}': return TOKEN_RIGHT_BRACE; default: return TOKEN_OTHER; } }
完整的parse逻辑实现:
void parse(char *string) { TokenType firstType = getTokenType(string[0]); if (firstType >= TOKEN_RIGHT_PAREN && firstType <= TOKEN_RIGHT_BRACE) { printf("ParseError: Statement begins with invalid token '%c'", string[0]); return; } int len = strlen(string); for (int i = 0; i < len; i++) { TokenType type = getTokenType(string[i]); if (type == TOKEN_OTHER) continue; // 左括号直接入栈 if (type < TOKEN_RIGHT_PAREN) { push(string[i]); continue; } // 右括号匹配校验 if (top == NULL) { printf("ParseError: Extra closing bracket '%c'", string[i]); return; } char topChar = top->character; if ((type == TOKEN_RIGHT_PAREN && topChar != '(') || (type == TOKEN_RIGHT_BRACKET && topChar != '[') || (type == TOKEN_RIGHT_BRACE && topChar != '{')) { printf("ParseError: Mismatched bracket '%c'", string[i]); return; } pop(); } // 遍历结束后栈非空说明有未闭合的左括号 if (top != NULL) { printf("ParseError: Unclosed brackets left"); return; } printf("Parse success: All brackets are matched correctly"); }
内容的提问来源于stack exchange,提问作者Anish Sinha
相关产品推荐
相关产品推荐

