You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 14:40:39