C语言实现逆波兰计算器遇段错误问题求助
逆波兰(RNP)计算器段错误问题修复
问题描述
- 输入类似
3 a 3 +时程序正常运行,但仅输入单个a时触发段错误。 - 输入过多运算符(如
3 5 + +)时触发段错误。
问题根源分析
1. stack_pop函数的空栈访问漏洞
当前stack_pop仅检查了栈结构体指针是否为NULL,但未校验栈顶元素指针astack->top是否为空。当栈为空时,直接访问astack->top->value会触发空指针解引用,这就是运算符过多时段错误的直接原因。
2. 非数字token的处理逻辑缺失
输入单个非数字token(如a)时,process函数既不执行压栈也不处理运算,但后续若存在读取栈顶元素的逻辑(比如输出最终结果),会再次触发空指针访问。同时函数末尾的固定日志输出也表明非合法token未被正确忽略。
修复方案
修复stack_pop函数
添加栈空检查,避免非法内存访问:
#include <math.h> // 引入NAN定义 float stack_pop(stack* astack) { float cur; if (astack == NULL || astack->top == NULL) { // 新增栈空判断 cur = NAN; } else { cur = astack->top->value; stack_element *nxt = astack->top->next; free(astack->top); astack->top = nxt; } return cur; }
完善process函数
- 直接忽略非数字、非运算符的token,移除无效日志输出
- 执行运算前检查栈元素数量,防止栈空时弹出NAN后继续运算:
void process(stack* astack, char* token) { if(is_number(token) == 1) { float number = atof(token); stack_push(astack, number); } else if (is_add(token) == 1) { if (astack->top == NULL || astack->top->next == NULL) return; float number1 = stack_pop(astack); float number2 = stack_pop(astack); stack_push(astack, (number1 + number2)); } else if(is_sub(token) == 1) { if (astack->top == NULL || astack->top->next == NULL) return; float number1 = stack_pop(astack); float number2 = stack_pop(astack); stack_push(astack, (number2 - number1)); } else if(is_mult(token) == 1) { if (astack->top == NULL || astack->top->next == NULL) return; float number1 = stack_pop(astack); float number2 = stack_pop(astack); stack_push(astack, (number1 * number2)); } // 非合法token直接忽略 return; }
补充结果输出的安全校验
在程序末尾输出最终结果时,必须检查栈状态:
void print_final_result(stack* astack) { if (astack == NULL || astack->top == NULL) { printf("表达式无效或无结果\n"); return; } float result = stack_pop(astack); if (astack->top != NULL) { printf("表达式存在未处理的多余元素\n"); // 可在此添加剩余栈元素的清理逻辑 } else { printf("计算结果:%.2f\n", result); } }
额外优化建议
- 为
stack结构体添加size字段,直接记录元素数量,替代链式遍历检查栈元素是否足够 - 扩展除法运算符时,需额外检查除数是否为0,避免浮点运算错误
内容的提问来源于stack exchange,提问作者helloworld
相关产品推荐
相关产品推荐

