C语言中缀表达式求值代码编译通过但运行崩溃,求问题排查
中缀表达式求值C代码崩溃问题排查与修复
你的代码崩溃主要是逻辑错误导致的内存越界和栈结构破坏,以下是具体问题和修复方案:
核心错误点与修复
1. popOp函数操作错误的栈指针
这是导致程序崩溃的最直接原因:操作符栈的指针是to,但popOp错误地使用了数字栈的指针tn,直接引发数组越界,触发内存访问错误。
错误代码:
char popOp() { return op[--tn]; }
修复后:
char popOp() { return op[--to]; }
2. 右括号处理逻辑错误
处理)时,while(op[to++]!='(')的写法会提前移动to指针,导致循环中访问错误的栈元素,后续的popOp()还会多弹出一个元素,彻底破坏栈结构。
错误代码:
else if(c==')') { while(op[to++]!='(') { r = actualOperation(numbers, op); pushNum(r); } popOp(); }
修复后:
else if(c==')') { // 循环直到遇到左括号,不提前移动指针 while(op[to] != '(') { r = actualOperation(numbers, op); pushNum(r); } // 弹出左括号即可,无需额外pop popOp(); }
3. 多位数解析逻辑错误
当前代码只会保留多位数的最后一位(比如12会被解析成2),正确逻辑应该是逐位累加构建完整数字。
错误代码:
num = 0; while(isItDigit(c)) { num = isItDigit(c); i++; if(i < strlen(expr)) { c = expr[i]; } else break; }
修复后:
num = 0; while(isItDigit(c)) { num = num * 10 + isItDigit(c); i++; if(i < strlen(expr)) { c = expr[i]; } else break; }
4. isItDigit函数遗漏'0'的处理
函数只覆盖了1-9,导致数字0无法被识别为有效数字,添加对应case即可:
修复后函数:
int isItDigit(char c) { switch(c) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; } return 0; }
5. isOperator函数缺少默认返回值
当输入字符不是运算符时,函数无明确返回值,会返回随机值导致逻辑判断错误,改为返回1/0表示是否为运算符:
修复后函数:
int isOperator(char ch) { switch(ch) { case '+': case '-': case '*': case '/': return 1; // 是运算符返回1 default: return 0; // 不是返回0 } }
修复后的完整代码
//header files #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> //global variables int numbers[50], tn=-1, to=-1; char op[50]; //is it digit? int isItDigit(char c) { switch(c) { case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; } return 0; } //function to push digits void pushNum(int n) { numbers[++tn]=n; } //function to push operators void pushOp(char ch) { op[++to]=ch; } //function to pop digits int popNum() { return numbers[--tn]; } //function to pop operators char popOp() { return op[--to]; } //actual operation int actualOperation(int numbers[50], char op[50]) { int x,y; char opr; x=popNum(); y=popNum(); opr=popOp(); switch(opr) { case '+': return x+y; case '-': return y-x; case '*': return x*y; case '/': if(x==0) { printf("\nCannot divide by zero"); exit(0); } else { return y/x; } } return 0; } //function to check if character is an operator or not int isOperator(char ch) { switch(ch) { case '+': case '-': case '*': case '/': return 1; default: return 0; } } //precedence of the operators int precedence(char ch) { switch (ch) { case '+': return 1; case '-': return 1; case '*': return 2; case '/': return 2; case '^': return 3; } return -1; } //to evaluate an infix expression int evaluateInfix(char expr[50]) { int i, num, output, r; char c; for(i=0;expr[i]!=0;i++) { c = expr[i]; if(isItDigit(c)!=0) { num = 0; while(isItDigit(c)) { num = num * 10 + isItDigit(c); i++; if(i < strlen(expr)) { c = expr[i]; } else break; } i--; pushNum(num); } else if(c=='(') { pushOp(c); } else if(c==')') { while(op[to] != '(') { r = actualOperation(numbers, op); pushNum(r); } popOp(); } else if(isOperator(c)) { while(to!=-1 && precedence(c)<=precedence(op[to])) { output = actualOperation(numbers, op); pushNum(output); } pushOp(c); } } while(to!=-1) { output = actualOperation(numbers, op); pushNum(output); } return popNum(); } //main function int main() { char expr[50] = "(7-2)+(3*4)"; int ans = evaluateInfix(expr); printf("Answer = %d", ans); return 0; }
运行修复后的代码,输入(7-2)+(3*4)会输出Answer = 17,符合预期。
内容的提问来源于stack exchange,提问作者Alexa Mau
相关产品推荐
相关产品推荐

