两段看似相同的括号检查代码为何表现差异巨大?
括号匹配检查函数的逻辑差异问题
我正在编写一个用于词法分析的括号检查函数,要求判断表达式是否完全被一对匹配的括号包裹(遵循规则<expr> ::= "(" <expr> ")")。比如输入(1+2)时返回true,输入(1+2)*(3+4)时返回false。
目前启用的代码版本运行正常,但注释掉的版本执行异常——通过gdb调试发现,注释版本的for循环每次都会直接返回false,无法正常遍历整个表达式。我原本以为两段代码逻辑一致,想不通为什么表现差异这么大。
代码如下:
bool check_parentheses(int p, int q) { int cnt = 0; int i = p; for(; i <= q; ++i) { if(tokens[i].type == '(') { ++cnt; } else if(tokens[i].type == ')') { --cnt; } if(cnt == 0 && tokens[p].type == '(' && tokens[q].type == ')') {break;} } if(i == q) return true; else return false; return false; // int i = p; // for(; i <= q; ++i) // { // if(tokens[i].type == '(') {++cnt;} // else if(tokens[i].type == ')') {--cnt;} // if(cnt == 0 && tokens[p].type == '(' && tokens[q].type == ')' && i == q) // return true; // else // return false; // } // return false; }
核心逻辑差异分析
两段代码的本质逻辑完全不同:
启用版本:
- 遍历整个表达式,维护括号计数
cnt - 当计数回到0且首尾是括号时,跳出循环
- 最后判断循环结束时的
i是否等于q(即是否是在表达式末尾才让计数回到0),以此确定整个表达式被一对括号完整包裹
- 遍历整个表达式,维护括号计数
注释版本:
在for循环的第一次迭代就会直接返回结果:
初始i=p,此时处理完括号计数后,判断条件cnt == 0 && tokens[p].type == '(' && tokens[q].type == ')' && i == q。除非p=q(单个括号,不符合合法表达式),否则i==q不成立,直接进入else分支返回false,循环根本没有机会继续遍历后续字符。
简单说,注释版本的逻辑是「每遍历一个字符就立即返回结果」,而启用版本是「遍历到符合条件的位置后再统一判断返回」,这就是两者表现天差地别的原因。
修正注释版本的思路
如果想让注释版本的逻辑和启用版本一致,需要把return语句移出循环,只在循环结束后判断条件返回,或者仅在满足特定条件时提前返回,否则继续循环:
bool check_parentheses(int p, int q) { int cnt = 0; int i = p; for(; i <= q; ++i) { if(tokens[i].type == '(') {++cnt;} else if(tokens[i].type == ')') {--cnt;} // 仅当计数回到0且不是遍历到末尾时,提前返回false if(cnt == 0 && i != q) { return false; } } // 循环结束后判断计数是否为0,且首尾是括号 return cnt == 0 && tokens[p].type == '(' && tokens[q].type == ')'; }
内容的提问来源于stack exchange,提问作者Lingardx
相关产品推荐
相关产品推荐

